Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r8fd52e90 r2a08c25  
    77// Resolver.cc --
    88//
    9 // Author           : Aaron B. Moss
     9// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed May 29 11:00:00 2019
    13 // Update Count     : 241
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb 17 11:19:40 2018
     13// Update Count     : 213
    1414//
    1515
     16#include <stddef.h>                      // for NULL
    1617#include <cassert>                       // for strict_dynamic_cast, assert
    1718#include <memory>                        // for allocator, allocator_traits<...
    1819#include <tuple>                         // for get
    19 #include <vector>                        // for vector
     20#include <vector>
    2021
    2122#include "Alternative.h"                 // for Alternative, AltList
    2223#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 "ResolvMode.h"                  // for ResolvMode
    29 #include "typeops.h"                     // for extractResultType
    30 #include "Unify.h"                       // for unify
    31 #include "AST/Chain.hpp"
    32 #include "AST/Decl.hpp"
    33 #include "AST/Init.hpp"
    34 #include "AST/Pass.hpp"
    35 #include "AST/Print.hpp"
    36 #include "AST/SymbolTable.hpp"
    37 #include "AST/Type.hpp"
    3824#include "Common/PassVisitor.h"          // for PassVisitor
    3925#include "Common/SemanticError.h"        // for SemanticError
    4026#include "Common/utility.h"              // for ValueGuard, group_iterate
     27#include "CurrentObject.h"               // for CurrentObject
    4128#include "InitTweak/GenInit.h"
    4229#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
     30#include "RenameVars.h"                  // for RenameVars, global_renamer
    4331#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     32#include "ResolveTypeof.h"               // for resolveTypeof
     33#include "Resolver.h"
    4434#include "SymTab/Autogen.h"              // for SizeType
    4535#include "SymTab/Indexer.h"              // for Indexer
     
    5242#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    5343#include "Tuples/Tuples.h"
    54 #include "Validate/FindSpecialDecls.h"   // for SizeType
     44#include "typeops.h"                     // for extractResultType
     45#include "Unify.h"                       // for unify
    5546
    5647using namespace std;
    5748
    5849namespace ResolvExpr {
    59         struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
    60                 Resolver_old() {}
    61                 Resolver_old( const SymTab::Indexer & other ) {
     50        struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {
     51                Resolver() {}
     52                Resolver( const SymTab::Indexer & other ) {
    6253                        indexer = other;
    6354                }
    6455
    65                 void previsit( FunctionDecl * functionDecl );
    66                 void postvisit( FunctionDecl * functionDecl );
    67                 void previsit( ObjectDecl * objectDecll );
     56                void previsit( FunctionDecl *functionDecl );
     57                void postvisit( FunctionDecl *functionDecl );
     58                void previsit( ObjectDecl *objectDecll );
     59                void previsit( TypeDecl *typeDecl );
    6860                void previsit( EnumDecl * enumDecl );
    6961                void previsit( StaticAssertDecl * assertDecl );
     
    7264                void previsit( PointerType * at );
    7365
    74                 void previsit( ExprStmt * exprStmt );
    75                 void previsit( AsmExpr * asmExpr );
    76                 void previsit( AsmStmt * asmStmt );
    77                 void previsit( IfStmt * ifStmt );
    78                 void previsit( WhileStmt * whileStmt );
    79                 void previsit( ForStmt * forStmt );
    80                 void previsit( SwitchStmt * switchStmt );
    81                 void previsit( CaseStmt * caseStmt );
    82                 void previsit( BranchStmt * branchStmt );
    83                 void previsit( ReturnStmt * returnStmt );
    84                 void previsit( ThrowStmt * throwStmt );
    85                 void previsit( CatchStmt * catchStmt );
     66                void previsit( ExprStmt *exprStmt );
     67                void previsit( AsmExpr *asmExpr );
     68                void previsit( AsmStmt *asmStmt );
     69                void previsit( IfStmt *ifStmt );
     70                void previsit( WhileStmt *whileStmt );
     71                void previsit( ForStmt *forStmt );
     72                void previsit( SwitchStmt *switchStmt );
     73                void previsit( CaseStmt *caseStmt );
     74                void previsit( BranchStmt *branchStmt );
     75                void previsit( ReturnStmt *returnStmt );
     76                void previsit( ThrowStmt *throwStmt );
     77                void previsit( CatchStmt *catchStmt );
    8678                void previsit( WaitForStmt * stmt );
    87 
    88                 void previsit( SingleInit * singleInit );
    89                 void previsit( ListInit * listInit );
    90                 void previsit( ConstructorInit * ctorInit );
     79                void previsit( WithStmt * withStmt );
     80
     81                void previsit( SingleInit *singleInit );
     82                void previsit( ListInit *listInit );
     83                void previsit( ConstructorInit *ctorInit );
    9184          private:
    9285                typedef std::list< Initializer * >::iterator InitIterator;
     
    9588                void handlePtrType( PtrType * type );
    9689
     90                void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    9791                void fallbackInit( ConstructorInit * ctorInit );
    9892
     
    10296        };
    10397
    104         struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
    105                 void previsit( FunctionDecl * );
    106                 void previsit( WithStmt * );
    107 
    108                 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    109         };
    110 
    11198        void resolve( std::list< Declaration * > translationUnit ) {
    112                 PassVisitor<Resolver_old> resolver;
     99                PassVisitor<Resolver> resolver;
    113100                acceptAll( translationUnit, resolver );
    114101        }
    115102
    116         void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
    117                 PassVisitor<Resolver_old> resolver( indexer );
     103        void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
     104                PassVisitor<Resolver> resolver( indexer );
    118105                maybeAccept( decl, resolver );
    119106        }
    120107
    121108        namespace {
    122                 struct DeleteFinder_old : public WithShortCircuiting    {
     109                struct DeleteFinder : public WithShortCircuiting        {
    123110                        DeletedExpr * delExpr = nullptr;
    124111                        void previsit( DeletedExpr * expr ) {
     
    134121
    135122        DeletedExpr * findDeletedExpr( Expression * expr ) {
    136                 PassVisitor<DeleteFinder_old> finder;
     123                PassVisitor<DeleteFinder> finder;
    137124                expr->accept( finder );
    138125                return finder.pass.delExpr;
     
    140127
    141128        namespace {
    142                 struct StripCasts_old {
     129                struct StripCasts {
    143130                        Expression * postmutate( CastExpr * castExpr ) {
    144131                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     
    153140
    154141                        static void strip( Expression *& expr ) {
    155                                 PassVisitor<StripCasts_old> stripper;
     142                                PassVisitor<StripCasts> stripper;
    156143                                expr = expr->acceptMutator( stripper );
    157144                        }
    158145                };
    159146
    160                 void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
     147                void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
    161148                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    162149                        env.makeSubstitution( *expr->env );
    163                         StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
     150                        StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
    164151                }
    165152
    166153                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    167154                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    168                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     155                                if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    169156                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
    170157                                        expr = castExpr->arg;
     
    178165
    179166        namespace {
    180                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
     167                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    181168                        assertf( untyped, "expected a non-null expression." );
    182 
    183                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    184                         static unsigned recursion_level = 0;
    185 
    186                         ++recursion_level;
    187169                        TypeEnvironment env;
    188170                        AlternativeFinder finder( indexer, env );
    189                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    190                         --recursion_level;
     171                        finder.find( untyped, adjust, prune, failFast );
    191172
    192173                        #if 0
     
    201182                        #endif
    202183
    203                         // produce filtered list of alternatives
    204184                        AltList candidates;
    205185                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    209189                        }
    210190
    211                         // produce invalid error if no candidates
    212                         if ( candidates.empty() ) {
     191                        // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
     192                        // choose the lowest cost expression among the candidates
     193                        AltList winners;
     194                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     195                        if ( winners.size() == 0 ) {
    213196                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    214                         }
    215 
    216                         // search for cheapest candidate
    217                         AltList winners;
    218                         bool seen_undeleted = false;
    219                         for ( unsigned i = 0; i < candidates.size(); ++i ) {
    220                                 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
    221 
    222                                 if ( c > 0 ) continue; // skip more expensive than winner
    223 
    224                                 if ( c < 0 ) {
    225                                         // reset on new cheapest
    226                                         seen_undeleted = ! findDeletedExpr( candidates[i].expr );
    227                                         winners.clear();
    228                                 } else /* if ( c == 0 ) */ {
    229                                         if ( findDeletedExpr( candidates[i].expr ) ) {
    230                                                 // skip deleted expression if already seen one equivalent-cost not
    231                                                 if ( seen_undeleted ) continue;
    232                                         } else if ( ! seen_undeleted ) {
    233                                                 // replace list of equivalent-cost deleted expressions with one non-deleted
    234                                                 winners.clear();
    235                                                 seen_undeleted = true;
    236                                         }
    237                                 }
    238 
    239                                 winners.emplace_back( std::move( candidates[i] ) );
    240                         }
    241 
    242                         // promote alternative.cvtCost to .cost
    243                         // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
    244                         for ( Alternative& winner : winners ) {
    245                                 winner.cost = winner.cvtCost;
    246                         }
    247 
    248                         // produce ambiguous errors, if applicable
    249                         if ( winners.size() != 1 ) {
     197                        } else if ( winners.size() != 1 ) {
    250198                                std::ostringstream stream;
    251199                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    256204                        }
    257205
    258                         // single selected choice
    259                         Alternative& choice = winners.front();
    260 
    261                         // fail on only expression deleted
    262                         if ( ! seen_undeleted ) {
     206                        // there is one unambiguous interpretation - move the expression into the with statement
     207                        Alternative & choice = winners.front();
     208                        if ( findDeletedExpr( choice.expr ) ) {
    263209                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    264210                        }
    265 
    266                         // xxx - check for ambiguous expressions
    267 
    268                         // output selected choice
    269211                        alt = std::move( choice );
    270212                }
    271213
    272214                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    273                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
     215                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    274216                        if ( ! untyped ) return;
    275217                        Alternative choice;
    276                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
     218                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
    277219                        finishExpr( choice.expr, choice.env, untyped->env );
    278220                        delete untyped;
     
    289231
    290232        // used in resolveTypeof
    291         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
     233        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
    292234                TypeEnvironment env;
    293235                return resolveInVoidContext( expr, indexer, env );
    294236        }
    295237
    296         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
     238        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
    297239                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    298240                // interpretations, an exception has already been thrown.
    299241                assertf( expr, "expected a non-null expression." );
    300242
    301                 CastExpr * untyped = new CastExpr( expr ); // cast to void
    302                 untyped->location = expr->location;
     243                static CastExpr untyped( nullptr ); // cast to void
     244                untyped.location = expr->location;
    303245
    304246                // set up and resolve expression cast to void
     247                untyped.arg = expr;
    305248                Alternative choice;
    306                 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
     249                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
    307250                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    308                 assert( castExpr );
    309251                env = std::move( choice.env );
    310252
     
    314256
    315257                // unlink the arg so that it isn't deleted twice at the end of the program
    316                 untyped->arg = nullptr;
     258                untyped.arg = nullptr;
    317259                return ret;
    318260        }
    319261
    320         void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     262        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    321263                resetTyVarRenaming();
    322264                TypeEnvironment env;
     
    327269        }
    328270
    329         void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     271        void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
    330272                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    331273        }
     
    346288                        if ( dynamic_cast< EnumInstType * >( type ) ) {
    347289                                return true;
    348                         } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
     290                        } else if ( BasicType *bt = dynamic_cast< BasicType * >( type ) ) {
    349291                                return bt->isInteger();
    350292                        } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
     
    355297                }
    356298
    357                 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     299                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    358300                        findKindExpression( untyped, indexer, "condition", isIntegralType );
    359301                }
    360302        }
    361303
    362 
    363         bool isStructOrUnion( const Alternative & alt ) {
    364                 Type * t = alt.expr->result->stripReferences();
    365                 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    366         }
    367 
    368         void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
    369                 PassVisitor<ResolveWithExprs> resolver;
    370                 acceptAll( translationUnit, resolver );
    371         }
    372 
    373         void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
    374                 for ( Expression *& expr : withExprs )  {
    375                         // only struct- and union-typed expressions are viable candidates
    376                         findKindExpression( expr, indexer, "with statement", isStructOrUnion );
    377 
    378                         // if with expression might be impure, create a temporary so that it is evaluated once
    379                         if ( Tuples::maybeImpure( expr ) ) {
    380                                 static UniqueName tmpNamer( "_with_tmp_" );
    381                                 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
    382                                 expr = new VariableExpr( tmp );
    383                                 newStmts.push_back( new DeclStmt( tmp ) );
    384                                 if ( InitTweak::isConstructable( tmp->type ) ) {
    385                                         // generate ctor/dtor and resolve them
    386                                         tmp->init = InitTweak::genCtorInit( tmp );
    387                                         tmp->accept( *visitor );
    388                                 }
    389                         }
    390                 }
    391         }
    392 
    393         void ResolveWithExprs::previsit( WithStmt * withStmt ) {
    394                 resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
    395         }
    396 
    397         void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
     304        void Resolver::previsit( ObjectDecl *objectDecl ) {
     305                Type *new_type = resolveTypeof( objectDecl->get_type(), indexer );
     306                objectDecl->set_type( new_type );
     307                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
     308                // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes
     309                // initContext because of a function type can contain object declarations in the return and parameter types. So
     310                // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting
     311                // the RHS.
     312                GuardValue( currentObject );
     313                currentObject = CurrentObject( objectDecl->get_type() );
     314                if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
     315                        // enumerator initializers should not use the enum type to initialize, since
     316                        // the enum type is still incomplete at this point. Use signed int instead.
     317                        currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     318                }
     319        }
     320
     321        template< typename PtrType >
     322        void Resolver::handlePtrType( PtrType * type ) {
     323                if ( type->get_dimension() ) {
     324                        findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer );
     325                }
     326        }
     327
     328        void Resolver::previsit( ArrayType * at ) {
     329                handlePtrType( at );
     330        }
     331
     332        void Resolver::previsit( PointerType * pt ) {
     333                handlePtrType( pt );
     334        }
     335
     336        void Resolver::previsit( TypeDecl *typeDecl ) {
     337                if ( typeDecl->get_base() ) {
     338                        Type *new_type = resolveTypeof( typeDecl->get_base(), indexer );
     339                        typeDecl->set_base( new_type );
     340                } // if
     341        }
     342
     343        void Resolver::previsit( FunctionDecl *functionDecl ) {
     344#if 0
     345                std::cerr << "resolver visiting functiondecl ";
     346                functionDecl->print( std::cerr );
     347                std::cerr << std::endl;
     348#endif
     349                Type *new_type = resolveTypeof( functionDecl->type, indexer );
     350                functionDecl->set_type( new_type );
     351                GuardValue( functionReturn );
     352                functionReturn = ResolvExpr::extractResultType( functionDecl->type );
     353
    398354                {
    399355                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
     
    411367        }
    412368
    413         void Resolver_old::previsit( ObjectDecl * objectDecl ) {
    414                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    415                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    416                 // The second analysis changes initContext because of a function type can contain object
    417                 // declarations in the return and parameter types. So each value of initContext is
    418                 // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    419                 GuardValue( currentObject );
    420                 currentObject = CurrentObject( objectDecl->get_type() );
    421                 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
    422                         // enumerator initializers should not use the enum type to initialize, since
    423                         // the enum type is still incomplete at this point. Use signed int instead.
    424                         currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    425                 }
    426         }
    427 
    428         template< typename PtrType >
    429         void Resolver_old::handlePtrType( PtrType * type ) {
    430                 if ( type->get_dimension() ) {
    431                         findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
    432                 }
    433         }
    434 
    435         void Resolver_old::previsit( ArrayType * at ) {
    436                 handlePtrType( at );
    437         }
    438 
    439         void Resolver_old::previsit( PointerType * pt ) {
    440                 handlePtrType( pt );
    441         }
    442 
    443         void Resolver_old::previsit( FunctionDecl * functionDecl ) {
    444 #if 0
    445                 std::cerr << "resolver visiting functiondecl ";
    446                 functionDecl->print( std::cerr );
    447                 std::cerr << std::endl;
    448 #endif
    449                 GuardValue( functionReturn );
    450                 functionReturn = ResolvExpr::extractResultType( functionDecl->type );
    451         }
    452 
    453         void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
    454                 // default value expressions have an environment which shouldn't be there and trips up
    455                 // later passes.
    456                 // xxx - it might be necessary to somehow keep the information from this environment, but I
    457                 // can't currently see how it's useful.
     369        void Resolver::postvisit( FunctionDecl *functionDecl ) {
     370                // default value expressions have an environment which shouldn't be there and trips up later passes.
     371                // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
     372                // see how it's useful.
    458373                for ( Declaration * d : functionDecl->type->parameters ) {
    459374                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    466381        }
    467382
    468         void Resolver_old::previsit( EnumDecl * ) {
     383        void Resolver::previsit( EnumDecl * ) {
    469384                // in case we decide to allow nested enums
    470385                GuardValue( inEnumDecl );
     
    472387        }
    473388
    474         void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
     389        void Resolver::previsit( StaticAssertDecl * assertDecl ) {
    475390                findIntegralExpression( assertDecl->condition, indexer );
    476391        }
    477392
    478         void Resolver_old::previsit( ExprStmt * exprStmt ) {
     393        void Resolver::previsit( ExprStmt *exprStmt ) {
    479394                visit_children = false;
    480395                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
     
    482397        }
    483398
    484         void Resolver_old::previsit( AsmExpr * asmExpr ) {
     399        void Resolver::previsit( AsmExpr *asmExpr ) {
    485400                visit_children = false;
    486401                findVoidExpression( asmExpr->operand, indexer );
     
    490405        }
    491406
    492         void Resolver_old::previsit( AsmStmt * asmStmt ) {
     407        void Resolver::previsit( AsmStmt *asmStmt ) {
    493408                visit_children = false;
    494409                acceptAll( asmStmt->get_input(), *visitor );
     
    496411        }
    497412
    498         void Resolver_old::previsit( IfStmt * ifStmt ) {
     413        void Resolver::previsit( IfStmt *ifStmt ) {
    499414                findIntegralExpression( ifStmt->condition, indexer );
    500415        }
    501416
    502         void Resolver_old::previsit( WhileStmt * whileStmt ) {
     417        void Resolver::previsit( WhileStmt *whileStmt ) {
    503418                findIntegralExpression( whileStmt->condition, indexer );
    504419        }
    505420
    506         void Resolver_old::previsit( ForStmt * forStmt ) {
     421        void Resolver::previsit( ForStmt *forStmt ) {
    507422                if ( forStmt->condition ) {
    508423                        findIntegralExpression( forStmt->condition, indexer );
     
    514429        }
    515430
    516         void Resolver_old::previsit( SwitchStmt * switchStmt ) {
     431        void Resolver::previsit( SwitchStmt *switchStmt ) {
    517432                GuardValue( currentObject );
    518433                findIntegralExpression( switchStmt->condition, indexer );
     
    521436        }
    522437
    523         void Resolver_old::previsit( CaseStmt * caseStmt ) {
     438        void Resolver::previsit( CaseStmt *caseStmt ) {
    524439                if ( caseStmt->condition ) {
    525440                        std::list< InitAlternative > initAlts = currentObject.getOptions();
     
    540455        }
    541456
    542         void Resolver_old::previsit( BranchStmt * branchStmt ) {
     457        void Resolver::previsit( BranchStmt *branchStmt ) {
    543458                visit_children = false;
    544459                // must resolve the argument for a computed goto
     
    551466        }
    552467
    553         void Resolver_old::previsit( ReturnStmt * returnStmt ) {
     468        void Resolver::previsit( ReturnStmt *returnStmt ) {
    554469                visit_children = false;
    555470                if ( returnStmt->expr ) {
     
    558473        }
    559474
    560         void Resolver_old::previsit( ThrowStmt * throwStmt ) {
     475        void Resolver::previsit( ThrowStmt *throwStmt ) {
    561476                visit_children = false;
    562477                // TODO: Replace *exception type with &exception type.
    563478                if ( throwStmt->get_expr() ) {
    564                         const StructDecl * exception_decl = indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
     479                        StructDecl * exception_decl =
     480                                indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
    565481                        assert( exception_decl );
    566                         Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
     482                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) );
    567483                        findSingleExpression( throwStmt->expr, exceptType, indexer );
    568484                }
    569485        }
    570486
    571         void Resolver_old::previsit( CatchStmt * catchStmt ) {
     487        void Resolver::previsit( CatchStmt *catchStmt ) {
    572488                if ( catchStmt->cond ) {
    573489                        findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
     
    584500        }
    585501
    586         void Resolver_old::previsit( WaitForStmt * stmt ) {
     502        void Resolver::previsit( WaitForStmt * stmt ) {
    587503                visit_children = false;
    588504
     
    666582
    667583                                                        // Make sure we don't widen any existing bindings
    668                                                         resultEnv.forbidWidening();
     584                                                        for ( auto & i : resultEnv ) {
     585                                                                i.allowWidening = false;
     586                                                        }
    669587
    670588                                                        // Find any unbound type variables
     
    674592                                                        auto param_end = function->parameters.end();
    675593
    676                                                         int n_mutex_param = 0;
     594                                                        int n_mutex_arg = 0;
    677595
    678596                                                        // For every arguments of its set, check if it matches one of the parameter
     
    684602                                                                        // We ran out of parameters but still have arguments
    685603                                                                        // this function doesn't match
    686                                                                         SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
     604                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_arg, "\n" ));
    687605                                                                }
    688606
    689                                                                 n_mutex_param++;
     607                                                                n_mutex_arg++;
    690608
    691609                                                                // Check if the argument matches the parameter type in the current scope
     
    710628                                                        // Check if parameters are missing
    711629                                                        if( advance_to_mutex( param, param_end ) ) {
    712                                                                 do {
    713                                                                         n_mutex_param++;
    714                                                                         param++;
    715                                                                 } while( advance_to_mutex( param, param_end ) );
    716 
    717630                                                                // We ran out of arguments but still have parameters left
    718631                                                                // this function doesn't match
    719                                                                 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
     632                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_arg, "\n" ));
    720633                                                        }
    721634
     
    733646
    734647                                                }
    735                                                 catch( SemanticErrorException & e ) {
     648                                                catch( SemanticErrorException &e ) {
    736649                                                        errors.append( e );
    737650                                                }
    738651                                        }
    739652                                }
    740                                 catch( SemanticErrorException & e ) {
     653                                catch( SemanticErrorException &e ) {
    741654                                        errors.append( e );
    742655                                }
     
    781694        }
    782695
    783         bool isCharType( Type * t ) {
     696        bool isStructOrUnion( const Alternative & alt ) {
     697                Type * t = alt.expr->result->stripReferences();
     698                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     699        }
     700
     701        void Resolver::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
     702                for ( Expression *& expr : withExprs )  {
     703                        // only struct- and union-typed expressions are viable candidates
     704                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
     705
     706                        // if with expression might be impure, create a temporary so that it is evaluated once
     707                        if ( Tuples::maybeImpure( expr ) ) {
     708                                static UniqueName tmpNamer( "_with_tmp_" );
     709                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
     710                                expr = new VariableExpr( tmp );
     711                                newStmts.push_back( new DeclStmt( tmp ) );
     712                                if ( InitTweak::isConstructable( tmp->type ) ) {
     713                                        // generate ctor/dtor and resolve them
     714                                        tmp->init = InitTweak::genCtorInit( tmp );
     715                                        tmp->accept( *visitor );
     716                                }
     717                        }
     718                }
     719        }
     720
     721        void Resolver::previsit( WithStmt * withStmt ) {
     722                resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
     723        }
     724
     725        template< typename T >
     726        bool isCharType( T t ) {
    784727                if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
    785728                        return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
     
    789732        }
    790733
    791         void Resolver_old::previsit( SingleInit * singleInit ) {
     734        void Resolver::previsit( SingleInit *singleInit ) {
    792735                visit_children = false;
    793736                // resolve initialization using the possibilities as determined by the currentObject cursor
     
    803746                initExpr->expr = nullptr;
    804747                std::swap( initExpr->env, newExpr->env );
    805                 // InitExpr may have inferParams in the case where the expression specializes a function
    806                 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
    807                 // sufficient.
     748                // InitExpr may have inferParams in the case where the expression specializes a function pointer,
     749                // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
    808750                newExpr->spliceInferParams( initExpr );
    809751                delete initExpr;
    810752
    811                 // get the actual object's type (may not exactly match what comes back from the resolver
    812                 // due to conversions)
     753                // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
    813754                Type * initContext = currentObject.getCurrentType();
    814755
     
    821762                                if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
    822763                                        if ( isCharType( pt->get_base() ) ) {
    823                                                 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    824                                                         // strip cast if we're initializing a char[] with a char *,
    825                                                         // e.g.  char x[] = "hello";
     764                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
     765                                                        // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
    826766                                                        newExpr = ce->get_arg();
    827767                                                        ce->set_arg( nullptr );
     
    841781        }
    842782
    843         void Resolver_old::previsit( ListInit * listInit ) {
     783        void Resolver::previsit( ListInit * listInit ) {
    844784                visit_children = false;
    845785                // move cursor into brace-enclosed initializer-list
    846786                currentObject.enterListInit();
    847                 // xxx - fix this so that the list isn't copied, iterator should be used to change current
    848                 // element
     787                // xxx - fix this so that the list isn't copied, iterator should be used to change current element
    849788                std::list<Designation *> newDesignations;
    850789                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    851                         // iterate designations and initializers in pairs, moving the cursor to the current
    852                         // designated object and resolving the initializer against that object.
     790                        // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
     791                        // the initializer against that object.
    853792                        Designation * des = std::get<0>(p);
    854793                        Initializer * init = std::get<1>(p);
     
    876815
    877816        // ConstructorInit - fall back on C-style initializer
    878         void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
     817        void Resolver::fallbackInit( ConstructorInit * ctorInit ) {
    879818                // could not find valid constructor, or found an intrinsic constructor
    880819                // fall back on C-style initializer
    881820                delete ctorInit->get_ctor();
    882                 ctorInit->set_ctor( nullptr );
     821                ctorInit->set_ctor( NULL );
    883822                delete ctorInit->get_dtor();
    884                 ctorInit->set_dtor( nullptr );
     823                ctorInit->set_dtor( NULL );
    885824                maybeAccept( ctorInit->get_init(), *visitor );
    886825        }
     
    889828        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
    890829                assert( ctorInit );
    891                 PassVisitor<Resolver_old> resolver( indexer );
     830                PassVisitor<Resolver> resolver( indexer );
    892831                ctorInit->accept( resolver );
    893832        }
     
    895834        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
    896835                assert( stmtExpr );
    897                 PassVisitor<Resolver_old> resolver( indexer );
     836                PassVisitor<Resolver> resolver( indexer );
    898837                stmtExpr->accept( resolver );
    899838                stmtExpr->computeResult();
     
    901840        }
    902841
    903         void Resolver_old::previsit( ConstructorInit * ctorInit ) {
     842        void Resolver::previsit( ConstructorInit *ctorInit ) {
    904843                visit_children = false;
    905844                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
     
    925864
    926865                // xxx - todo -- what about arrays?
    927                 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     866                // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    928867                //      // can reduce the constructor down to a SingleInit using the
    929868                //      // second argument from the ctor call, since
    930869                //      delete ctorInit->get_ctor();
    931                 //      ctorInit->set_ctor( nullptr );
     870                //      ctorInit->set_ctor( NULL );
    932871
    933872                //      Expression * arg =
     
    935874                // }
    936875        }
    937 
    938         ///////////////////////////////////////////////////////////////////////////
    939         //
    940         // *** NEW RESOLVER ***
    941         //
    942         ///////////////////////////////////////////////////////////////////////////
    943 
    944         namespace {
    945                 /// Finds deleted expressions in an expression tree
    946                 struct DeleteFinder_new final : public ast::WithShortCircuiting {
    947                         const ast::DeletedExpr * delExpr = nullptr;
    948 
    949                         void previsit( const ast::DeletedExpr * expr ) {
    950                                 if ( delExpr ) { visit_children = false; }
    951                                 else { delExpr = expr; }
    952                         }
    953 
    954                         void previsit( const ast::Expr * ) {
    955                                 if ( delExpr ) { visit_children = false; }
    956                         }
    957                 };
    958         } // anonymous namespace
    959 
    960         /// Check if this expression is or includes a deleted expression
    961         const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
    962                 ast::Pass<DeleteFinder_new> finder;
    963                 expr->accept( finder );
    964                 return finder.pass.delExpr;
    965         }
    966 
    967         namespace {
    968                 /// always-accept candidate filter
    969                 bool anyCandidate( const Candidate & ) { return true; }
    970 
    971                 /// Calls the CandidateFinder and finds the single best candidate
    972                 CandidateRef findUnfinishedKindExpression(
    973                         const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
    974                         std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
    975                 ) {
    976                         if ( ! untyped ) return nullptr;
    977 
    978                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    979                         static unsigned recursion_level = 0;
    980 
    981                         ++recursion_level;
    982                         ast::TypeEnvironment env;
    983                         CandidateFinder finder{ symtab, env };
    984                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    985                         --recursion_level;
    986 
    987                         // produce a filtered list of candidates
    988                         CandidateList candidates;
    989                         for ( auto & cand : finder.candidates ) {
    990                                 if ( pred( *cand ) ) { candidates.emplace_back( cand ); }
    991                         }
    992 
    993                         // produce invalid error if no candidates
    994                         if ( candidates.empty() ) {
    995                                 SemanticError( untyped,
    996                                         toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),
    997                                         "expression: ") );
    998                         }
    999 
    1000                         // search for cheapest candidate
    1001                         CandidateList winners;
    1002                         bool seen_undeleted = false;
    1003                         for ( CandidateRef & cand : candidates ) {
    1004                                 int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );
    1005 
    1006                                 if ( c > 0 ) continue;  // skip more expensive than winner
    1007 
    1008                                 if ( c < 0 ) {
    1009                                         // reset on new cheapest
    1010                                         seen_undeleted = ! findDeletedExpr( cand->expr );
    1011                                         winners.clear();
    1012                                 } else /* if ( c == 0 ) */ {
    1013                                         if ( findDeletedExpr( cand->expr ) ) {
    1014                                                 // skip deleted expression if already seen one equivalent-cost not
    1015                                                 if ( seen_undeleted ) continue;
    1016                                         } else if ( ! seen_undeleted ) {
    1017                                                 // replace list of equivalent-cost deleted expressions with one non-deleted
    1018                                                 winners.clear();
    1019                                                 seen_undeleted = true;
    1020                                         }
    1021                                 }
    1022 
    1023                                 winners.emplace_back( std::move( cand ) );
    1024                         }
    1025 
    1026                         // promote candidate.cvtCost to .cost
    1027                         promoteCvtCost( winners );
    1028 
    1029                         // produce ambiguous errors, if applicable
    1030                         if ( winners.size() != 1 ) {
    1031                                 std::ostringstream stream;
    1032                                 stream << "Cannot choose between " << winners.size() << " alternatives for "
    1033                                         << kind << (kind != "" ? " " : "") << "expression\n";
    1034                                 ast::print( stream, untyped );
    1035                                 stream << " Alternatives are:\n";
    1036                                 print( stream, winners, 1 );
    1037                                 SemanticError( untyped->location, stream.str() );
    1038                         }
    1039 
    1040                         // single selected choice
    1041                         CandidateRef & choice = winners.front();
    1042 
    1043                         // fail on only expression deleted
    1044                         if ( ! seen_undeleted ) {
    1045                                 SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "
    1046                                 "includes deleted identifier in " );
    1047                         }
    1048 
    1049                         return std::move( choice );
    1050                 }
    1051 
    1052                 /// Strips extraneous casts out of an expression
    1053                 struct StripCasts_new final {
    1054                         const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
    1055                                 if (
    1056                                         castExpr->isGenerated
    1057                                         && typesCompatible( castExpr->arg->result, castExpr->result )
    1058                                 ) {
    1059                                         // generated cast is the same type as its argument, remove it after keeping env
    1060                                         return ast::mutate_field(
    1061                                                 castExpr->arg.get(), &ast::Expr::env, castExpr->env );
    1062                                 }
    1063                                 return castExpr;
    1064                         }
    1065 
    1066                         static void strip( ast::ptr< ast::Expr > & expr ) {
    1067                                 ast::Pass< StripCasts_new > stripper;
    1068                                 expr = expr->accept( stripper );
    1069                         }
    1070                 };
    1071 
    1072                 /// Swaps argument into expression pointer, saving original environment
    1073                 void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {
    1074                         ast::ptr< ast::TypeSubstitution > env = expr->env;
    1075                         expr.set_and_mutate( newExpr )->env = env;
    1076                 }
    1077 
    1078                 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
    1079                 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
    1080                         if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
    1081                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
    1082                                         // cast is to the same type as its argument, remove it
    1083                                         swap_and_save_env( expr, castExpr->arg );
    1084                                 }
    1085                         }
    1086                 }
    1087 
    1088                 /// Establish post-resolver invariants for expressions
    1089                 void finishExpr(
    1090                         ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
    1091                         const ast::TypeSubstitution * oldenv = nullptr
    1092                 ) {
    1093                         // set up new type substitution for expression
    1094                         ast::ptr< ast::TypeSubstitution > newenv =
    1095                                  oldenv ? oldenv : new ast::TypeSubstitution{};
    1096                         env.writeToSubstitution( *newenv.get_and_mutate() );
    1097                         expr.get_and_mutate()->env = std::move( newenv );
    1098                         // remove unncecessary casts
    1099                         StripCasts_new::strip( expr );
    1100                 }
    1101         } // anonymous namespace
    1102 
    1103 
    1104         ast::ptr< ast::Expr > resolveInVoidContext(
    1105                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
    1106         ) {
    1107                 assertf( expr, "expected a non-null expression" );
    1108 
    1109                 // set up and resolve expression cast to void
    1110                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
    1111                 CandidateRef choice = findUnfinishedKindExpression(
    1112                         untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
    1113 
    1114                 // a cast expression has either 0 or 1 interpretations (by language rules);
    1115                 // if 0, an exception has already been thrown, and this code will not run
    1116                 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
    1117                 env = std::move( choice->env );
    1118 
    1119                 return castExpr->arg;
    1120         }
    1121 
    1122         namespace {
    1123                 /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    1124                 /// context.
    1125                 ast::ptr< ast::Expr > findVoidExpression(
    1126                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1127                 ) {
    1128                         resetTyVarRenaming();
    1129                         ast::TypeEnvironment env;
    1130                         ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
    1131                         finishExpr( newExpr, env, untyped->env );
    1132                         return newExpr;
    1133                 }
    1134 
    1135                 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    1136                 /// lowest cost, returning the resolved version
    1137                 ast::ptr< ast::Expr > findKindExpression(
    1138                         const ast::Expr * untyped, const ast::SymbolTable & symtab,
    1139                         std::function<bool(const Candidate &)> pred = anyCandidate,
    1140                         const std::string & kind = "", ResolvMode mode = {}
    1141                 ) {
    1142                         if ( ! untyped ) return {};
    1143                         CandidateRef choice =
    1144                                 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
    1145                         finishExpr( choice->expr, choice->env, untyped->env );
    1146                         return std::move( choice->expr );
    1147                 }
    1148 
    1149                 /// Resolve `untyped` to the single expression whose candidate is the best match
    1150                 ast::ptr< ast::Expr > findSingleExpression(
    1151                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1152                 ) {
    1153                         return findKindExpression( untyped, symtab );
    1154                 }
    1155         } // anonymous namespace
    1156 
    1157                 ast::ptr< ast::Expr > findSingleExpression(
    1158                         const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
    1159                 ) {
    1160                         assert( untyped && type );
    1161                         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    1162                         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    1163                         removeExtraneousCast( newExpr, symtab );
    1164                         return newExpr;
    1165                 }
    1166 
    1167         namespace {
    1168                 /// Predicate for "Candidate has integral type"
    1169                 bool hasIntegralType( const Candidate & i ) {
    1170                         const ast::Type * type = i.expr->result;
    1171 
    1172                         if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {
    1173                                 return bt->isInteger();
    1174                         } else if (
    1175                                 dynamic_cast< const ast::EnumInstType * >( type )
    1176                                 || dynamic_cast< const ast::ZeroType * >( type )
    1177                                 || dynamic_cast< const ast::OneType * >( type )
    1178                         ) {
    1179                                 return true;
    1180                         } else return false;
    1181                 }
    1182 
    1183                 /// Resolve `untyped` as an integral expression, returning the resolved version
    1184                 ast::ptr< ast::Expr > findIntegralExpression(
    1185                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1186                 ) {
    1187                         return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
    1188                 }
    1189 
    1190                 /// check if a type is a character type
    1191                 bool isCharType( const ast::Type * t ) {
    1192                         if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {
    1193                                 return bt->kind == ast::BasicType::Char
    1194                                         || bt->kind == ast::BasicType::SignedChar
    1195                                         || bt->kind == ast::BasicType::UnsignedChar;
    1196                         }
    1197                         return false;
    1198                 }
    1199 
    1200                 /// Advance a type itertor to the next mutex parameter
    1201                 template<typename Iter>
    1202                 inline bool nextMutex( Iter & it, const Iter & end ) {
    1203                         while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
    1204                         return it != end;
    1205                 }
    1206         }
    1207 
    1208         class Resolver_new final
    1209         : public ast::WithSymbolTable, public ast::WithGuards,
    1210           public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
    1211           public ast::WithStmtsToAdd<> {
    1212 
    1213                 ast::ptr< ast::Type > functionReturn = nullptr;
    1214                 ast::CurrentObject currentObject;
    1215                 bool inEnumDecl = false;
    1216 
    1217         public:
    1218                 Resolver_new() = default;
    1219                 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
    1220 
    1221                 void previsit( const ast::FunctionDecl * );
    1222                 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
    1223                 void previsit( const ast::ObjectDecl * );
    1224                 void previsit( const ast::EnumDecl * );
    1225                 const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
    1226 
    1227                 const ast::ArrayType * previsit( const ast::ArrayType * );
    1228                 const ast::PointerType * previsit( const ast::PointerType * );
    1229 
    1230                 const ast::ExprStmt *        previsit( const ast::ExprStmt * );
    1231                 const ast::AsmExpr *         previsit( const ast::AsmExpr * );
    1232                 const ast::AsmStmt *         previsit( const ast::AsmStmt * );
    1233                 const ast::IfStmt *          previsit( const ast::IfStmt * );
    1234                 const ast::WhileStmt *       previsit( const ast::WhileStmt * );
    1235                 const ast::ForStmt *         previsit( const ast::ForStmt * );
    1236                 const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
    1237                 const ast::CaseStmt *        previsit( const ast::CaseStmt * );
    1238                 const ast::BranchStmt *      previsit( const ast::BranchStmt * );
    1239                 const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
    1240                 const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
    1241                 const ast::CatchStmt *       previsit( const ast::CatchStmt * );
    1242                 const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
    1243 
    1244                 const ast::SingleInit *      previsit( const ast::SingleInit * );
    1245                 const ast::ListInit *        previsit( const ast::ListInit * );
    1246                 const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
    1247         };
    1248 
    1249         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
    1250                 ast::Pass< Resolver_new > resolver;
    1251                 accept_all( translationUnit, resolver );
    1252         }
    1253 
    1254         ast::ptr< ast::Init > resolveCtorInit(
    1255                 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab
    1256         ) {
    1257                 assert( ctorInit );
    1258                 ast::Pass< Resolver_new > resolver{ symtab };
    1259                 return ctorInit->accept( resolver );
    1260         }
    1261 
    1262         ast::ptr< ast::Expr > resolveStmtExpr(
    1263                 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab
    1264         ) {
    1265                 assert( stmtExpr );
    1266                 ast::Pass< Resolver_new > resolver{ symtab };
    1267                 ast::ptr< ast::Expr > ret = stmtExpr;
    1268                 ret = ret->accept( resolver );
    1269                 strict_dynamic_cast< ast::StmtExpr * >( ret.get_and_mutate() )->computeResult();
    1270                 return ret;
    1271         }
    1272 
    1273         void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
    1274                 GuardValue( functionReturn );
    1275                 functionReturn = extractResultType( functionDecl->type );
    1276         }
    1277 
    1278         const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) {
    1279                 // default value expressions have an environment which shouldn't be there and trips up
    1280                 // later passes.
    1281                 ast::ptr< ast::FunctionDecl > ret = functionDecl;
    1282                 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1283                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
    1284 
    1285                         if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
    1286                                 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    1287                                         if ( init->value->env == nullptr ) continue;
    1288                                         // clone initializer minus the initializer environment
    1289                                         ast::chain_mutate( ret )
    1290                                                 ( &ast::FunctionDecl::type )
    1291                                                         ( &ast::FunctionType::params )[i]
    1292                                                                 ( &ast::ObjectDecl::init )
    1293                                                                         ( &ast::SingleInit::value )->env = nullptr;
    1294 
    1295                                         assert( functionDecl != ret.get() || functionDecl->unique() );
    1296                                         assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );
    1297                                 }
    1298                         }
    1299                 }
    1300                 return ret.get();
    1301         }
    1302 
    1303         void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    1304                 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
    1305                 // class-variable `initContext` is changed multiple times because the LHS is analyzed
    1306                 // twice. The second analysis changes `initContext` because a function type can contain
    1307                 // object declarations in the return and parameter types. Therefore each value of
    1308                 // `initContext` is retained so the type on the first analysis is preserved and used for
    1309                 // selecting the RHS.
    1310                 GuardValue( currentObject );
    1311                 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
    1312                 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
    1313                         // enumerator initializers should not use the enum type to initialize, since the
    1314                         // enum type is still incomplete at this point. Use `int` instead.
    1315                         currentObject = ast::CurrentObject{
    1316                                 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
    1317                 }
    1318         }
    1319 
    1320         void Resolver_new::previsit( const ast::EnumDecl * ) {
    1321                 // in case we decide to allow nested enums
    1322                 GuardValue( inEnumDecl );
    1323                 inEnumDecl = false;
    1324         }
    1325 
    1326         const ast::StaticAssertDecl * Resolver_new::previsit(
    1327                 const ast::StaticAssertDecl * assertDecl
    1328         ) {
    1329                 return ast::mutate_field(
    1330                         assertDecl, &ast::StaticAssertDecl::cond,
    1331                         findIntegralExpression( assertDecl->cond, symtab ) );
    1332         }
    1333 
    1334         template< typename PtrType >
    1335         const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
    1336                 if ( type->dimension ) {
    1337                         #warning should use new equivalent to Validate::SizeType rather than sizeType here
    1338                         ast::ptr< ast::Type > sizeType = new ast::BasicType{ ast::BasicType::LongUnsignedInt };
    1339                         ast::mutate_field(
    1340                                 type, &PtrType::dimension,
    1341                                 findSingleExpression( type->dimension, sizeType, symtab ) );
    1342                 }
    1343                 return type;
    1344         }
    1345 
    1346         const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
    1347                 return handlePtrType( at, symtab );
    1348         }
    1349 
    1350         const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
    1351                 return handlePtrType( pt, symtab );
    1352         }
    1353 
    1354         const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
    1355                 visit_children = false;
    1356                 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
    1357 
    1358                 return ast::mutate_field(
    1359                         exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
    1360         }
    1361 
    1362         const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
    1363                 visit_children = false;
    1364 
    1365                 asmExpr = ast::mutate_field(
    1366                         asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
    1367 
    1368                 if ( asmExpr->inout ) {
    1369                         asmExpr = ast::mutate_field(
    1370                                 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) );
    1371                 }
    1372 
    1373                 return asmExpr;
    1374         }
    1375 
    1376         const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
    1377                 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
    1378                 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
    1379                 visit_children = false;
    1380                 return asmStmt;
    1381         }
    1382 
    1383         const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
    1384                 return ast::mutate_field(
    1385                         ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
    1386         }
    1387 
    1388         const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
    1389                 return ast::mutate_field(
    1390                         whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );
    1391         }
    1392 
    1393         const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
    1394                 if ( forStmt->cond ) {
    1395                         forStmt = ast::mutate_field(
    1396                                 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
    1397                 }
    1398 
    1399                 if ( forStmt->inc ) {
    1400                         forStmt = ast::mutate_field(
    1401                                 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
    1402                 }
    1403 
    1404                 return forStmt;
    1405         }
    1406 
    1407         const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
    1408                 GuardValue( currentObject );
    1409                 switchStmt = ast::mutate_field(
    1410                         switchStmt, &ast::SwitchStmt::cond,
    1411                         findIntegralExpression( switchStmt->cond, symtab ) );
    1412                 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
    1413                 return switchStmt;
    1414         }
    1415 
    1416         const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
    1417                 if ( caseStmt->cond ) {
    1418                         std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
    1419                         assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
    1420                                 "expression." );
    1421 
    1422                         ast::ptr< ast::Expr > untyped =
    1423                                 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1424                         ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
    1425 
    1426                         // case condition cannot have a cast in C, so it must be removed here, regardless of
    1427                         // whether it would perform a conversion.
    1428                         if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
    1429                                 swap_and_save_env( newExpr, castExpr->arg );
    1430                         }
    1431 
    1432                         caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr );
    1433                 }
    1434                 return caseStmt;
    1435         }
    1436 
    1437         const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
    1438                 visit_children = false;
    1439                 // must resolve the argument of a computed goto
    1440                 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    1441                         // computed goto argument is void*
    1442                         ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    1443                         branchStmt = ast::mutate_field(
    1444                                 branchStmt, &ast::BranchStmt::computedTarget,
    1445                                 findSingleExpression( branchStmt->computedTarget, target, symtab ) );
    1446                 }
    1447                 return branchStmt;
    1448         }
    1449 
    1450         const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
    1451                 visit_children = false;
    1452                 if ( returnStmt->expr ) {
    1453                         returnStmt = ast::mutate_field(
    1454                                 returnStmt, &ast::ReturnStmt::expr,
    1455                                 findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
    1456                 }
    1457                 return returnStmt;
    1458         }
    1459 
    1460         const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
    1461                 visit_children = false;
    1462                 if ( throwStmt->expr ) {
    1463                         const ast::StructDecl * exceptionDecl =
    1464                                 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" );
    1465                         assert( exceptionDecl );
    1466                         ast::ptr< ast::Type > exceptType =
    1467                                 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
    1468                         throwStmt = ast::mutate_field(
    1469                                 throwStmt, &ast::ThrowStmt::expr,
    1470                                 findSingleExpression( throwStmt->expr, exceptType, symtab ) );
    1471                 }
    1472                 return throwStmt;
    1473         }
    1474 
    1475         const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
    1476                 if ( catchStmt->cond ) {
    1477                         ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
    1478                         catchStmt = ast::mutate_field(
    1479                                 catchStmt, &ast::CatchStmt::cond,
    1480                                 findSingleExpression( catchStmt->cond, boolType, symtab ) );
    1481                 }
    1482                 return catchStmt;
    1483         }
    1484 
    1485         const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
    1486                 visit_children = false;
    1487 
    1488                 // Resolve all clauses first
    1489                 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
    1490                         const ast::WaitForStmt::Clause & clause = stmt->clauses[i];
    1491 
    1492                         ast::TypeEnvironment env;
    1493                         CandidateFinder funcFinder{ symtab, env };
    1494 
    1495                         // Find all candidates for a function in canonical form
    1496                         funcFinder.find( clause.target.func, ResolvMode::withAdjustment() );
    1497 
    1498                         if ( funcFinder.candidates.empty() ) {
    1499                                 stringstream ss;
    1500                                 ss << "Use of undeclared indentifier '";
    1501                                 ss << clause.target.func.strict_as< ast::NameExpr >()->name;
    1502                                 ss << "' in call to waitfor";
    1503                                 SemanticError( stmt->location, ss.str() );
    1504                         }
    1505 
    1506                         if ( clause.target.args.empty() ) {
    1507                                 SemanticError( stmt->location,
    1508                                         "Waitfor clause must have at least one mutex parameter");
    1509                         }
    1510 
    1511                         // Find all alternatives for all arguments in canonical form
    1512                         std::vector< CandidateFinder > argFinders =
    1513                                 funcFinder.findSubExprs( clause.target.args );
    1514 
    1515                         // List all combinations of arguments
    1516                         std::vector< CandidateList > possibilities;
    1517                         combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );
    1518 
    1519                         // For every possible function:
    1520                         // * try matching the arguments to the parameters, not the other way around because
    1521                         //   more arguments than parameters
    1522                         CandidateList funcCandidates;
    1523                         std::vector< CandidateList > argsCandidates;
    1524                         SemanticErrorException errors;
    1525                         for ( CandidateRef & func : funcFinder.candidates ) {
    1526                                 try {
    1527                                         auto pointerType = dynamic_cast< const ast::PointerType * >(
    1528                                                 func->expr->result->stripReferences() );
    1529                                         if ( ! pointerType ) {
    1530                                                 SemanticError( stmt->location, func->expr->result.get(),
    1531                                                         "candidate not viable: not a pointer type\n" );
    1532                                         }
    1533 
    1534                                         auto funcType = pointerType->base.as< ast::FunctionType >();
    1535                                         if ( ! funcType ) {
    1536                                                 SemanticError( stmt->location, func->expr->result.get(),
    1537                                                         "candidate not viable: not a function type\n" );
    1538                                         }
    1539 
    1540                                         {
    1541                                                 auto param    = funcType->params.begin();
    1542                                                 auto paramEnd = funcType->params.end();
    1543 
    1544                                                 if( ! nextMutex( param, paramEnd ) ) {
    1545                                                         SemanticError( stmt->location, funcType,
    1546                                                                 "candidate function not viable: no mutex parameters\n");
    1547                                                 }
    1548                                         }
    1549 
    1550                                         CandidateRef func2{ new Candidate{ *func } };
    1551                                         // strip reference from function
    1552                                         func2->expr = referenceToRvalueConversion( func->expr, func2->cost );
    1553 
    1554                                         // Each argument must be matched with a parameter of the current candidate
    1555                                         for ( auto & argsList : possibilities ) {
    1556                                                 try {
    1557                                                         // Declare data structures needed for resolution
    1558                                                         ast::OpenVarSet open;
    1559                                                         ast::AssertionSet need, have;
    1560                                                         ast::TypeEnvironment resultEnv{ func->env };
    1561                                                         // Add all type variables as open so that those not used in the
    1562                                                         // parameter list are still considered open
    1563                                                         resultEnv.add( funcType->forall );
    1564 
    1565                                                         // load type variables from arguments into one shared space
    1566                                                         for ( auto & arg : argsList ) {
    1567                                                                 resultEnv.simpleCombine( arg->env );
    1568                                                         }
    1569 
    1570                                                         // Make sure we don't widen any existing bindings
    1571                                                         resultEnv.forbidWidening();
    1572 
    1573                                                         // Find any unbound type variables
    1574                                                         resultEnv.extractOpenVars( open );
    1575 
    1576                                                         auto param = funcType->params.begin();
    1577                                                         auto paramEnd = funcType->params.end();
    1578 
    1579                                                         unsigned n_mutex_param = 0;
    1580 
    1581                                                         // For every argument of its set, check if it matches one of the
    1582                                                         // parameters. The order is important
    1583                                                         for ( auto & arg : argsList ) {
    1584                                                                 // Ignore non-mutex arguments
    1585                                                                 if ( ! nextMutex( param, paramEnd ) ) {
    1586                                                                         // We ran out of parameters but still have arguments.
    1587                                                                         // This function doesn't match
    1588                                                                         SemanticError( stmt->location, funcType,
    1589                                                                                 toString("candidate function not viable: too many mutex "
    1590                                                                                 "arguments, expected ", n_mutex_param, "\n" ) );
    1591                                                                 }
    1592 
    1593                                                                 ++n_mutex_param;
    1594 
    1595                                                                 // Check if the argument matches the parameter type in the current
    1596                                                                 // scope
    1597                                                                 ast::ptr< ast::Type > paramType = (*param)->get_type();
    1598                                                                 if (
    1599                                                                         ! unify(
    1600                                                                                 arg->expr->result, paramType, resultEnv, need, have, open,
    1601                                                                                 symtab )
    1602                                                                 ) {
    1603                                                                         // Type doesn't match
    1604                                                                         stringstream ss;
    1605                                                                         ss << "candidate function not viable: no known conversion "
    1606                                                                                 "from '";
    1607                                                                         ast::print( ss, (*param)->get_type() );
    1608                                                                         ss << "' to '";
    1609                                                                         ast::print( ss, arg->expr->result );
    1610                                                                         ss << "' with env '";
    1611                                                                         ast::print( ss, resultEnv );
    1612                                                                         ss << "'\n";
    1613                                                                         SemanticError( stmt->location, funcType, ss.str() );
    1614                                                                 }
    1615 
    1616                                                                 ++param;
    1617                                                         }
    1618 
    1619                                                         // All arguments match!
    1620 
    1621                                                         // Check if parameters are missing
    1622                                                         if ( nextMutex( param, paramEnd ) ) {
    1623                                                                 do {
    1624                                                                         ++n_mutex_param;
    1625                                                                         ++param;
    1626                                                                 } while ( nextMutex( param, paramEnd ) );
    1627 
    1628                                                                 // We ran out of arguments but still have parameters left; this
    1629                                                                 // function doesn't match
    1630                                                                 SemanticError( stmt->location, funcType,
    1631                                                                         toString( "candidate function not viable: too few mutex "
    1632                                                                         "arguments, expected ", n_mutex_param, "\n" ) );
    1633                                                         }
    1634 
    1635                                                         // All parameters match!
    1636 
    1637                                                         // Finish the expressions to tie in proper environments
    1638                                                         finishExpr( func2->expr, resultEnv );
    1639                                                         for ( CandidateRef & arg : argsList ) {
    1640                                                                 finishExpr( arg->expr, resultEnv );
    1641                                                         }
    1642 
    1643                                                         // This is a match, store it and save it for later
    1644                                                         funcCandidates.emplace_back( std::move( func2 ) );
    1645                                                         argsCandidates.emplace_back( std::move( argsList ) );
    1646 
    1647                                                 } catch ( SemanticErrorException & e ) {
    1648                                                         errors.append( e );
    1649                                                 }
    1650                                         }
    1651                                 } catch ( SemanticErrorException & e ) {
    1652                                         errors.append( e );
    1653                                 }
    1654                         }
    1655 
    1656                         // Make sure correct number of arguments
    1657                         if( funcCandidates.empty() ) {
    1658                                 SemanticErrorException top( stmt->location,
    1659                                         "No alternatives for function in call to waitfor" );
    1660                                 top.append( errors );
    1661                                 throw top;
    1662                         }
    1663 
    1664                         if( argsCandidates.empty() ) {
    1665                                 SemanticErrorException top( stmt->location,
    1666                                         "No alternatives for arguments in call to waitfor" );
    1667                                 top.append( errors );
    1668                                 throw top;
    1669                         }
    1670 
    1671                         if( funcCandidates.size() > 1 ) {
    1672                                 SemanticErrorException top( stmt->location,
    1673                                         "Ambiguous function in call to waitfor" );
    1674                                 top.append( errors );
    1675                                 throw top;
    1676                         }
    1677                         if( argsCandidates.size() > 1 ) {
    1678                                 SemanticErrorException top( stmt->location,
    1679                                         "Ambiguous arguments in call to waitfor" );
    1680                                 top.append( errors );
    1681                                 throw top;
    1682                         }
    1683                         // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    1684 
    1685                         // build new clause
    1686                         ast::WaitForStmt::Clause clause2;
    1687 
    1688                         clause2.target.func = funcCandidates.front()->expr;
    1689 
    1690                         clause2.target.args.reserve( clause.target.args.size() );
    1691                         for ( auto arg : argsCandidates.front() ) {
    1692                                 clause2.target.args.emplace_back( std::move( arg->expr ) );
    1693                         }
    1694 
    1695                         // Resolve the conditions as if it were an IfStmt, statements normally
    1696                         clause2.cond = findSingleExpression( clause.cond, symtab );
    1697                         clause2.stmt = clause.stmt->accept( *visitor );
    1698 
    1699                         // set results into stmt
    1700                         auto n = mutate( stmt );
    1701                         n->clauses[i] = std::move( clause2 );
    1702                         stmt = n;
    1703                 }
    1704 
    1705                 if ( stmt->timeout.stmt ) {
    1706                         // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
    1707                         ast::WaitForStmt::Timeout timeout2;
    1708 
    1709                         ast::ptr< ast::Type > target =
    1710                                 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
    1711                         timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab );
    1712                         timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab );
    1713                         timeout2.stmt = stmt->timeout.stmt->accept( *visitor );
    1714 
    1715                         // set results into stmt
    1716                         auto n = mutate( stmt );
    1717                         n->timeout = std::move( timeout2 );
    1718                         stmt = n;
    1719                 }
    1720 
    1721                 if ( stmt->orElse.stmt ) {
    1722                         // resolve the condition like IfStmt, stmts normally
    1723                         ast::WaitForStmt::OrElse orElse2;
    1724 
    1725                         orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab );
    1726                         orElse2.stmt = stmt->orElse.stmt->accept( *visitor );
    1727 
    1728                         // set results into stmt
    1729                         auto n = mutate( stmt );
    1730                         n->orElse = std::move( orElse2 );
    1731                         stmt = n;
    1732                 }
    1733 
    1734                 return stmt;
    1735         }
    1736 
    1737 
    1738 
    1739         const ast::SingleInit * Resolver_new::previsit( const ast::SingleInit * singleInit ) {
    1740                 visit_children = false;
    1741                 // resolve initialization using the possibilities as determined by the `currentObject`
    1742                 // cursor.
    1743                 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    1744                         singleInit->location, singleInit->value, currentObject.getOptions() };
    1745                 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
    1746                 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    1747 
    1748                 // move cursor to the object that is actually initialized
    1749                 currentObject.setNext( initExpr->designation );
    1750 
    1751                 // discard InitExpr wrapper and retain relevant pieces.
    1752                 // `initExpr` may have inferred params in the case where the expression specialized a
    1753                 // function pointer, and newExpr may already have inferParams of its own, so a simple
    1754                 // swap is not sufficient
    1755                 ast::Expr::InferUnion inferred = initExpr->inferred;
    1756                 swap_and_save_env( newExpr, initExpr->expr );
    1757                 newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );
    1758 
    1759                 // get the actual object's type (may not exactly match what comes back from the resolver
    1760                 // due to conversions)
    1761                 const ast::Type * initContext = currentObject.getCurrentType();
    1762 
    1763                 removeExtraneousCast( newExpr, symtab );
    1764 
    1765                 // check if actual object's type is char[]
    1766                 if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {
    1767                         if ( isCharType( at->base ) ) {
    1768                                 // check if the resolved type is char*
    1769                                 if ( auto pt = newExpr->result.as< ast::PointerType >() ) {
    1770                                         if ( isCharType( pt->base ) ) {
    1771                                                 // strip cast if we're initializing a char[] with a char*
    1772                                                 // e.g. char x[] = "hello"
    1773                                                 if ( auto ce = newExpr.as< ast::CastExpr >() ) {
    1774                                                         swap_and_save_env( newExpr, ce->arg );
    1775                                                 }
    1776                                         }
    1777                                 }
    1778                         }
    1779                 }
    1780 
    1781                 // move cursor to next object in preparation for next initializer
    1782                 currentObject.increment();
    1783 
    1784                 // set initializer expression to resolved expression
    1785                 return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );
    1786         }
    1787 
    1788         const ast::ListInit * Resolver_new::previsit( const ast::ListInit * listInit ) {
    1789                 // move cursor into brace-enclosed initializer-list
    1790                 currentObject.enterListInit( listInit->location );
    1791 
    1792                 assert( listInit->designations.size() == listInit->initializers.size() );
    1793                 for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {
    1794                         // iterate designations and initializers in pairs, moving the cursor to the current
    1795                         // designated object and resolving the initializer against that object
    1796                         listInit = ast::mutate_field_index(
    1797                                 listInit, &ast::ListInit::designations, i,
    1798                                 currentObject.findNext( listInit->designations[i] ) );
    1799                         listInit = ast::mutate_field_index(
    1800                                 listInit, &ast::ListInit::initializers, i,
    1801                                 listInit->initializers[i]->accept( *visitor ) );
    1802                 }
    1803 
    1804                 // move cursor out of brace-enclosed initializer-list
    1805                 currentObject.exitListInit();
    1806 
    1807                 visit_children = false;
    1808                 return listInit;
    1809         }
    1810 
    1811         const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {
    1812                 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
    1813                 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
    1814 
    1815                 // found a constructor - can get rid of C-style initializer
    1816                 // xxx - Rob suggests this field is dead code
    1817                 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );
    1818 
    1819                 // intrinsic single-parameter constructors and destructors do nothing. Since this was
    1820                 // implicitly generated, there's no way for it to have side effects, so get rid of it to
    1821                 // clean up generated code
    1822                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
    1823                         ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );
    1824                 }
    1825                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
    1826                         ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );
    1827                 }
    1828 
    1829                 return ctorInit;
    1830         }
    1831 
    1832876} // namespace ResolvExpr
    1833877
Note: See TracChangeset for help on using the changeset viewer.