source: src/ResolvExpr/Resolver.cc @ b9fe89b

ast-experimental
Last change on this file since b9fe89b was b9fe89b, checked in by Michael Brooks <mlbrooks@…>, 16 months ago

Make the symbol table's error-checking times explicit.

Previously, error checking happened on all WithSymbolTable? uses. Error checking means having a symbol-table add operation potentially cause a user-visible error report. Now, this only happens on the resolver pass's symbol table, while other passes' run in an "assert no errors can happen" mode.

An "ignore errors for now" mode is implemented too, which will be used in upcoming commits, for pre-resolver passes that use the symbol table.

  • Property mode set to 100644
File size: 77.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Resolver.cc --
8//
9// Author           : Aaron B. Moss
10// Created On       : Sun May 17 12:17:01 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Apr 20 10:41:00 2022
13// Update Count     : 248
14//
15
16#include <cassert>                       // for strict_dynamic_cast, assert
17#include <memory>                        // for allocator, allocator_traits<...
18#include <tuple>                         // for get
19#include <vector>                        // for vector
20
21#include "Alternative.h"                 // for Alternative, AltList
22#include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
23#include "Candidate.hpp"
24#include "CandidateFinder.hpp"
25#include "CurrentObject.h"               // for CurrentObject
26#include "RenameVars.h"                  // for RenameVars, global_renamer
27#include "Resolver.h"
28#include "ResolveTypeof.h"
29#include "ResolvMode.h"                  // for ResolvMode
30#include "typeops.h"                     // for extractResultType
31#include "Unify.h"                       // for unify
32#include "CompilationState.h"
33#include "AST/Chain.hpp"
34#include "AST/Decl.hpp"
35#include "AST/Init.hpp"
36#include "AST/Pass.hpp"
37#include "AST/Print.hpp"
38#include "AST/SymbolTable.hpp"
39#include "AST/Type.hpp"
40#include "Common/Eval.h"                 // for eval
41#include "Common/Iterate.hpp"            // for group_iterate
42#include "Common/PassVisitor.h"          // for PassVisitor
43#include "Common/SemanticError.h"        // for SemanticError
44#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
45#include "Common/ToString.hpp"           // for toCString
46#include "InitTweak/GenInit.h"
47#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
48#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
49#include "SymTab/Autogen.h"              // for SizeType
50#include "SymTab/Indexer.h"              // for Indexer
51#include "SymTab/Mangler.h"              // for Mangler
52#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
53#include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
54#include "SynTree/Initializer.h"         // for ConstructorInit, SingleInit
55#include "SynTree/Statement.h"           // for ForStmt, Statement, BranchStmt
56#include "SynTree/Type.h"                // for Type, BasicType, PointerType
57#include "SynTree/TypeSubstitution.h"    // for TypeSubstitution
58#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
59#include "Tuples/Tuples.h"
60#include "Validate/FindSpecialDecls.h"   // for SizeType
61
62using namespace std;
63
64namespace ResolvExpr {
65        struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
66                Resolver_old() {}
67                Resolver_old( const SymTab::Indexer & other ) {
68                        indexer = other;
69                }
70
71                void previsit( FunctionDecl * functionDecl );
72                void postvisit( FunctionDecl * functionDecl );
73                void previsit( ObjectDecl * objectDecll );
74                void previsit( EnumDecl * enumDecl );
75                void previsit( StaticAssertDecl * assertDecl );
76
77                void previsit( ArrayType * at );
78                void previsit( PointerType * at );
79
80                void previsit( ExprStmt * exprStmt );
81                void previsit( AsmExpr * asmExpr );
82                void previsit( AsmStmt * asmStmt );
83                void previsit( IfStmt * ifStmt );
84                void previsit( WhileDoStmt * whileDoStmt );
85                void previsit( ForStmt * forStmt );
86                void previsit( SwitchStmt * switchStmt );
87                void previsit( CaseStmt * caseStmt );
88                void previsit( BranchStmt * branchStmt );
89                void previsit( ReturnStmt * returnStmt );
90                void previsit( ThrowStmt * throwStmt );
91                void previsit( CatchStmt * catchStmt );
92                void postvisit( CatchStmt * catchStmt );
93                void previsit( WaitForStmt * stmt );
94
95                void previsit( SingleInit * singleInit );
96                void previsit( ListInit * listInit );
97                void previsit( ConstructorInit * ctorInit );
98          private:
99                typedef std::list< Initializer * >::iterator InitIterator;
100
101                template< typename PtrType >
102                void handlePtrType( PtrType * type );
103
104                void fallbackInit( ConstructorInit * ctorInit );
105
106                Type * functionReturn = nullptr;
107                CurrentObject currentObject = nullptr;
108                bool inEnumDecl = false;
109        };
110
111        struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
112                void previsit( FunctionDecl * );
113                void previsit( WithStmt * );
114
115                void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
116        };
117
118        void resolve( std::list< Declaration * > translationUnit ) {
119                PassVisitor<Resolver_old> resolver;
120                acceptAll( translationUnit, resolver );
121        }
122
123        void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
124                PassVisitor<Resolver_old> resolver( indexer );
125                maybeAccept( decl, resolver );
126        }
127
128        namespace {
129                struct DeleteFinder_old : public WithShortCircuiting    {
130                        DeletedExpr * delExpr = nullptr;
131                        void previsit( DeletedExpr * expr ) {
132                                if ( delExpr ) visit_children = false;
133                                else delExpr = expr;
134                        }
135
136                        void previsit( Expression * ) {
137                                if ( delExpr ) visit_children = false;
138                        }
139                };
140        }
141
142        DeletedExpr * findDeletedExpr( Expression * expr ) {
143                PassVisitor<DeleteFinder_old> finder;
144                expr->accept( finder );
145                return finder.pass.delExpr;
146        }
147
148        namespace {
149                struct StripCasts_old {
150                        Expression * postmutate( CastExpr * castExpr ) {
151                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
152                                        // generated cast is to the same type as its argument, so it's unnecessary -- remove it
153                                        Expression * expr = castExpr->arg;
154                                        castExpr->arg = nullptr;
155                                        std::swap( expr->env, castExpr->env );
156                                        return expr;
157                                }
158                                return castExpr;
159                        }
160
161                        static void strip( Expression *& expr ) {
162                                PassVisitor<StripCasts_old> stripper;
163                                expr = expr->acceptMutator( stripper );
164                        }
165                };
166
167                void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
168                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
169                        env.makeSubstitution( *expr->env );
170                        StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
171                }
172
173                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
174                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
175                                if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
176                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
177                                        expr = castExpr->arg;
178                                        castExpr->arg = nullptr;
179                                        std::swap( expr->env, castExpr->env );
180                                        delete castExpr;
181                                }
182                        }
183                }
184        } // namespace
185
186        namespace {
187                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
188                        assertf( untyped, "expected a non-null expression." );
189
190                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
191                        static unsigned recursion_level = 0;
192
193                        ++recursion_level;
194                        TypeEnvironment env;
195                        AlternativeFinder finder( indexer, env );
196                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
197                        --recursion_level;
198
199                        #if 0
200                        if ( finder.get_alternatives().size() != 1 ) {
201                                std::cerr << "untyped expr is ";
202                                untyped->print( std::cerr );
203                                std::cerr << std::endl << "alternatives are:";
204                                for ( const Alternative & alt : finder.get_alternatives() ) {
205                                        alt.print( std::cerr );
206                                } // for
207                        } // if
208                        #endif
209
210                        // produce filtered list of alternatives
211                        AltList candidates;
212                        for ( Alternative & alt : finder.get_alternatives() ) {
213                                if ( pred( alt ) ) {
214                                        candidates.push_back( std::move( alt ) );
215                                }
216                        }
217
218                        // produce invalid error if no candidates
219                        if ( candidates.empty() ) {
220                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
221                        }
222
223                        // search for cheapest candidate
224                        AltList winners;
225                        bool seen_undeleted = false;
226                        for ( unsigned i = 0; i < candidates.size(); ++i ) {
227                                int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
228
229                                if ( c > 0 ) continue; // skip more expensive than winner
230
231                                if ( c < 0 ) {
232                                        // reset on new cheapest
233                                        seen_undeleted = ! findDeletedExpr( candidates[i].expr );
234                                        winners.clear();
235                                } else /* if ( c == 0 ) */ {
236                                        if ( findDeletedExpr( candidates[i].expr ) ) {
237                                                // skip deleted expression if already seen one equivalent-cost not
238                                                if ( seen_undeleted ) continue;
239                                        } else if ( ! seen_undeleted ) {
240                                                // replace list of equivalent-cost deleted expressions with one non-deleted
241                                                winners.clear();
242                                                seen_undeleted = true;
243                                        }
244                                }
245
246                                winners.emplace_back( std::move( candidates[i] ) );
247                        }
248
249                        // promote alternative.cvtCost to .cost
250                        // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
251                        for ( Alternative& winner : winners ) {
252                                winner.cost = winner.cvtCost;
253                        }
254
255                        // produce ambiguous errors, if applicable
256                        if ( winners.size() != 1 ) {
257                                std::ostringstream stream;
258                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
259                                untyped->print( stream );
260                                stream << " Alternatives are:\n";
261                                printAlts( winners, stream, 1 );
262                                SemanticError( untyped->location, stream.str() );
263                        }
264
265                        // single selected choice
266                        Alternative& choice = winners.front();
267
268                        // fail on only expression deleted
269                        if ( ! seen_undeleted ) {
270                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
271                        }
272
273                        // xxx - check for ambiguous expressions
274
275                        // output selected choice
276                        alt = std::move( choice );
277                }
278
279                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
280                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
281                        if ( ! untyped ) return;
282                        Alternative choice;
283                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
284                        finishExpr( choice.expr, choice.env, untyped->env );
285                        delete untyped;
286                        untyped = choice.expr;
287                        choice.expr = nullptr;
288                }
289
290                bool standardAlternativeFilter( const Alternative & ) {
291                        // currently don't need to filter, under normal circumstances.
292                        // in the future, this may be useful for removing deleted expressions
293                        return true;
294                }
295        } // namespace
296
297        // used in resolveTypeof
298        Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
299                TypeEnvironment env;
300                return resolveInVoidContext( expr, indexer, env );
301        }
302
303        Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
304                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
305                // interpretations, an exception has already been thrown.
306                assertf( expr, "expected a non-null expression." );
307
308                CastExpr * untyped = new CastExpr( expr ); // cast to void
309                untyped->location = expr->location;
310
311                // set up and resolve expression cast to void
312                Alternative choice;
313                findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
314                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
315                assert( castExpr );
316                env = std::move( choice.env );
317
318                // clean up resolved expression
319                Expression * ret = castExpr->arg;
320                castExpr->arg = nullptr;
321
322                // unlink the arg so that it isn't deleted twice at the end of the program
323                untyped->arg = nullptr;
324                return ret;
325        }
326
327        void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
328                resetTyVarRenaming();
329                TypeEnvironment env;
330                Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
331                finishExpr( newExpr, env, untyped->env );
332                delete untyped;
333                untyped = newExpr;
334        }
335
336        void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
337                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
338        }
339
340        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
341                assert( untyped && type );
342                // transfer location to generated cast for error purposes
343                CodeLocation location = untyped->location;
344                untyped = new CastExpr( untyped, type );
345                untyped->location = location;
346                findSingleExpression( untyped, indexer );
347                removeExtraneousCast( untyped, indexer );
348        }
349
350        namespace {
351                bool isIntegralType( const Alternative & alt ) {
352                        Type * type = alt.expr->result;
353                        if ( dynamic_cast< EnumInstType * >( type ) ) {
354                                return true;
355                        } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
356                                return bt->isInteger();
357                        } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
358                                return true;
359                        } else {
360                                return false;
361                        } // if
362                }
363
364                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
365                        findKindExpression( untyped, indexer, "condition", isIntegralType );
366                }
367        }
368
369
370        bool isStructOrUnion( const Alternative & alt ) {
371                Type * t = alt.expr->result->stripReferences();
372                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
373        }
374
375        void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
376                PassVisitor<ResolveWithExprs> resolver;
377                acceptAll( translationUnit, resolver );
378        }
379
380        void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
381                for ( Expression *& expr : withExprs )  {
382                        // only struct- and union-typed expressions are viable candidates
383                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
384
385                        // if with expression might be impure, create a temporary so that it is evaluated once
386                        if ( Tuples::maybeImpure( expr ) ) {
387                                static UniqueName tmpNamer( "_with_tmp_" );
388                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
389                                expr = new VariableExpr( tmp );
390                                newStmts.push_back( new DeclStmt( tmp ) );
391                                if ( InitTweak::isConstructable( tmp->type ) ) {
392                                        // generate ctor/dtor and resolve them
393                                        tmp->init = InitTweak::genCtorInit( tmp );
394                                        tmp->accept( *visitor );
395                                }
396                        }
397                }
398        }
399
400        void ResolveWithExprs::previsit( WithStmt * withStmt ) {
401                resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
402        }
403
404        void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
405                {
406                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
407                        // front of the function body.
408                        auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
409                        indexer.addFunctionType( functionDecl->type );
410                        std::list< Statement * > newStmts;
411                        resolveWithExprs( functionDecl->withExprs, newStmts );
412                        if ( functionDecl->statements ) {
413                                functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
414                        } else {
415                                assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
416                        }
417                }
418        }
419
420        void Resolver_old::previsit( ObjectDecl * objectDecl ) {
421                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
422                // class-variable initContext is changed multiple time because the LHS is analysed twice.
423                // The second analysis changes initContext because of a function type can contain object
424                // declarations in the return and parameter types. So each value of initContext is
425                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
426                GuardValue( currentObject );
427                currentObject = CurrentObject( objectDecl->get_type() );
428                if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
429                        // enumerator initializers should not use the enum type to initialize, since
430                        // the enum type is still incomplete at this point. Use signed int instead.
431                        // TODO: BasicType::SignedInt may not longer be true
432                        currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
433                }
434        }
435
436        template< typename PtrType >
437        void Resolver_old::handlePtrType( PtrType * type ) {
438                if ( type->get_dimension() ) {
439                        findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
440                }
441        }
442
443        void Resolver_old::previsit( ArrayType * at ) {
444                handlePtrType( at );
445        }
446
447        void Resolver_old::previsit( PointerType * pt ) {
448                handlePtrType( pt );
449        }
450
451        void Resolver_old::previsit( FunctionDecl * functionDecl ) {
452#if 0
453                std::cerr << "resolver visiting functiondecl ";
454                functionDecl->print( std::cerr );
455                std::cerr << std::endl;
456#endif
457                GuardValue( functionReturn );
458                functionReturn = ResolvExpr::extractResultType( functionDecl->type );
459        }
460
461        void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
462                // default value expressions have an environment which shouldn't be there and trips up
463                // later passes.
464                // xxx - it might be necessary to somehow keep the information from this environment, but I
465                // can't currently see how it's useful.
466                for ( Declaration * d : functionDecl->type->parameters ) {
467                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
468                                if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) {
469                                        delete init->value->env;
470                                        init->value->env = nullptr;
471                                }
472                        }
473                }
474        }
475
476        void Resolver_old::previsit( EnumDecl * ) {
477                // in case we decide to allow nested enums
478                GuardValue( inEnumDecl );
479                inEnumDecl = true;
480        }
481
482        void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
483                findIntegralExpression( assertDecl->condition, indexer );
484        }
485
486        void Resolver_old::previsit( ExprStmt * exprStmt ) {
487                visit_children = false;
488                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
489                findVoidExpression( exprStmt->expr, indexer );
490        }
491
492        void Resolver_old::previsit( AsmExpr * asmExpr ) {
493                visit_children = false;
494                findVoidExpression( asmExpr->operand, indexer );
495        }
496
497        void Resolver_old::previsit( AsmStmt * asmStmt ) {
498                visit_children = false;
499                acceptAll( asmStmt->get_input(), *visitor );
500                acceptAll( asmStmt->get_output(), *visitor );
501        }
502
503        void Resolver_old::previsit( IfStmt * ifStmt ) {
504                findIntegralExpression( ifStmt->condition, indexer );
505        }
506
507        void Resolver_old::previsit( WhileDoStmt * whileDoStmt ) {
508                findIntegralExpression( whileDoStmt->condition, indexer );
509        }
510
511        void Resolver_old::previsit( ForStmt * forStmt ) {
512                if ( forStmt->condition ) {
513                        findIntegralExpression( forStmt->condition, indexer );
514                } // if
515
516                if ( forStmt->increment ) {
517                        findVoidExpression( forStmt->increment, indexer );
518                } // if
519        }
520
521        void Resolver_old::previsit( SwitchStmt * switchStmt ) {
522                GuardValue( currentObject );
523                findIntegralExpression( switchStmt->condition, indexer );
524
525                currentObject = CurrentObject( switchStmt->condition->result );
526        }
527
528        void Resolver_old::previsit( CaseStmt * caseStmt ) {
529                if ( caseStmt->condition ) {
530                        std::list< InitAlternative > initAlts = currentObject.getOptions();
531                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
532                        // must remove cast from case statement because RangeExpr cannot be cast.
533                        Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
534                        findSingleExpression( newExpr, indexer );
535                        // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
536                        // Ideally we would perform the conversion internally here.
537                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
538                                newExpr = castExpr->arg;
539                                castExpr->arg = nullptr;
540                                std::swap( newExpr->env, castExpr->env );
541                                delete castExpr;
542                        }
543                        caseStmt->condition = newExpr;
544                }
545        }
546
547        void Resolver_old::previsit( BranchStmt * branchStmt ) {
548                visit_children = false;
549                // must resolve the argument for a computed goto
550                if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
551                        if ( branchStmt->computedTarget ) {
552                                // computed goto argument is void *
553                                findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer );
554                        } // if
555                } // if
556        }
557
558        void Resolver_old::previsit( ReturnStmt * returnStmt ) {
559                visit_children = false;
560                if ( returnStmt->expr ) {
561                        findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer );
562                } // if
563        }
564
565        void Resolver_old::previsit( ThrowStmt * throwStmt ) {
566                visit_children = false;
567                // TODO: Replace *exception type with &exception type.
568                if ( throwStmt->get_expr() ) {
569                        const StructDecl * exception_decl = indexer.lookupStruct( "__cfaehm_base_exception_t" );
570                        assert( exception_decl );
571                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
572                        findSingleExpression( throwStmt->expr, exceptType, indexer );
573                }
574        }
575
576        void Resolver_old::previsit( CatchStmt * catchStmt ) {
577                // Until we are very sure this invarent (ifs that move between passes have then)
578                // holds, check it. This allows a check for when to decode the mangling.
579                if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) {
580                        assert( ifStmt->then );
581                }
582                // Encode the catchStmt so the condition can see the declaration.
583                if ( catchStmt->cond ) {
584                        IfStmt * ifStmt = new IfStmt( catchStmt->cond, nullptr, catchStmt->body );
585                        catchStmt->cond = nullptr;
586                        catchStmt->body = ifStmt;
587                }
588        }
589
590        void Resolver_old::postvisit( CatchStmt * catchStmt ) {
591                // Decode the catchStmt so everything is stored properly.
592                IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body );
593                if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
594                        assert( ifStmt->condition );
595                        assert( ifStmt->else_ );
596                        catchStmt->cond = ifStmt->condition;
597                        catchStmt->body = ifStmt->else_;
598                        ifStmt->condition = nullptr;
599                        ifStmt->else_ = nullptr;
600                        delete ifStmt;
601                }
602        }
603
604        template< typename iterator_t >
605        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
606                while( it != end && !(*it)->get_type()->get_mutex() ) {
607                        it++;
608                }
609
610                return it != end;
611        }
612
613        void Resolver_old::previsit( WaitForStmt * stmt ) {
614                visit_children = false;
615
616                // Resolve all clauses first
617                for( auto& clause : stmt->clauses ) {
618
619                        TypeEnvironment env;
620                        AlternativeFinder funcFinder( indexer, env );
621
622                        // Find all alternatives for a function in canonical form
623                        funcFinder.findWithAdjustment( clause.target.function );
624
625                        if ( funcFinder.get_alternatives().empty() ) {
626                                stringstream ss;
627                                ss << "Use of undeclared indentifier '";
628                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
629                                ss << "' in call to waitfor";
630                                SemanticError( stmt->location, ss.str() );
631                        }
632
633                        if(clause.target.arguments.empty()) {
634                                SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
635                        }
636
637                        // Find all alternatives for all arguments in canonical form
638                        std::vector< AlternativeFinder > argAlternatives;
639                        funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
640
641                        // List all combinations of arguments
642                        std::vector< AltList > possibilities;
643                        combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
644
645                        AltList                func_candidates;
646                        std::vector< AltList > args_candidates;
647
648                        // For every possible function :
649                        //      try matching the arguments to the parameters
650                        //      not the other way around because we have more arguments than parameters
651                        SemanticErrorException errors;
652                        for ( Alternative & func : funcFinder.get_alternatives() ) {
653                                try {
654                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
655                                        if( !pointer ) {
656                                                SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
657                                        }
658
659                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
660                                        if( !function ) {
661                                                SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
662                                        }
663
664
665                                        {
666                                                auto param     = function->parameters.begin();
667                                                auto param_end = function->parameters.end();
668
669                                                if( !advance_to_mutex( param, param_end ) ) {
670                                                        SemanticError(function, "candidate function not viable: no mutex parameters\n");
671                                                }
672                                        }
673
674                                        Alternative newFunc( func );
675                                        // Strip reference from function
676                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
677
678                                        // For all the set of arguments we have try to match it with the parameter of the current function alternative
679                                        for ( auto & argsList : possibilities ) {
680
681                                                try {
682                                                        // Declare data structures need for resolution
683                                                        OpenVarSet openVars;
684                                                        AssertionSet resultNeed, resultHave;
685                                                        TypeEnvironment resultEnv( func.env );
686                                                        makeUnifiableVars( function, openVars, resultNeed );
687                                                        // add all type variables as open variables now so that those not used in the parameter
688                                                        // list are still considered open.
689                                                        resultEnv.add( function->forall );
690
691                                                        // Load type variables from arguemnts into one shared space
692                                                        simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
693
694                                                        // Make sure we don't widen any existing bindings
695                                                        resultEnv.forbidWidening();
696
697                                                        // Find any unbound type variables
698                                                        resultEnv.extractOpenVars( openVars );
699
700                                                        auto param     = function->parameters.begin();
701                                                        auto param_end = function->parameters.end();
702
703                                                        int n_mutex_param = 0;
704
705                                                        // For every arguments of its set, check if it matches one of the parameter
706                                                        // The order is important
707                                                        for( auto & arg : argsList ) {
708
709                                                                // Ignore non-mutex arguments
710                                                                if( !advance_to_mutex( param, param_end ) ) {
711                                                                        // We ran out of parameters but still have arguments
712                                                                        // this function doesn't match
713                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
714                                                                }
715
716                                                                n_mutex_param++;
717
718                                                                // Check if the argument matches the parameter type in the current scope
719                                                                if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
720                                                                        // Type doesn't match
721                                                                        stringstream ss;
722                                                                        ss << "candidate function not viable: no known convertion from '";
723                                                                        (*param)->get_type()->print( ss );
724                                                                        ss << "' to '";
725                                                                        arg.expr->get_result()->print( ss );
726                                                                        ss << "' with env '";
727                                                                        resultEnv.print(ss);
728                                                                        ss << "'\n";
729                                                                        SemanticError( function, ss.str() );
730                                                                }
731
732                                                                param++;
733                                                        }
734
735                                                        // All arguments match !
736
737                                                        // Check if parameters are missing
738                                                        if( advance_to_mutex( param, param_end ) ) {
739                                                                do {
740                                                                        n_mutex_param++;
741                                                                        param++;
742                                                                } while( advance_to_mutex( param, param_end ) );
743
744                                                                // We ran out of arguments but still have parameters left
745                                                                // this function doesn't match
746                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
747                                                        }
748
749                                                        // All parameters match !
750
751                                                        // Finish the expressions to tie in the proper environments
752                                                        finishExpr( newFunc.expr, resultEnv );
753                                                        for( Alternative & alt : argsList ) {
754                                                                finishExpr( alt.expr, resultEnv );
755                                                        }
756
757                                                        // This is a match store it and save it for later
758                                                        func_candidates.push_back( newFunc );
759                                                        args_candidates.push_back( argsList );
760
761                                                }
762                                                catch( SemanticErrorException & e ) {
763                                                        errors.append( e );
764                                                }
765                                        }
766                                }
767                                catch( SemanticErrorException & e ) {
768                                        errors.append( e );
769                                }
770                        }
771
772                        // Make sure we got the right number of arguments
773                        if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
774                        if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
775                        if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
776                        if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
777                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
778
779                        // Swap the results from the alternative with the unresolved values.
780                        // Alternatives will handle deletion on destruction
781                        std::swap( clause.target.function, func_candidates.front().expr );
782                        for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
783                                std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
784                        }
785
786                        // Resolve the conditions as if it were an IfStmt
787                        // Resolve the statments normally
788                        findSingleExpression( clause.condition, this->indexer );
789                        clause.statement->accept( *visitor );
790                }
791
792
793                if( stmt->timeout.statement ) {
794                        // Resolve the timeout as an size_t for now
795                        // Resolve the conditions as if it were an IfStmt
796                        // Resolve the statments normally
797                        findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
798                        findSingleExpression( stmt->timeout.condition, this->indexer );
799                        stmt->timeout.statement->accept( *visitor );
800                }
801
802                if( stmt->orelse.statement ) {
803                        // Resolve the conditions as if it were an IfStmt
804                        // Resolve the statments normally
805                        findSingleExpression( stmt->orelse.condition, this->indexer );
806                        stmt->orelse.statement->accept( *visitor );
807                }
808        }
809
810        bool isCharType( Type * t ) {
811                if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
812                        return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
813                                bt->get_kind() == BasicType::UnsignedChar;
814                }
815                return false;
816        }
817
818        void Resolver_old::previsit( SingleInit * singleInit ) {
819                visit_children = false;
820                // resolve initialization using the possibilities as determined by the currentObject cursor
821                Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() );
822                findSingleExpression( newExpr, indexer );
823                InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
824
825                // move cursor to the object that is actually initialized
826                currentObject.setNext( initExpr->get_designation() );
827
828                // discard InitExpr wrapper and retain relevant pieces
829                newExpr = initExpr->expr;
830                initExpr->expr = nullptr;
831                std::swap( initExpr->env, newExpr->env );
832                // InitExpr may have inferParams in the case where the expression specializes a function
833                // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
834                // sufficient.
835                newExpr->spliceInferParams( initExpr );
836                delete initExpr;
837
838                // get the actual object's type (may not exactly match what comes back from the resolver
839                // due to conversions)
840                Type * initContext = currentObject.getCurrentType();
841
842                removeExtraneousCast( newExpr, indexer );
843
844                // check if actual object's type is char[]
845                if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
846                        if ( isCharType( at->get_base() ) ) {
847                                // check if the resolved type is char *
848                                if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
849                                        if ( isCharType( pt->get_base() ) ) {
850                                                if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) {
851                                                        // strip cast if we're initializing a char[] with a char *,
852                                                        // e.g.  char x[] = "hello";
853                                                        newExpr = ce->get_arg();
854                                                        ce->set_arg( nullptr );
855                                                        std::swap( ce->env, newExpr->env );
856                                                        delete ce;
857                                                }
858                                        }
859                                }
860                        }
861                }
862
863                // set initializer expr to resolved express
864                singleInit->value = newExpr;
865
866                // move cursor to next object in preparation for next initializer
867                currentObject.increment();
868        }
869
870        void Resolver_old::previsit( ListInit * listInit ) {
871                visit_children = false;
872                // move cursor into brace-enclosed initializer-list
873                currentObject.enterListInit();
874                // xxx - fix this so that the list isn't copied, iterator should be used to change current
875                // element
876                std::list<Designation *> newDesignations;
877                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
878                        // iterate designations and initializers in pairs, moving the cursor to the current
879                        // designated object and resolving the initializer against that object.
880                        Designation * des = std::get<0>(p);
881                        Initializer * init = std::get<1>(p);
882                        newDesignations.push_back( currentObject.findNext( des ) );
883                        init->accept( *visitor );
884                }
885                // set the set of 'resolved' designations and leave the brace-enclosed initializer-list
886                listInit->get_designations() = newDesignations; // xxx - memory management
887                currentObject.exitListInit();
888
889                // xxx - this part has not be folded into CurrentObject yet
890                // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
891                //      Type * base = tt->get_baseType()->get_base();
892                //      if ( base ) {
893                //              // know the implementation type, so try using that as the initContext
894                //              ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr );
895                //              currentObject = &tmpObj;
896                //              visit( listInit );
897                //      } else {
898                //              // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
899                //              Parent::visit( listInit );
900                //      }
901                // } else {
902        }
903
904        // ConstructorInit - fall back on C-style initializer
905        void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
906                // could not find valid constructor, or found an intrinsic constructor
907                // fall back on C-style initializer
908                delete ctorInit->get_ctor();
909                ctorInit->set_ctor( nullptr );
910                delete ctorInit->get_dtor();
911                ctorInit->set_dtor( nullptr );
912                maybeAccept( ctorInit->get_init(), *visitor );
913        }
914
915        // needs to be callable from outside the resolver, so this is a standalone function
916        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
917                assert( ctorInit );
918                PassVisitor<Resolver_old> resolver( indexer );
919                ctorInit->accept( resolver );
920        }
921
922        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
923                assert( stmtExpr );
924                PassVisitor<Resolver_old> resolver( indexer );
925                stmtExpr->accept( resolver );
926                stmtExpr->computeResult();
927                // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
928        }
929
930        void Resolver_old::previsit( ConstructorInit * ctorInit ) {
931                visit_children = false;
932                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
933                maybeAccept( ctorInit->ctor, *visitor );
934                maybeAccept( ctorInit->dtor, *visitor );
935
936                // found a constructor - can get rid of C-style initializer
937                delete ctorInit->init;
938                ctorInit->init = nullptr;
939
940                // intrinsic single parameter constructors and destructors do nothing. Since this was
941                // implicitly generated, there's no way for it to have side effects, so get rid of it
942                // to clean up generated code.
943                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
944                        delete ctorInit->ctor;
945                        ctorInit->ctor = nullptr;
946                }
947
948                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
949                        delete ctorInit->dtor;
950                        ctorInit->dtor = nullptr;
951                }
952
953                // xxx - todo -- what about arrays?
954                // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
955                //      // can reduce the constructor down to a SingleInit using the
956                //      // second argument from the ctor call, since
957                //      delete ctorInit->get_ctor();
958                //      ctorInit->set_ctor( nullptr );
959
960                //      Expression * arg =
961                //      ctorInit->set_init( new SingleInit( arg ) );
962                // }
963        }
964
965        ///////////////////////////////////////////////////////////////////////////
966        //
967        // *** NEW RESOLVER ***
968        //
969        ///////////////////////////////////////////////////////////////////////////
970
971        namespace {
972                /// Finds deleted expressions in an expression tree
973                struct DeleteFinder_new final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder_new> {
974                        const ast::DeletedExpr * result = nullptr;
975
976                        void previsit( const ast::DeletedExpr * expr ) {
977                                if ( result ) { visit_children = false; }
978                                else { result = expr; }
979                        }
980
981                        void previsit( const ast::Expr * expr ) {
982                                if ( result ) { visit_children = false; }
983                                if (expr->inferred.hasParams()) {
984                                        for (auto & imp : expr->inferred.inferParams() ) {
985                                                imp.second.expr->accept(*visitor);
986                                        }
987                                }
988                        }
989                };
990        } // anonymous namespace
991        /// Check if this expression is or includes a deleted expression
992        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
993                return ast::Pass<DeleteFinder_new>::read( expr );
994        }
995
996        namespace {
997                /// always-accept candidate filter
998                bool anyCandidate( const Candidate & ) { return true; }
999
1000                /// Calls the CandidateFinder and finds the single best candidate
1001                CandidateRef findUnfinishedKindExpression(
1002                        const ast::Expr * untyped, const ResolveContext & context, const std::string & kind,
1003                        std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
1004                ) {
1005                        if ( ! untyped ) return nullptr;
1006
1007                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
1008                        static unsigned recursion_level = 0;
1009
1010                        ++recursion_level;
1011                        ast::TypeEnvironment env;
1012                        CandidateFinder finder( context, env );
1013                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
1014                        --recursion_level;
1015
1016                        // produce a filtered list of candidates
1017                        CandidateList candidates;
1018                        for ( auto & cand : finder.candidates ) {
1019                                if ( pred( *cand ) ) { candidates.emplace_back( cand ); }
1020                        }
1021
1022                        // produce invalid error if no candidates
1023                        if ( candidates.empty() ) {
1024                                SemanticError( untyped,
1025                                        toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),
1026                                        "expression: ") );
1027                        }
1028
1029                        // search for cheapest candidate
1030                        CandidateList winners;
1031                        bool seen_undeleted = false;
1032                        for ( CandidateRef & cand : candidates ) {
1033                                int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );
1034
1035                                if ( c > 0 ) continue;  // skip more expensive than winner
1036
1037                                if ( c < 0 ) {
1038                                        // reset on new cheapest
1039                                        seen_undeleted = ! findDeletedExpr( cand->expr );
1040                                        winners.clear();
1041                                } else /* if ( c == 0 ) */ {
1042                                        if ( findDeletedExpr( cand->expr ) ) {
1043                                                // skip deleted expression if already seen one equivalent-cost not
1044                                                if ( seen_undeleted ) continue;
1045                                        } else if ( ! seen_undeleted ) {
1046                                                // replace list of equivalent-cost deleted expressions with one non-deleted
1047                                                winners.clear();
1048                                                seen_undeleted = true;
1049                                        }
1050                                }
1051
1052                                winners.emplace_back( std::move( cand ) );
1053                        }
1054
1055                        // promote candidate.cvtCost to .cost
1056                        promoteCvtCost( winners );
1057
1058                        // produce ambiguous errors, if applicable
1059                        if ( winners.size() != 1 ) {
1060                                std::ostringstream stream;
1061                                stream << "Cannot choose between " << winners.size() << " alternatives for "
1062                                        << kind << (kind != "" ? " " : "") << "expression\n";
1063                                ast::print( stream, untyped );
1064                                stream << " Alternatives are:\n";
1065                                print( stream, winners, 1 );
1066                                SemanticError( untyped->location, stream.str() );
1067                        }
1068
1069                        // single selected choice
1070                        CandidateRef & choice = winners.front();
1071
1072                        // fail on only expression deleted
1073                        if ( ! seen_undeleted ) {
1074                                SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "
1075                                "includes deleted identifier in " );
1076                        }
1077
1078                        return std::move( choice );
1079                }
1080
1081                /// Strips extraneous casts out of an expression
1082                struct StripCasts_new final {
1083                        const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
1084                                if (
1085                                        castExpr->isGenerated == ast::GeneratedCast
1086                                        && typesCompatible( castExpr->arg->result, castExpr->result )
1087                                ) {
1088                                        // generated cast is the same type as its argument, remove it after keeping env
1089                                        return ast::mutate_field(
1090                                                castExpr->arg.get(), &ast::Expr::env, castExpr->env );
1091                                }
1092                                return castExpr;
1093                        }
1094
1095                        static void strip( ast::ptr< ast::Expr > & expr ) {
1096                                ast::Pass< StripCasts_new > stripper;
1097                                expr = expr->accept( stripper );
1098                        }
1099                };
1100
1101                /// Swaps argument into expression pointer, saving original environment
1102                void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {
1103                        ast::ptr< ast::TypeSubstitution > env = expr->env;
1104                        expr.set_and_mutate( newExpr )->env = env;
1105                }
1106
1107                /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
1108                void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
1109                        if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
1110                                if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) {
1111                                        // cast is to the same type as its argument, remove it
1112                                        swap_and_save_env( expr, castExpr->arg );
1113                                }
1114                        }
1115                }
1116
1117
1118        } // anonymous namespace
1119/// Establish post-resolver invariants for expressions
1120                void finishExpr(
1121                        ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
1122                        const ast::TypeSubstitution * oldenv = nullptr
1123                ) {
1124                        // set up new type substitution for expression
1125                        ast::ptr< ast::TypeSubstitution > newenv =
1126                                 oldenv ? oldenv : new ast::TypeSubstitution{};
1127                        env.writeToSubstitution( *newenv.get_and_mutate() );
1128                        expr.get_and_mutate()->env = std::move( newenv );
1129                        // remove unncecessary casts
1130                        StripCasts_new::strip( expr );
1131                }
1132
1133        ast::ptr< ast::Expr > resolveInVoidContext(
1134                const ast::Expr * expr, const ResolveContext & context,
1135                ast::TypeEnvironment & env
1136        ) {
1137                assertf( expr, "expected a non-null expression" );
1138
1139                // set up and resolve expression cast to void
1140                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
1141                CandidateRef choice = findUnfinishedKindExpression(
1142                        untyped, context, "", anyCandidate, ResolvMode::withAdjustment() );
1143
1144                // a cast expression has either 0 or 1 interpretations (by language rules);
1145                // if 0, an exception has already been thrown, and this code will not run
1146                const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
1147                env = std::move( choice->env );
1148
1149                return castExpr->arg;
1150        }
1151
1152        /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
1153                /// context.
1154                ast::ptr< ast::Expr > findVoidExpression(
1155                        const ast::Expr * untyped, const ResolveContext & context
1156                ) {
1157                        ast::TypeEnvironment env;
1158                        ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env );
1159                        finishExpr( newExpr, env, untyped->env );
1160                        return newExpr;
1161                }
1162
1163        namespace {
1164
1165
1166                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
1167                /// lowest cost, returning the resolved version
1168                ast::ptr< ast::Expr > findKindExpression(
1169                        const ast::Expr * untyped, const ResolveContext & context,
1170                        std::function<bool(const Candidate &)> pred = anyCandidate,
1171                        const std::string & kind = "", ResolvMode mode = {}
1172                ) {
1173                        if ( ! untyped ) return {};
1174                        CandidateRef choice =
1175                                findUnfinishedKindExpression( untyped, context, kind, pred, mode );
1176                        ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
1177                        return std::move( choice->expr );
1178                }
1179
1180                /// Resolve `untyped` to the single expression whose candidate is the best match
1181                ast::ptr< ast::Expr > findSingleExpression(
1182                        const ast::Expr * untyped, const ResolveContext & context
1183                ) {
1184                        Stats::ResolveTime::start( untyped );
1185                        auto res = findKindExpression( untyped, context );
1186                        Stats::ResolveTime::stop();
1187                        return res;
1188                }
1189        } // anonymous namespace
1190
1191        ast::ptr< ast::Expr > findSingleExpression(
1192                const ast::Expr * untyped, const ast::Type * type,
1193                const ResolveContext & context
1194        ) {
1195                assert( untyped && type );
1196                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
1197                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
1198                removeExtraneousCast( newExpr, context.symtab );
1199                return newExpr;
1200        }
1201
1202        namespace {
1203                bool structOrUnion( const Candidate & i ) {
1204                        const ast::Type * t = i.expr->result->stripReferences();
1205                        return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
1206                }
1207                /// Predicate for "Candidate has integral type"
1208                bool hasIntegralType( const Candidate & i ) {
1209                        const ast::Type * type = i.expr->result;
1210
1211                        if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {
1212                                return bt->isInteger();
1213                        } else if (
1214                                dynamic_cast< const ast::EnumInstType * >( type )
1215                                || dynamic_cast< const ast::ZeroType * >( type )
1216                                || dynamic_cast< const ast::OneType * >( type )
1217                        ) {
1218                                return true;
1219                        } else return false;
1220                }
1221
1222                /// Resolve `untyped` as an integral expression, returning the resolved version
1223                ast::ptr< ast::Expr > findIntegralExpression(
1224                        const ast::Expr * untyped, const ResolveContext & context
1225                ) {
1226                        return findKindExpression( untyped, context, hasIntegralType, "condition" );
1227                }
1228
1229                /// check if a type is a character type
1230                bool isCharType( const ast::Type * t ) {
1231                        if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {
1232                                return bt->kind == ast::BasicType::Char
1233                                        || bt->kind == ast::BasicType::SignedChar
1234                                        || bt->kind == ast::BasicType::UnsignedChar;
1235                        }
1236                        return false;
1237                }
1238
1239                /// Advance a type itertor to the next mutex parameter
1240                template<typename Iter>
1241                inline bool nextMutex( Iter & it, const Iter & end ) {
1242                        while ( it != end && ! (*it)->is_mutex() ) { ++it; }
1243                        return it != end;
1244                }
1245        }
1246
1247        class Resolver_new final
1248        : public ast::WithSymbolTable, public ast::WithGuards,
1249          public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
1250          public ast::WithStmtsToAdd<> {
1251
1252                ast::ptr< ast::Type > functionReturn = nullptr;
1253                ast::CurrentObject currentObject;
1254                // for work previously in GenInit
1255                static InitTweak::ManagedTypes_new managedTypes;
1256                ResolveContext context;
1257
1258                bool inEnumDecl = false;
1259
1260        public:
1261                static size_t traceId;
1262                Resolver_new( const ast::TranslationGlobal & global ) :
1263                        ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd),
1264                        context{ symtab, global } {}
1265                Resolver_new( const ResolveContext & context ) :
1266                        ast::WithSymbolTable{ context.symtab },
1267                        context{ symtab, context.global } {}
1268
1269                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
1270                const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
1271                const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
1272                void previsit( const ast::AggregateDecl * );
1273                void previsit( const ast::StructDecl * );
1274                void previsit( const ast::EnumDecl * );
1275                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
1276
1277                const ast::ArrayType * previsit( const ast::ArrayType * );
1278                const ast::PointerType * previsit( const ast::PointerType * );
1279
1280                const ast::ExprStmt *        previsit( const ast::ExprStmt * );
1281                const ast::AsmExpr *         previsit( const ast::AsmExpr * );
1282                const ast::AsmStmt *         previsit( const ast::AsmStmt * );
1283                const ast::IfStmt *          previsit( const ast::IfStmt * );
1284                const ast::WhileDoStmt *     previsit( const ast::WhileDoStmt * );
1285                const ast::ForStmt *         previsit( const ast::ForStmt * );
1286                const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
1287                const ast::CaseClause *      previsit( const ast::CaseClause * );
1288                const ast::BranchStmt *      previsit( const ast::BranchStmt * );
1289                const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
1290                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
1291                const ast::CatchClause *     previsit( const ast::CatchClause * );
1292                const ast::CatchClause *     postvisit( const ast::CatchClause * );
1293                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
1294                const ast::WithStmt *        previsit( const ast::WithStmt * );
1295
1296                const ast::SingleInit *      previsit( const ast::SingleInit * );
1297                const ast::ListInit *        previsit( const ast::ListInit * );
1298                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
1299
1300                void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
1301
1302                void beginScope() { managedTypes.beginScope(); }
1303                void endScope() { managedTypes.endScope(); }
1304                bool on_error(ast::ptr<ast::Decl> & decl);
1305        };
1306        // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
1307
1308        InitTweak::ManagedTypes_new Resolver_new::managedTypes;
1309
1310        void resolve( ast::TranslationUnit& translationUnit ) {
1311                ast::Pass< Resolver_new >::run( translationUnit, translationUnit.global );
1312        }
1313
1314        ast::ptr< ast::Init > resolveCtorInit(
1315                const ast::ConstructorInit * ctorInit, const ResolveContext & context
1316        ) {
1317                assert( ctorInit );
1318                ast::Pass< Resolver_new > resolver( context );
1319                return ctorInit->accept( resolver );
1320        }
1321
1322        const ast::Expr * resolveStmtExpr(
1323                const ast::StmtExpr * stmtExpr, const ResolveContext & context
1324        ) {
1325                assert( stmtExpr );
1326                ast::Pass< Resolver_new > resolver( context );
1327                auto ret = mutate(stmtExpr->accept(resolver));
1328                strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
1329                return ret;
1330        }
1331
1332        namespace {
1333                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) {
1334                        std::string name = attr->normalizedName();
1335                        if (name == "constructor" || name == "destructor") {
1336                                if (attr->params.size() == 1) {
1337                                        auto arg = attr->params.front();
1338                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context );
1339                                        auto result = eval(arg);
1340
1341                                        auto mutAttr = mutate(attr);
1342                                        mutAttr->params.front() = resolved;
1343                                        if (! result.second) {
1344                                                SemanticWarning(loc, Warning::GccAttributes,
1345                                                        toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
1346                                        }
1347                                        else {
1348                                                auto priority = result.first;
1349                                                if (priority < 101) {
1350                                                        SemanticWarning(loc, Warning::GccAttributes,
1351                                                                toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
1352                                                } else if (priority < 201 && ! buildingLibrary()) {
1353                                                        SemanticWarning(loc, Warning::GccAttributes,
1354                                                                toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
1355                                                }
1356                                        }
1357                                        return mutAttr;
1358                                } else if (attr->params.size() > 1) {
1359                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
1360                                } else {
1361                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
1362                                }
1363                        }
1364                        return attr;
1365                }
1366        }
1367
1368        const ast::FunctionDecl * Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
1369                GuardValue( functionReturn );
1370
1371                assert (functionDecl->unique());
1372                if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
1373                        SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
1374                }
1375
1376                if (!functionDecl->isTypeFixed) {
1377                        auto mutDecl = mutate(functionDecl);
1378                        auto mutType = mutDecl->type.get_and_mutate();
1379
1380                        for (auto & attr: mutDecl->attributes) {
1381                                attr = handleAttribute(mutDecl->location, attr, context );
1382                        }
1383
1384                        // handle assertions
1385
1386                        symtab.enterScope();
1387                        mutType->forall.clear();
1388                        mutType->assertions.clear();
1389                        for (auto & typeParam : mutDecl->type_params) {
1390                                symtab.addType(typeParam);
1391                                mutType->forall.emplace_back(new ast::TypeInstType(typeParam));
1392                        }
1393                        for (auto & asst : mutDecl->assertions) {
1394                                asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context);
1395                                symtab.addId(asst);
1396                                mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
1397                        }
1398
1399                        // temporarily adds params to symbol table.
1400                        // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
1401
1402                        std::vector<ast::ptr<ast::Type>> paramTypes;
1403                        std::vector<ast::ptr<ast::Type>> returnTypes;
1404
1405                        for (auto & param : mutDecl->params) {
1406                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context);
1407                                symtab.addId(param);
1408                                paramTypes.emplace_back(param->get_type());
1409                        }
1410                        for (auto & ret : mutDecl->returns) {
1411                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context);
1412                                returnTypes.emplace_back(ret->get_type());
1413                        }
1414                        // since function type in decl is just a view of param types, need to update that as well
1415                        mutType->params = std::move(paramTypes);
1416                        mutType->returns = std::move(returnTypes);
1417
1418                        auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID));
1419
1420                        std::list<ast::ptr<ast::Stmt>> newStmts;
1421                        resolveWithExprs (mutDecl->withExprs, newStmts);
1422
1423                        if (mutDecl->stmts) {
1424                                auto mutStmt = mutDecl->stmts.get_and_mutate();
1425                                mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
1426                                mutDecl->stmts = mutStmt;
1427                        }
1428
1429                        symtab.leaveScope();
1430
1431                        mutDecl->type = renamedType;
1432                        mutDecl->mangleName = Mangle::mangle(mutDecl);
1433                        mutDecl->isTypeFixed = true;
1434                        functionDecl = mutDecl;
1435                }
1436                managedTypes.handleDWT(functionDecl);
1437
1438                functionReturn = extractResultType( functionDecl->type );
1439                return functionDecl;
1440        }
1441
1442        const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) {
1443                // default value expressions have an environment which shouldn't be there and trips up
1444                // later passes.
1445                assert( functionDecl->unique() );
1446                ast::FunctionType * mutType = mutate( functionDecl->type.get() );
1447
1448                for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) {
1449                        if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {
1450                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
1451                                        if ( init->value->env == nullptr ) continue;
1452                                        // clone initializer minus the initializer environment
1453                                        auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() );
1454                                        auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() );
1455                                        auto mutValue = mutate( mutInit->value.get() );
1456
1457                                        mutValue->env = nullptr;
1458                                        mutInit->value = mutValue;
1459                                        mutParam->init = mutInit;
1460                                        mutType->params[i] = mutParam;
1461
1462                                        assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env);
1463                                }
1464                        }
1465                }
1466                mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
1467                return functionDecl;
1468        }
1469
1470        const ast::ObjectDecl * Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
1471                // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
1472                // class-variable `initContext` is changed multiple times because the LHS is analyzed
1473                // twice. The second analysis changes `initContext` because a function type can contain
1474                // object declarations in the return and parameter types. Therefore each value of
1475                // `initContext` is retained so the type on the first analysis is preserved and used for
1476                // selecting the RHS.
1477                GuardValue( currentObject );
1478
1479                if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
1480                        // enumerator initializers should not use the enum type to initialize, since the
1481                        // enum type is still incomplete at this point. Use `int` instead.
1482
1483                        if ( auto enumBase = dynamic_cast< const ast::EnumInstType * >
1484                                ( objectDecl->get_type() )->base->base ) {
1485                                objectDecl = fixObjectType( objectDecl, context );
1486                                currentObject = ast::CurrentObject{ 
1487                                        objectDecl->location, 
1488                                        enumBase
1489                                };
1490                        } else {
1491                                objectDecl = fixObjectType( objectDecl, context );
1492                                currentObject = ast::CurrentObject{
1493                                        objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
1494                        }
1495
1496                }
1497                else {
1498                        if ( !objectDecl->isTypeFixed ) {
1499                                auto newDecl = fixObjectType(objectDecl, context);
1500                                auto mutDecl = mutate(newDecl);
1501
1502                                // generate CtorInit wrapper when necessary.
1503                                // in certain cases, fixObjectType is called before reaching
1504                                // this object in visitor pass, thus disabling CtorInit codegen.
1505                                // this happens on aggregate members and function parameters.
1506                                if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
1507                                        // constructed objects cannot be designated
1508                                        if ( InitTweak::isDesignated( mutDecl->init ) ) SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
1509                                        // constructed objects should not have initializers nested too deeply
1510                                        if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
1511
1512                                        mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
1513                                }
1514
1515                                objectDecl = mutDecl;
1516                        }
1517                        currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
1518                }
1519
1520                return objectDecl;
1521        }
1522
1523        void Resolver_new::previsit( const ast::AggregateDecl * _aggDecl ) {
1524                auto aggDecl = mutate(_aggDecl);
1525                assertf(aggDecl == _aggDecl, "type declarations must be unique");
1526
1527                for (auto & member: aggDecl->members) {
1528                        // nested type decls are hoisted already. no need to do anything
1529                        if (auto obj = member.as<ast::ObjectDecl>()) {
1530                                member = fixObjectType(obj, context);
1531                        }
1532                }
1533        }
1534
1535        void Resolver_new::previsit( const ast::StructDecl * structDecl ) {
1536                previsit(static_cast<const ast::AggregateDecl *>(structDecl));
1537                managedTypes.handleStruct(structDecl);
1538        }
1539
1540        void Resolver_new::previsit( const ast::EnumDecl * ) {
1541                // in case we decide to allow nested enums
1542                GuardValue( inEnumDecl );
1543                inEnumDecl = true;
1544                // don't need to fix types for enum fields
1545        }
1546
1547        const ast::StaticAssertDecl * Resolver_new::previsit(
1548                const ast::StaticAssertDecl * assertDecl
1549        ) {
1550                return ast::mutate_field(
1551                        assertDecl, &ast::StaticAssertDecl::cond,
1552                        findIntegralExpression( assertDecl->cond, context ) );
1553        }
1554
1555        template< typename PtrType >
1556        const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) {
1557                if ( type->dimension ) {
1558                        const ast::Type * sizeType = context.global.sizeType.get();
1559                        ast::ptr< ast::Expr > dimension = findSingleExpression( type->dimension, sizeType, context );
1560                        assertf(dimension->env->empty(), "array dimension expr has nonempty env");
1561                        dimension.get_and_mutate()->env = nullptr;
1562                        ast::mutate_field( type, &PtrType::dimension, dimension );
1563                }
1564                return type;
1565        }
1566
1567        const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
1568                return handlePtrType( at, context );
1569        }
1570
1571        const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
1572                return handlePtrType( pt, context );
1573        }
1574
1575        const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
1576                visit_children = false;
1577                assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
1578
1579                return ast::mutate_field(
1580                        exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) );
1581        }
1582
1583        const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
1584                visit_children = false;
1585
1586                asmExpr = ast::mutate_field(
1587                        asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) );
1588
1589                return asmExpr;
1590        }
1591
1592        const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
1593                visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
1594                visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
1595                visit_children = false;
1596                return asmStmt;
1597        }
1598
1599        const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
1600                return ast::mutate_field(
1601                        ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) );
1602        }
1603
1604        const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) {
1605                return ast::mutate_field(
1606                        whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) );
1607        }
1608
1609        const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
1610                if ( forStmt->cond ) {
1611                        forStmt = ast::mutate_field(
1612                                forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) );
1613                }
1614
1615                if ( forStmt->inc ) {
1616                        forStmt = ast::mutate_field(
1617                                forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) );
1618                }
1619
1620                return forStmt;
1621        }
1622
1623        const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
1624                GuardValue( currentObject );
1625                switchStmt = ast::mutate_field(
1626                        switchStmt, &ast::SwitchStmt::cond,
1627                        findIntegralExpression( switchStmt->cond, context ) );
1628                currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
1629                return switchStmt;
1630        }
1631
1632        const ast::CaseClause * Resolver_new::previsit( const ast::CaseClause * caseStmt ) {
1633                if ( caseStmt->cond ) {
1634                        std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
1635                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
1636                                "expression." );
1637
1638                        ast::ptr< ast::Expr > untyped =
1639                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
1640                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context );
1641
1642                        // case condition cannot have a cast in C, so it must be removed here, regardless of
1643                        // whether it would perform a conversion.
1644                        if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
1645                                swap_and_save_env( newExpr, castExpr->arg );
1646                        }
1647
1648                        caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr );
1649                }
1650                return caseStmt;
1651        }
1652
1653        const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
1654                visit_children = false;
1655                // must resolve the argument of a computed goto
1656                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
1657                        // computed goto argument is void*
1658                        ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
1659                        branchStmt = ast::mutate_field(
1660                                branchStmt, &ast::BranchStmt::computedTarget,
1661                                findSingleExpression( branchStmt->computedTarget, target, context ) );
1662                }
1663                return branchStmt;
1664        }
1665
1666        const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
1667                visit_children = false;
1668                if ( returnStmt->expr ) {
1669                        returnStmt = ast::mutate_field(
1670                                returnStmt, &ast::ReturnStmt::expr,
1671                                findSingleExpression( returnStmt->expr, functionReturn, context ) );
1672                }
1673                return returnStmt;
1674        }
1675
1676        const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
1677                visit_children = false;
1678                if ( throwStmt->expr ) {
1679                        const ast::StructDecl * exceptionDecl =
1680                                symtab.lookupStruct( "__cfaehm_base_exception_t" );
1681                        assert( exceptionDecl );
1682                        ast::ptr< ast::Type > exceptType =
1683                                new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
1684                        throwStmt = ast::mutate_field(
1685                                throwStmt, &ast::ThrowStmt::expr,
1686                                findSingleExpression( throwStmt->expr, exceptType, context ) );
1687                }
1688                return throwStmt;
1689        }
1690
1691        const ast::CatchClause * Resolver_new::previsit( const ast::CatchClause * catchClause ) {
1692                // Until we are very sure this invarent (ifs that move between passes have then)
1693                // holds, check it. This allows a check for when to decode the mangling.
1694                if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) {
1695                        assert( ifStmt->then );
1696                }
1697                // Encode the catchStmt so the condition can see the declaration.
1698                if ( catchClause->cond ) {
1699                        ast::CatchClause * clause = mutate( catchClause );
1700                        clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body );
1701                        clause->cond = nullptr;
1702                        return clause;
1703                }
1704                return catchClause;
1705        }
1706
1707        const ast::CatchClause * Resolver_new::postvisit( const ast::CatchClause * catchClause ) {
1708                // Decode the catchStmt so everything is stored properly.
1709                const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>();
1710                if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
1711                        assert( ifStmt->cond );
1712                        assert( ifStmt->else_ );
1713                        ast::CatchClause * clause = ast::mutate( catchClause );
1714                        clause->cond = ifStmt->cond;
1715                        clause->body = ifStmt->else_;
1716                        // ifStmt should be implicately deleted here.
1717                        return clause;
1718                }
1719                return catchClause;
1720        }
1721
1722        const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
1723                visit_children = false;
1724
1725                // Resolve all clauses first
1726                for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
1727                        const ast::WaitForClause & clause = *stmt->clauses[i];
1728
1729                        ast::TypeEnvironment env;
1730                        CandidateFinder funcFinder( context, env );
1731
1732                        // Find all candidates for a function in canonical form
1733                        funcFinder.find( clause.target, ResolvMode::withAdjustment() );
1734
1735                        if ( funcFinder.candidates.empty() ) {
1736                                stringstream ss;
1737                                ss << "Use of undeclared indentifier '";
1738                                ss << clause.target.strict_as< ast::NameExpr >()->name;
1739                                ss << "' in call to waitfor";
1740                                SemanticError( stmt->location, ss.str() );
1741                        }
1742
1743                        if ( clause.target_args.empty() ) {
1744                                SemanticError( stmt->location,
1745                                        "Waitfor clause must have at least one mutex parameter");
1746                        }
1747
1748                        // Find all alternatives for all arguments in canonical form
1749                        std::vector< CandidateFinder > argFinders =
1750                                funcFinder.findSubExprs( clause.target_args );
1751
1752                        // List all combinations of arguments
1753                        std::vector< CandidateList > possibilities;
1754                        combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );
1755
1756                        // For every possible function:
1757                        // * try matching the arguments to the parameters, not the other way around because
1758                        //   more arguments than parameters
1759                        CandidateList funcCandidates;
1760                        std::vector< CandidateList > argsCandidates;
1761                        SemanticErrorException errors;
1762                        for ( CandidateRef & func : funcFinder.candidates ) {
1763                                try {
1764                                        auto pointerType = dynamic_cast< const ast::PointerType * >(
1765                                                func->expr->result->stripReferences() );
1766                                        if ( ! pointerType ) {
1767                                                SemanticError( stmt->location, func->expr->result.get(),
1768                                                        "candidate not viable: not a pointer type\n" );
1769                                        }
1770
1771                                        auto funcType = pointerType->base.as< ast::FunctionType >();
1772                                        if ( ! funcType ) {
1773                                                SemanticError( stmt->location, func->expr->result.get(),
1774                                                        "candidate not viable: not a function type\n" );
1775                                        }
1776
1777                                        {
1778                                                auto param    = funcType->params.begin();
1779                                                auto paramEnd = funcType->params.end();
1780
1781                                                if( ! nextMutex( param, paramEnd ) ) {
1782                                                        SemanticError( stmt->location, funcType,
1783                                                                "candidate function not viable: no mutex parameters\n");
1784                                                }
1785                                        }
1786
1787                                        CandidateRef func2{ new Candidate{ *func } };
1788                                        // strip reference from function
1789                                        func2->expr = referenceToRvalueConversion( func->expr, func2->cost );
1790
1791                                        // Each argument must be matched with a parameter of the current candidate
1792                                        for ( auto & argsList : possibilities ) {
1793                                                try {
1794                                                        // Declare data structures needed for resolution
1795                                                        ast::OpenVarSet open;
1796                                                        ast::AssertionSet need, have;
1797                                                        ast::TypeEnvironment resultEnv{ func->env };
1798                                                        // Add all type variables as open so that those not used in the
1799                                                        // parameter list are still considered open
1800                                                        resultEnv.add( funcType->forall );
1801
1802                                                        // load type variables from arguments into one shared space
1803                                                        for ( auto & arg : argsList ) {
1804                                                                resultEnv.simpleCombine( arg->env );
1805                                                        }
1806
1807                                                        // Make sure we don't widen any existing bindings
1808                                                        resultEnv.forbidWidening();
1809
1810                                                        // Find any unbound type variables
1811                                                        resultEnv.extractOpenVars( open );
1812
1813                                                        auto param = funcType->params.begin();
1814                                                        auto paramEnd = funcType->params.end();
1815
1816                                                        unsigned n_mutex_param = 0;
1817
1818                                                        // For every argument of its set, check if it matches one of the
1819                                                        // parameters. The order is important
1820                                                        for ( auto & arg : argsList ) {
1821                                                                // Ignore non-mutex arguments
1822                                                                if ( ! nextMutex( param, paramEnd ) ) {
1823                                                                        // We ran out of parameters but still have arguments.
1824                                                                        // This function doesn't match
1825                                                                        SemanticError( stmt->location, funcType,
1826                                                                                toString("candidate function not viable: too many mutex "
1827                                                                                "arguments, expected ", n_mutex_param, "\n" ) );
1828                                                                }
1829
1830                                                                ++n_mutex_param;
1831
1832                                                                // Check if the argument matches the parameter type in the current
1833                                                                // scope
1834                                                                // ast::ptr< ast::Type > paramType = (*param)->get_type();
1835                                                                if (
1836                                                                        ! unify(
1837                                                                                arg->expr->result, *param, resultEnv, need, have, open )
1838                                                                ) {
1839                                                                        // Type doesn't match
1840                                                                        stringstream ss;
1841                                                                        ss << "candidate function not viable: no known conversion "
1842                                                                                "from '";
1843                                                                        ast::print( ss, *param );
1844                                                                        ss << "' to '";
1845                                                                        ast::print( ss, arg->expr->result );
1846                                                                        ss << "' with env '";
1847                                                                        ast::print( ss, resultEnv );
1848                                                                        ss << "'\n";
1849                                                                        SemanticError( stmt->location, funcType, ss.str() );
1850                                                                }
1851
1852                                                                ++param;
1853                                                        }
1854
1855                                                        // All arguments match!
1856
1857                                                        // Check if parameters are missing
1858                                                        if ( nextMutex( param, paramEnd ) ) {
1859                                                                do {
1860                                                                        ++n_mutex_param;
1861                                                                        ++param;
1862                                                                } while ( nextMutex( param, paramEnd ) );
1863
1864                                                                // We ran out of arguments but still have parameters left; this
1865                                                                // function doesn't match
1866                                                                SemanticError( stmt->location, funcType,
1867                                                                        toString( "candidate function not viable: too few mutex "
1868                                                                        "arguments, expected ", n_mutex_param, "\n" ) );
1869                                                        }
1870
1871                                                        // All parameters match!
1872
1873                                                        // Finish the expressions to tie in proper environments
1874                                                        finishExpr( func2->expr, resultEnv );
1875                                                        for ( CandidateRef & arg : argsList ) {
1876                                                                finishExpr( arg->expr, resultEnv );
1877                                                        }
1878
1879                                                        // This is a match, store it and save it for later
1880                                                        funcCandidates.emplace_back( std::move( func2 ) );
1881                                                        argsCandidates.emplace_back( std::move( argsList ) );
1882
1883                                                } catch ( SemanticErrorException & e ) {
1884                                                        errors.append( e );
1885                                                }
1886                                        }
1887                                } catch ( SemanticErrorException & e ) {
1888                                        errors.append( e );
1889                                }
1890                        }
1891
1892                        // Make sure correct number of arguments
1893                        if( funcCandidates.empty() ) {
1894                                SemanticErrorException top( stmt->location,
1895                                        "No alternatives for function in call to waitfor" );
1896                                top.append( errors );
1897                                throw top;
1898                        }
1899
1900                        if( argsCandidates.empty() ) {
1901                                SemanticErrorException top( stmt->location,
1902                                        "No alternatives for arguments in call to waitfor" );
1903                                top.append( errors );
1904                                throw top;
1905                        }
1906
1907                        if( funcCandidates.size() > 1 ) {
1908                                SemanticErrorException top( stmt->location,
1909                                        "Ambiguous function in call to waitfor" );
1910                                top.append( errors );
1911                                throw top;
1912                        }
1913                        if( argsCandidates.size() > 1 ) {
1914                                SemanticErrorException top( stmt->location,
1915                                        "Ambiguous arguments in call to waitfor" );
1916                                top.append( errors );
1917                                throw top;
1918                        }
1919                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
1920
1921                        // build new clause
1922                        auto clause2 = new ast::WaitForClause( clause.location );
1923
1924                        clause2->target = funcCandidates.front()->expr;
1925
1926                        clause2->target_args.reserve( clause.target_args.size() );
1927                        const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" );
1928                        for ( auto arg : argsCandidates.front() ) {
1929                                const auto & loc = stmt->location;
1930
1931                                ast::Expr * init = new ast::CastExpr( loc,
1932                                        new ast::UntypedExpr( loc,
1933                                                new ast::NameExpr( loc, "get_monitor" ),
1934                                                { arg->expr }
1935                                        ),
1936                                        new ast::PointerType(
1937                                                new ast::StructInstType(
1938                                                        decl_monitor
1939                                                )
1940                                        )
1941                                );
1942
1943                                clause2->target_args.emplace_back( findSingleExpression( init, context ) );
1944                        }
1945
1946                        // Resolve the conditions as if it were an IfStmt, statements normally
1947                        clause2->when_cond = findSingleExpression( clause.when_cond, context );
1948                        clause2->stmt = clause.stmt->accept( *visitor );
1949
1950                        // set results into stmt
1951                        auto n = mutate( stmt );
1952                        n->clauses[i] = clause2;
1953                        stmt = n;
1954                }
1955
1956                if ( stmt->timeout_stmt ) {
1957                        // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
1958                        ast::ptr< ast::Type > target =
1959                                new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
1960                        auto timeout_time = findSingleExpression( stmt->timeout_time, target, context );
1961                        auto timeout_cond = findSingleExpression( stmt->timeout_cond, context );
1962                        auto timeout_stmt = stmt->timeout_stmt->accept( *visitor );
1963
1964                        // set results into stmt
1965                        auto n = mutate( stmt );
1966                        n->timeout_time = std::move( timeout_time );
1967                        n->timeout_cond = std::move( timeout_cond );
1968                        n->timeout_stmt = std::move( timeout_stmt );
1969                        stmt = n;
1970                }
1971
1972                if ( stmt->else_stmt ) {
1973                        // resolve the condition like IfStmt, stmts normally
1974                        auto else_cond = findSingleExpression( stmt->else_cond, context );
1975                        auto else_stmt = stmt->else_stmt->accept( *visitor );
1976
1977                        // set results into stmt
1978                        auto n = mutate( stmt );
1979                        n->else_cond = std::move( else_cond );
1980                        n->else_stmt = std::move( else_stmt );
1981                        stmt = n;
1982                }
1983
1984                return stmt;
1985        }
1986
1987        const ast::WithStmt * Resolver_new::previsit( const ast::WithStmt * withStmt ) {
1988                auto mutStmt = mutate(withStmt);
1989                resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
1990                return mutStmt;
1991        }
1992
1993        void Resolver_new::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
1994                for (auto & expr : exprs) {
1995                        // only struct- and union-typed expressions are viable candidates
1996                        expr = findKindExpression( expr, context, structOrUnion, "with expression" );
1997
1998                        // if with expression might be impure, create a temporary so that it is evaluated once
1999                        if ( Tuples::maybeImpure( expr ) ) {
2000                                static UniqueName tmpNamer( "_with_tmp_" );
2001                                const CodeLocation loc = expr->location;
2002                                auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
2003                                expr = new ast::VariableExpr( loc, tmp );
2004                                stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
2005                                if ( InitTweak::isConstructable( tmp->type ) ) {
2006                                        // generate ctor/dtor and resolve them
2007                                        tmp->init = InitTweak::genCtorInit( loc, tmp );
2008                                }
2009                                // since tmp is freshly created, this should modify tmp in-place
2010                                tmp->accept( *visitor );
2011                        }
2012                        else if (expr->env && expr->env->empty()) {
2013                                expr = ast::mutate_field(expr.get(), &ast::Expr::env, nullptr);
2014                        }
2015                }
2016        }
2017
2018
2019        const ast::SingleInit * Resolver_new::previsit( const ast::SingleInit * singleInit ) {
2020                visit_children = false;
2021                // resolve initialization using the possibilities as determined by the `currentObject`
2022                // cursor.
2023                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
2024                        singleInit->location, singleInit->value, currentObject.getOptions() };
2025                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context );
2026                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
2027
2028                // move cursor to the object that is actually initialized
2029                currentObject.setNext( initExpr->designation );
2030
2031                // discard InitExpr wrapper and retain relevant pieces.
2032                // `initExpr` may have inferred params in the case where the expression specialized a
2033                // function pointer, and newExpr may already have inferParams of its own, so a simple
2034                // swap is not sufficient
2035                ast::Expr::InferUnion inferred = initExpr->inferred;
2036                swap_and_save_env( newExpr, initExpr->expr );
2037                newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );
2038
2039                // get the actual object's type (may not exactly match what comes back from the resolver
2040                // due to conversions)
2041                const ast::Type * initContext = currentObject.getCurrentType();
2042
2043                removeExtraneousCast( newExpr, symtab );
2044
2045                // check if actual object's type is char[]
2046                if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {
2047                        if ( isCharType( at->base ) ) {
2048                                // check if the resolved type is char*
2049                                if ( auto pt = newExpr->result.as< ast::PointerType >() ) {
2050                                        if ( isCharType( pt->base ) ) {
2051                                                // strip cast if we're initializing a char[] with a char*
2052                                                // e.g. char x[] = "hello"
2053                                                if ( auto ce = newExpr.as< ast::CastExpr >() ) {
2054                                                        swap_and_save_env( newExpr, ce->arg );
2055                                                }
2056                                        }
2057                                }
2058                        }
2059                }
2060
2061                // move cursor to next object in preparation for next initializer
2062                currentObject.increment();
2063
2064                // set initializer expression to resolved expression
2065                return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );
2066        }
2067
2068        const ast::ListInit * Resolver_new::previsit( const ast::ListInit * listInit ) {
2069                // move cursor into brace-enclosed initializer-list
2070                currentObject.enterListInit( listInit->location );
2071
2072                assert( listInit->designations.size() == listInit->initializers.size() );
2073                for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {
2074                        // iterate designations and initializers in pairs, moving the cursor to the current
2075                        // designated object and resolving the initializer against that object
2076                        listInit = ast::mutate_field_index(
2077                                listInit, &ast::ListInit::designations, i,
2078                                currentObject.findNext( listInit->designations[i] ) );
2079                        listInit = ast::mutate_field_index(
2080                                listInit, &ast::ListInit::initializers, i,
2081                                listInit->initializers[i]->accept( *visitor ) );
2082                }
2083
2084                // move cursor out of brace-enclosed initializer-list
2085                currentObject.exitListInit();
2086
2087                visit_children = false;
2088                return listInit;
2089        }
2090
2091        const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {
2092                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
2093                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
2094
2095                // found a constructor - can get rid of C-style initializer
2096                // xxx - Rob suggests this field is dead code
2097                ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );
2098
2099                // intrinsic single-parameter constructors and destructors do nothing. Since this was
2100                // implicitly generated, there's no way for it to have side effects, so get rid of it to
2101                // clean up generated code
2102                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
2103                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );
2104                }
2105                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
2106                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );
2107                }
2108
2109                return ctorInit;
2110        }
2111
2112        // suppress error on autogen functions and mark invalid autogen as deleted.
2113        bool Resolver_new::on_error(ast::ptr<ast::Decl> & decl) {
2114                if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
2115                        // xxx - can intrinsic gen ever fail?
2116                        if (functionDecl->linkage == ast::Linkage::AutoGen) {
2117                                auto mutDecl = mutate(functionDecl);
2118                                mutDecl->isDeleted = true;
2119                                mutDecl->stmts = nullptr;
2120                                decl = mutDecl;
2121                                return false;
2122                        }
2123                }
2124                return true;
2125        }
2126
2127} // namespace ResolvExpr
2128
2129// Local Variables: //
2130// tab-width: 4 //
2131// mode: c++ //
2132// compile-command: "make install" //
2133// End: //
Note: See TracBrowser for help on using the repository browser.