Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r14755e5 r9ddcee1  
    5050
    5151namespace ResolvExpr {
    52 
    53 namespace {
    54         /// Finds deleted expressions in an expression tree
    55         struct DeleteFinder final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder> {
    56                 const ast::DeletedExpr * result = nullptr;
    57 
    58                 void previsit( const ast::DeletedExpr * expr ) {
    59                         if ( result ) { visit_children = false; }
    60                         else { result = expr; }
    61                 }
    62 
    63                 void previsit( const ast::Expr * expr ) {
    64                         if ( result ) { visit_children = false; }
    65                         if (expr->inferred.hasParams()) {
    66                                 for (auto & imp : expr->inferred.inferParams() ) {
    67                                         imp.second.expr->accept(*visitor);
     52        namespace {
     53                /// Finds deleted expressions in an expression tree
     54                struct DeleteFinder final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder> {
     55                        const ast::DeletedExpr * result = nullptr;
     56
     57                        void previsit( const ast::DeletedExpr * expr ) {
     58                                if ( result ) { visit_children = false; }
     59                                else { result = expr; }
     60                        }
     61
     62                        void previsit( const ast::Expr * expr ) {
     63                                if ( result ) { visit_children = false; }
     64                                if (expr->inferred.hasParams()) {
     65                                        for (auto & imp : expr->inferred.inferParams() ) {
     66                                                imp.second.expr->accept(*visitor);
     67                                        }
    6868                                }
    6969                        }
    70                 }
    71         };
    72 
    73         struct ResolveDesignators final : public ast::WithShortCircuiting {
    74                 ResolveContext& context;
    75                 bool result = false;
    76 
    77                 ResolveDesignators( ResolveContext& _context ): context(_context) {};
    78 
    79                 void previsit( const ast::Node * ) {
    80                         // short circuit if we already know there are designations
    81                         if ( result ) visit_children = false;
    82                 }
    83 
    84                 void previsit( const ast::Designation * des ) {
    85                         if ( result ) visit_children = false;
    86                         else if ( ! des->designators.empty() ) {
    87                                 if ( (des->designators.size() == 1) ) {
    88                                         const ast::Expr * designator = des->designators.at(0);
    89                                         if ( const ast::NameExpr * designatorName = dynamic_cast<const ast::NameExpr *>(designator) ) {
    90                                                 auto candidates = context.symtab.lookupId(designatorName->name);
    91                                                 for ( auto candidate : candidates ) {
    92                                                         if ( dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type()) ) {
    93                                                                 result = true;
    94                                                                 break;
     70                };
     71
     72                struct ResolveDesignators final : public ast::WithShortCircuiting {
     73                        ResolveContext& context;
     74                        bool result = false;
     75
     76                        ResolveDesignators( ResolveContext& _context ): context{_context} {};
     77
     78                        void previsit( const ast::Node * ) {
     79                                // short circuit if we already know there are designations
     80                                if ( result ) visit_children = false;
     81                        }
     82
     83                        void previsit( const ast::Designation * des ) {
     84                                if ( result ) visit_children = false;
     85                                else if ( ! des->designators.empty() ) {
     86                                        if ( (des->designators.size() == 1) ) {
     87                                                const ast::Expr * designator = des->designators.at(0);
     88                                                if ( const ast::NameExpr * designatorName = dynamic_cast<const ast::NameExpr *>(designator) ) {
     89                                                        auto candidates = context.symtab.lookupId(designatorName->name);
     90                                                        for ( auto candidate : candidates ) {
     91                                                                if ( dynamic_cast<const ast::EnumInstType *>(candidate.id->get_type()) ) {
     92                                                                        result = true;
     93                                                                        break;
     94                                                                }
    9595                                                        }
    9696                                                }
    9797                                        }
     98                                        visit_children = false;
    9899                                }
    99                                 visit_children = false;
    100                         }
    101                 }
    102         };
    103 } // anonymous namespace
    104 
    105 /// Check if this expression is or includes a deleted expression
    106 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
    107         return ast::Pass<DeleteFinder>::read( expr );
    108 }
    109 
    110 namespace {
    111         /// always-accept candidate filter
    112         bool anyCandidate( const Candidate & ) { return true; }
    113 
    114         /// Calls the CandidateFinder and finds the single best candidate
    115         CandidateRef findUnfinishedKindExpression(
    116                 const ast::Expr * untyped, const ResolveContext & context, const std::string & kind,
    117                 std::function<bool(const Candidate &)> pred = anyCandidate, ResolveMode mode = {}
    118         ) {
    119                 if ( ! untyped ) return nullptr;
    120 
    121                 // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    122                 static unsigned recursion_level = 0;
    123 
    124                 ++recursion_level;
    125                 ast::TypeEnvironment env;
    126                 CandidateFinder finder( context, env );
    127                 finder.allowVoid = true;
    128                 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    129                 --recursion_level;
    130 
    131                 // produce a filtered list of candidates
    132                 CandidateList candidates;
    133                 for ( auto & cand : finder.candidates ) {
    134                         if ( pred( *cand ) ) { candidates.emplace_back( cand ); }
    135                 }
    136 
    137                 // produce invalid error if no candidates
    138                 if ( candidates.empty() ) {
    139                         SemanticError( untyped,
    140                                 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),
    141                                 "expression: ") );
    142                 }
    143 
    144                 // search for cheapest candidate
    145                 CandidateList winners;
    146                 bool seen_undeleted = false;
    147                 for ( CandidateRef & cand : candidates ) {
    148                         int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );
    149 
    150                         if ( c > 0 ) continue;  // skip more expensive than winner
    151 
    152                         if ( c < 0 ) {
    153                                 // reset on new cheapest
    154                                 seen_undeleted = ! findDeletedExpr( cand->expr );
    155                                 winners.clear();
    156                         } else /* if ( c == 0 ) */ {
    157                                 if ( findDeletedExpr( cand->expr ) ) {
    158                                         // skip deleted expression if already seen one equivalent-cost not
    159                                         if ( seen_undeleted ) continue;
    160                                 } else if ( ! seen_undeleted ) {
    161                                         // replace list of equivalent-cost deleted expressions with one non-deleted
     100                        }
     101                };
     102        } // anonymous namespace
     103        /// Check if this expression is or includes a deleted expression
     104        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
     105                return ast::Pass<DeleteFinder>::read( expr );
     106        }
     107
     108        namespace {
     109                /// always-accept candidate filter
     110                bool anyCandidate( const Candidate & ) { return true; }
     111
     112                /// Calls the CandidateFinder and finds the single best candidate
     113                CandidateRef findUnfinishedKindExpression(
     114                        const ast::Expr * untyped, const ResolveContext & context, const std::string & kind,
     115                        std::function<bool(const Candidate &)> pred = anyCandidate, ResolveMode mode = {}
     116                ) {
     117                        if ( ! untyped ) return nullptr;
     118
     119                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
     120                        static unsigned recursion_level = 0;
     121
     122                        ++recursion_level;
     123                        ast::TypeEnvironment env;
     124                        CandidateFinder finder( context, env );
     125                        finder.allowVoid = true;
     126                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     127                        --recursion_level;
     128
     129                        // produce a filtered list of candidates
     130                        CandidateList candidates;
     131                        for ( auto & cand : finder.candidates ) {
     132                                if ( pred( *cand ) ) { candidates.emplace_back( cand ); }
     133                        }
     134
     135                        // produce invalid error if no candidates
     136                        if ( candidates.empty() ) {
     137                                SemanticError( untyped,
     138                                        toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),
     139                                        "expression: ") );
     140                        }
     141
     142                        // search for cheapest candidate
     143                        CandidateList winners;
     144                        bool seen_undeleted = false;
     145                        for ( CandidateRef & cand : candidates ) {
     146                                int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );
     147
     148                                if ( c > 0 ) continue;  // skip more expensive than winner
     149
     150                                if ( c < 0 ) {
     151                                        // reset on new cheapest
     152                                        seen_undeleted = ! findDeletedExpr( cand->expr );
    162153                                        winners.clear();
    163                                         seen_undeleted = true;
    164                                 }
    165                         }
    166 
    167                         winners.emplace_back( std::move( cand ) );
    168                 }
    169 
    170                 // promote candidate.cvtCost to .cost
    171                 // promoteCvtCost( winners );
    172 
    173                 // produce ambiguous errors, if applicable
    174                 if ( winners.size() != 1 ) {
    175                         std::ostringstream stream;
    176                         stream << "Cannot choose between " << winners.size() << " alternatives for "
    177                                 << kind << (kind != "" ? " " : "") << "expression\n";
    178                         ast::print( stream, untyped );
    179                         stream << " Alternatives are:\n";
    180                         print( stream, winners, 1 );
    181                         SemanticError( untyped->location, stream.str() );
    182                 }
    183 
    184                 // single selected choice
    185                 CandidateRef & choice = winners.front();
    186 
    187                 // fail on only expression deleted
    188                 if ( ! seen_undeleted ) {
    189                         SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "
    190                         "includes deleted identifier in " );
    191                 }
    192 
    193                 return std::move( choice );
    194         }
    195 
    196         /// Strips extraneous casts out of an expression
    197         struct StripCasts final {
    198                 const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
    199                         if (
    200                                 castExpr->isGenerated == ast::GeneratedCast
    201                                 && typesCompatible( castExpr->arg->result, castExpr->result )
    202                         ) {
    203                                 // generated cast is the same type as its argument, remove it after keeping env
    204                                 return ast::mutate_field(
    205                                         castExpr->arg.get(), &ast::Expr::env, castExpr->env );
    206                         }
    207                         return castExpr;
    208                 }
    209 
    210                 static void strip( ast::ptr< ast::Expr > & expr ) {
    211                         ast::Pass< StripCasts > stripper;
    212                         expr = expr->accept( stripper );
    213                 }
    214         };
    215 
    216         /// Swaps argument into expression pointer, saving original environment
    217         void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {
    218                 ast::ptr< ast::TypeSubstitution > env = expr->env;
    219                 expr.set_and_mutate( newExpr )->env = env;
    220         }
    221 
    222         /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
    223         void removeExtraneousCast( ast::ptr<ast::Expr> & expr ) {
    224                 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
    225                         if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) {
    226                                 // cast is to the same type as its argument, remove it
    227                                 swap_and_save_env( expr, castExpr->arg );
    228                         }
    229                 }
    230         }
    231 
    232 } // anonymous namespace
    233 
    234 /// Establish post-resolver invariants for expressions
    235 void finishExpr(
    236         ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
    237         const ast::TypeSubstitution * oldenv = nullptr
    238 ) {
    239         // set up new type substitution for expression
    240         ast::ptr< ast::TypeSubstitution > newenv =
    241                  oldenv ? oldenv : new ast::TypeSubstitution{};
    242         env.writeToSubstitution( *newenv.get_and_mutate() );
    243         expr.get_and_mutate()->env = std::move( newenv );
    244         // remove unncecessary casts
    245         StripCasts::strip( expr );
    246 }
    247 
    248 ast::ptr< ast::Expr > resolveInVoidContext(
    249         const ast::Expr * expr, const ResolveContext & context,
    250         ast::TypeEnvironment & env
    251 ) {
    252         assertf( expr, "expected a non-null expression" );
    253 
    254         // set up and resolve expression cast to void
    255         ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    256         CandidateRef choice = findUnfinishedKindExpression(
    257                 untyped, context, "", anyCandidate, ResolveMode::withAdjustment() );
    258 
    259         // a cast expression has either 0 or 1 interpretations (by language rules);
    260         // if 0, an exception has already been thrown, and this code will not run
    261         const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
    262         env = std::move( choice->env );
    263 
    264         return castExpr->arg;
    265 }
    266 
    267 /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    268 /// context.
    269 ast::ptr< ast::Expr > findVoidExpression(
    270         const ast::Expr * untyped, const ResolveContext & context
    271 ) {
    272         ast::TypeEnvironment env;
    273         ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env );
    274         finishExpr( newExpr, env, untyped->env );
    275         return newExpr;
    276 }
    277 
    278 namespace {
    279         /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    280         /// lowest cost, returning the resolved version
    281         ast::ptr< ast::Expr > findKindExpression(
    282                 const ast::Expr * untyped, const ResolveContext & context,
    283                 std::function<bool(const Candidate &)> pred = anyCandidate,
    284                 const std::string & kind = "", ResolveMode mode = {}
    285         ) {
    286                 if ( ! untyped ) return {};
    287                 CandidateRef choice =
    288                         findUnfinishedKindExpression( untyped, context, kind, pred, mode );
    289                 ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
    290                 return std::move( choice->expr );
    291         }
    292 
    293         /// Resolve `untyped` to the single expression whose candidate is the best match
    294         ast::ptr< ast::Expr > findSingleExpression(
    295                 const ast::Expr * untyped, const ResolveContext & context
    296         ) {
    297                 Stats::ResolveTime::start( untyped );
    298                 auto res = findKindExpression( untyped, context );
    299                 Stats::ResolveTime::stop();
    300                 return res;
    301         }
    302 } // anonymous namespace
    303 
    304 ast::ptr< ast::Expr > findSingleExpression(
    305         const ast::Expr * untyped, const ast::Type * type,
    306         const ResolveContext & context
    307 ) {
    308         assert( untyped && type );
    309         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    310         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
    311         removeExtraneousCast( newExpr );
    312         return newExpr;
    313 }
    314 
    315 namespace {
    316         bool structOrUnion( const Candidate & i ) {
    317                 const ast::Type * t = i.expr->result->stripReferences();
    318                 return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
    319         }
    320         /// Predicate for "Candidate has integral type"
    321         bool hasIntegralType( const Candidate & i ) {
    322                 const ast::Type * type = i.expr->result;
    323 
    324                 if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {
    325                         return bt->isInteger();
    326                 } else if (
    327                         dynamic_cast< const ast::EnumInstType * >( type )
    328                         || dynamic_cast< const ast::ZeroType * >( type )
    329                         || dynamic_cast< const ast::OneType * >( type )
    330                 ) {
    331                         return true;
    332                 } else return false;
    333         }
    334 
    335         /// Resolve `untyped` as an integral expression, returning the resolved version
    336         ast::ptr< ast::Expr > findIntegralExpression(
    337                 const ast::Expr * untyped, const ResolveContext & context
    338         ) {
    339                 return findKindExpression( untyped, context, hasIntegralType, "condition" );
    340         }
    341 
    342         /// check if a type is a character type
    343         bool isCharType( const ast::Type * t ) {
    344                 if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {
    345                         return bt->kind == ast::BasicType::Char
    346                                 || bt->kind == ast::BasicType::SignedChar
    347                                 || bt->kind == ast::BasicType::UnsignedChar;
    348                 }
    349                 return false;
    350         }
    351 
    352         /// Advance a type itertor to the next mutex parameter
    353         template<typename Iter>
    354         inline bool nextMutex( Iter & it, const Iter & end ) {
    355                 while ( it != end && ! (*it)->is_mutex() ) { ++it; }
    356                 return it != end;
    357         }
    358 }
    359 
    360 class Resolver final
    361 : public ast::WithSymbolTable, public ast::WithGuards,
    362   public ast::WithVisitorRef<Resolver>, public ast::WithShortCircuiting,
    363   public ast::WithStmtsToAdd<> {
    364 
    365         ast::ptr< ast::Type > functionReturn = nullptr;
    366         ast::CurrentObject currentObject;
    367         // for work previously in GenInit
    368         static InitTweak::ManagedTypes managedTypes;
    369         ResolveContext context;
    370 
    371         bool inEnumDecl = false;
    372 
    373 public:
    374         static size_t traceId;
    375         Resolver( const ast::TranslationGlobal & global ) :
    376                 ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd),
    377                 context{ symtab, global } {}
    378         Resolver( const ResolveContext & context ) :
    379                 ast::WithSymbolTable{ context.symtab },
    380                 context{ symtab, context.global } {}
    381 
    382         const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
    383         const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
    384         const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
    385         void previsit( const ast::AggregateDecl * );
    386         void previsit( const ast::StructDecl * );
    387         void previsit( const ast::EnumDecl * );
    388         const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
    389 
    390         const ast::ArrayType * previsit( const ast::ArrayType * );
    391         const ast::PointerType * previsit( const ast::PointerType * );
    392 
    393         const ast::ExprStmt *        previsit( const ast::ExprStmt * );
    394         const ast::AsmExpr *         previsit( const ast::AsmExpr * );
    395         const ast::AsmStmt *         previsit( const ast::AsmStmt * );
    396         const ast::IfStmt *          previsit( const ast::IfStmt * );
    397         const ast::WhileDoStmt *     previsit( const ast::WhileDoStmt * );
    398         const ast::ForStmt *         previsit( const ast::ForStmt * );
    399         const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
    400         const ast::CaseClause *      previsit( const ast::CaseClause * );
    401         const ast::BranchStmt *      previsit( const ast::BranchStmt * );
    402         const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
    403         const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
    404         const ast::CatchClause *     previsit( const ast::CatchClause * );
    405         const ast::CatchClause *     postvisit( const ast::CatchClause * );
    406         const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
    407         const ast::WithStmt *        previsit( const ast::WithStmt * );
    408 
    409         const ast::SingleInit *      previsit( const ast::SingleInit * );
    410         const ast::ListInit *        previsit( const ast::ListInit * );
    411         const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
    412 
    413         void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
    414 
    415         void beginScope() { managedTypes.beginScope(); }
    416         void endScope() { managedTypes.endScope(); }
    417         bool on_error(ast::ptr<ast::Decl> & decl);
    418 };
    419 // size_t Resolver::traceId = Stats::Heap::new_stacktrace_id("Resolver");
    420 
    421 InitTweak::ManagedTypes Resolver::managedTypes;
    422 
    423 void resolve( ast::TranslationUnit& translationUnit ) {
    424         ast::Pass< Resolver >::run( translationUnit, translationUnit.global );
    425 }
    426 
    427 ast::ptr< ast::Init > resolveCtorInit(
    428         const ast::ConstructorInit * ctorInit, const ResolveContext & context
    429 ) {
    430         assert( ctorInit );
    431         ast::Pass< Resolver > resolver( context );
    432         return ctorInit->accept( resolver );
    433 }
    434 
    435 const ast::Expr * resolveStmtExpr(
    436         const ast::StmtExpr * stmtExpr, const ResolveContext & context
    437 ) {
    438         assert( stmtExpr );
    439         ast::Pass< Resolver > resolver( context );
    440         auto ret = mutate(stmtExpr->accept(resolver));
    441         strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
    442         return ret;
    443 }
    444 
    445 namespace {
    446         const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) {
    447                 std::string name = attr->normalizedName();
    448                 if (name == "constructor" || name == "destructor") {
    449                         if (attr->params.size() == 1) {
    450                                 auto arg = attr->params.front();
    451                                 auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context );
    452                                 auto result = eval(arg);
    453 
    454                                 auto mutAttr = mutate(attr);
    455                                 mutAttr->params.front() = resolved;
    456                                 if (! result.hasKnownValue) {
    457                                         SemanticWarning(loc, Warning::GccAttributes,
    458                                                 toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
    459                                 }
    460                                 else {
    461                                         auto priority = result.knownValue;
    462                                         if (priority < 101) {
    463                                                 SemanticWarning(loc, Warning::GccAttributes,
    464                                                         toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
    465                                         } else if (priority < 201 && ! buildingLibrary()) {
    466                                                 SemanticWarning(loc, Warning::GccAttributes,
    467                                                         toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
     154                                } else /* if ( c == 0 ) */ {
     155                                        if ( findDeletedExpr( cand->expr ) ) {
     156                                                // skip deleted expression if already seen one equivalent-cost not
     157                                                if ( seen_undeleted ) continue;
     158                                        } else if ( ! seen_undeleted ) {
     159                                                // replace list of equivalent-cost deleted expressions with one non-deleted
     160                                                winners.clear();
     161                                                seen_undeleted = true;
    468162                                        }
    469163                                }
    470                                 return mutAttr;
    471                         } else if (attr->params.size() > 1) {
    472                                 SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
     164
     165                                winners.emplace_back( std::move( cand ) );
     166                        }
     167
     168                        // promote candidate.cvtCost to .cost
     169                        // promoteCvtCost( winners );
     170
     171                        // produce ambiguous errors, if applicable
     172                        if ( winners.size() != 1 ) {
     173                                std::ostringstream stream;
     174                                stream << "Cannot choose between " << winners.size() << " alternatives for "
     175                                        << kind << (kind != "" ? " " : "") << "expression\n";
     176                                ast::print( stream, untyped );
     177                                stream << " Alternatives are:\n";
     178                                print( stream, winners, 1 );
     179                                SemanticError( untyped->location, stream.str() );
     180                        }
     181
     182                        // single selected choice
     183                        CandidateRef & choice = winners.front();
     184
     185                        // fail on only expression deleted
     186                        if ( ! seen_undeleted ) {
     187                                SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "
     188                                "includes deleted identifier in " );
     189                        }
     190
     191                        return std::move( choice );
     192                }
     193
     194                /// Strips extraneous casts out of an expression
     195                struct StripCasts final {
     196                        const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
     197                                if (
     198                                        castExpr->isGenerated == ast::GeneratedCast
     199                                        && typesCompatible( castExpr->arg->result, castExpr->result )
     200                                ) {
     201                                        // generated cast is the same type as its argument, remove it after keeping env
     202                                        return ast::mutate_field(
     203                                                castExpr->arg.get(), &ast::Expr::env, castExpr->env );
     204                                }
     205                                return castExpr;
     206                        }
     207
     208                        static void strip( ast::ptr< ast::Expr > & expr ) {
     209                                ast::Pass< StripCasts > stripper;
     210                                expr = expr->accept( stripper );
     211                        }
     212                };
     213
     214                /// Swaps argument into expression pointer, saving original environment
     215                void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {
     216                        ast::ptr< ast::TypeSubstitution > env = expr->env;
     217                        expr.set_and_mutate( newExpr )->env = env;
     218                }
     219
     220                /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
     221                void removeExtraneousCast( ast::ptr<ast::Expr> & expr ) {
     222                        if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
     223                                if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) {
     224                                        // cast is to the same type as its argument, remove it
     225                                        swap_and_save_env( expr, castExpr->arg );
     226                                }
     227                        }
     228                }
     229
     230
     231        } // anonymous namespace
     232/// Establish post-resolver invariants for expressions
     233                void finishExpr(
     234                        ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
     235                        const ast::TypeSubstitution * oldenv = nullptr
     236                ) {
     237                        // set up new type substitution for expression
     238                        ast::ptr< ast::TypeSubstitution > newenv =
     239                                 oldenv ? oldenv : new ast::TypeSubstitution{};
     240                        env.writeToSubstitution( *newenv.get_and_mutate() );
     241                        expr.get_and_mutate()->env = std::move( newenv );
     242                        // remove unncecessary casts
     243                        StripCasts::strip( expr );
     244                }
     245
     246        ast::ptr< ast::Expr > resolveInVoidContext(
     247                const ast::Expr * expr, const ResolveContext & context,
     248                ast::TypeEnvironment & env
     249        ) {
     250                assertf( expr, "expected a non-null expression" );
     251
     252                // set up and resolve expression cast to void
     253                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
     254                CandidateRef choice = findUnfinishedKindExpression(
     255                        untyped, context, "", anyCandidate, ResolveMode::withAdjustment() );
     256
     257                // a cast expression has either 0 or 1 interpretations (by language rules);
     258                // if 0, an exception has already been thrown, and this code will not run
     259                const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
     260                env = std::move( choice->env );
     261
     262                return castExpr->arg;
     263        }
     264
     265        /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
     266                /// context.
     267                ast::ptr< ast::Expr > findVoidExpression(
     268                        const ast::Expr * untyped, const ResolveContext & context
     269                ) {
     270                        ast::TypeEnvironment env;
     271                        ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env );
     272                        finishExpr( newExpr, env, untyped->env );
     273                        return newExpr;
     274                }
     275
     276        namespace {
     277
     278
     279                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
     280                /// lowest cost, returning the resolved version
     281                ast::ptr< ast::Expr > findKindExpression(
     282                        const ast::Expr * untyped, const ResolveContext & context,
     283                        std::function<bool(const Candidate &)> pred = anyCandidate,
     284                        const std::string & kind = "", ResolveMode mode = {}
     285                ) {
     286                        if ( ! untyped ) return {};
     287                        CandidateRef choice =
     288                                findUnfinishedKindExpression( untyped, context, kind, pred, mode );
     289                        ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
     290                        return std::move( choice->expr );
     291                }
     292
     293                /// Resolve `untyped` to the single expression whose candidate is the best match
     294                ast::ptr< ast::Expr > findSingleExpression(
     295                        const ast::Expr * untyped, const ResolveContext & context
     296                ) {
     297                        Stats::ResolveTime::start( untyped );
     298                        auto res = findKindExpression( untyped, context );
     299                        Stats::ResolveTime::stop();
     300                        return res;
     301                }
     302        } // anonymous namespace
     303
     304        ast::ptr< ast::Expr > findSingleExpression(
     305                const ast::Expr * untyped, const ast::Type * type,
     306                const ResolveContext & context
     307        ) {
     308                assert( untyped && type );
     309                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
     310                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
     311                removeExtraneousCast( newExpr );
     312                return newExpr;
     313        }
     314
     315        namespace {
     316                bool structOrUnion( const Candidate & i ) {
     317                        const ast::Type * t = i.expr->result->stripReferences();
     318                        return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
     319                }
     320                /// Predicate for "Candidate has integral type"
     321                bool hasIntegralType( const Candidate & i ) {
     322                        const ast::Type * type = i.expr->result;
     323
     324                        if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {
     325                                return bt->isInteger();
     326                        } else if (
     327                                dynamic_cast< const ast::EnumInstType * >( type )
     328                                || dynamic_cast< const ast::ZeroType * >( type )
     329                                || dynamic_cast< const ast::OneType * >( type )
     330                        ) {
     331                                return true;
     332                        } else return false;
     333                }
     334
     335                /// Resolve `untyped` as an integral expression, returning the resolved version
     336                ast::ptr< ast::Expr > findIntegralExpression(
     337                        const ast::Expr * untyped, const ResolveContext & context
     338                ) {
     339                        return findKindExpression( untyped, context, hasIntegralType, "condition" );
     340                }
     341
     342                /// check if a type is a character type
     343                bool isCharType( const ast::Type * t ) {
     344                        if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {
     345                                return bt->kind == ast::BasicType::Char
     346                                        || bt->kind == ast::BasicType::SignedChar
     347                                        || bt->kind == ast::BasicType::UnsignedChar;
     348                        }
     349                        return false;
     350                }
     351
     352                /// Advance a type itertor to the next mutex parameter
     353                template<typename Iter>
     354                inline bool nextMutex( Iter & it, const Iter & end ) {
     355                        while ( it != end && ! (*it)->is_mutex() ) { ++it; }
     356                        return it != end;
     357                }
     358        }
     359
     360        class Resolver final
     361        : public ast::WithSymbolTable, public ast::WithGuards,
     362          public ast::WithVisitorRef<Resolver>, public ast::WithShortCircuiting,
     363          public ast::WithStmtsToAdd<> {
     364
     365                ast::ptr< ast::Type > functionReturn = nullptr;
     366                ast::CurrentObject currentObject;
     367                // for work previously in GenInit
     368                static InitTweak::ManagedTypes managedTypes;
     369                ResolveContext context;
     370
     371                bool inEnumDecl = false;
     372
     373        public:
     374                static size_t traceId;
     375                Resolver( const ast::TranslationGlobal & global ) :
     376                        ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd),
     377                        context{ symtab, global } {}
     378                Resolver( const ResolveContext & context ) :
     379                        ast::WithSymbolTable{ context.symtab },
     380                        context{ symtab, context.global } {}
     381
     382                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
     383                const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
     384                const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
     385                void previsit( const ast::AggregateDecl * );
     386                void previsit( const ast::StructDecl * );
     387                void previsit( const ast::EnumDecl * );
     388                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
     389
     390                const ast::ArrayType * previsit( const ast::ArrayType * );
     391                const ast::PointerType * previsit( const ast::PointerType * );
     392
     393                const ast::ExprStmt *        previsit( const ast::ExprStmt * );
     394                const ast::AsmExpr *         previsit( const ast::AsmExpr * );
     395                const ast::AsmStmt *         previsit( const ast::AsmStmt * );
     396                const ast::IfStmt *          previsit( const ast::IfStmt * );
     397                const ast::WhileDoStmt *     previsit( const ast::WhileDoStmt * );
     398                const ast::ForStmt *         previsit( const ast::ForStmt * );
     399                const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
     400                const ast::CaseClause *      previsit( const ast::CaseClause * );
     401                const ast::BranchStmt *      previsit( const ast::BranchStmt * );
     402                const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
     403                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
     404                const ast::CatchClause *     previsit( const ast::CatchClause * );
     405                const ast::CatchClause *     postvisit( const ast::CatchClause * );
     406                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
     407                const ast::WithStmt *        previsit( const ast::WithStmt * );
     408
     409                const ast::SingleInit *      previsit( const ast::SingleInit * );
     410                const ast::ListInit *        previsit( const ast::ListInit * );
     411                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
     412
     413                void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
     414
     415                void beginScope() { managedTypes.beginScope(); }
     416                void endScope() { managedTypes.endScope(); }
     417                bool on_error(ast::ptr<ast::Decl> & decl);
     418        };
     419        // size_t Resolver::traceId = Stats::Heap::new_stacktrace_id("Resolver");
     420
     421        InitTweak::ManagedTypes Resolver::managedTypes;
     422
     423        void resolve( ast::TranslationUnit& translationUnit ) {
     424                ast::Pass< Resolver >::run( translationUnit, translationUnit.global );
     425        }
     426
     427        ast::ptr< ast::Init > resolveCtorInit(
     428                const ast::ConstructorInit * ctorInit, const ResolveContext & context
     429        ) {
     430                assert( ctorInit );
     431                ast::Pass< Resolver > resolver( context );
     432                return ctorInit->accept( resolver );
     433        }
     434
     435        const ast::Expr * resolveStmtExpr(
     436                const ast::StmtExpr * stmtExpr, const ResolveContext & context
     437        ) {
     438                assert( stmtExpr );
     439                ast::Pass< Resolver > resolver( context );
     440                auto ret = mutate(stmtExpr->accept(resolver));
     441                strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
     442                return ret;
     443        }
     444
     445        namespace {
     446                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) {
     447                        std::string name = attr->normalizedName();
     448                        if (name == "constructor" || name == "destructor") {
     449                                if (attr->params.size() == 1) {
     450                                        auto arg = attr->params.front();
     451                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context );
     452                                        auto result = eval(arg);
     453
     454                                        auto mutAttr = mutate(attr);
     455                                        mutAttr->params.front() = resolved;
     456                                        if (! result.hasKnownValue) {
     457                                                SemanticWarning(loc, Warning::GccAttributes,
     458                                                        toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
     459                                        }
     460                                        else {
     461                                                auto priority = result.knownValue;
     462                                                if (priority < 101) {
     463                                                        SemanticWarning(loc, Warning::GccAttributes,
     464                                                                toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
     465                                                } else if (priority < 201 && ! buildingLibrary()) {
     466                                                        SemanticWarning(loc, Warning::GccAttributes,
     467                                                                toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
     468                                                }
     469                                        }
     470                                        return mutAttr;
     471                                } else if (attr->params.size() > 1) {
     472                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
     473                                } else {
     474                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
     475                                }
     476                        }
     477                        return attr;
     478                }
     479        }
     480
     481        const ast::FunctionDecl * Resolver::previsit( const ast::FunctionDecl * functionDecl ) {
     482                GuardValue( functionReturn );
     483
     484                assert (functionDecl->unique());
     485                if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
     486                        SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
     487                }
     488
     489                if (!functionDecl->isTypeFixed) {
     490                        auto mutDecl = mutate(functionDecl);
     491                        auto mutType = mutDecl->type.get_and_mutate();
     492
     493                        for (auto & attr: mutDecl->attributes) {
     494                                attr = handleAttribute(mutDecl->location, attr, context );
     495                        }
     496
     497                        // handle assertions
     498
     499                        symtab.enterScope();
     500                        mutType->forall.clear();
     501                        mutType->assertions.clear();
     502                        for (auto & typeParam : mutDecl->type_params) {
     503                                symtab.addType(typeParam);
     504                                mutType->forall.emplace_back(new ast::TypeInstType(typeParam));
     505                        }
     506                        for (auto & asst : mutDecl->assertions) {
     507                                asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context);
     508                                symtab.addId(asst);
     509                                mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
     510                        }
     511
     512                        // temporarily adds params to symbol table.
     513                        // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
     514
     515                        std::vector<ast::ptr<ast::Type>> paramTypes;
     516                        std::vector<ast::ptr<ast::Type>> returnTypes;
     517
     518                        for (auto & param : mutDecl->params) {
     519                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context);
     520                                symtab.addId(param);
     521                                paramTypes.emplace_back(param->get_type());
     522                        }
     523                        for (auto & ret : mutDecl->returns) {
     524                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context);
     525                                returnTypes.emplace_back(ret->get_type());
     526                        }
     527                        // since function type in decl is just a view of param types, need to update that as well
     528                        mutType->params = std::move(paramTypes);
     529                        mutType->returns = std::move(returnTypes);
     530
     531                        auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID));
     532
     533                        std::list<ast::ptr<ast::Stmt>> newStmts;
     534                        resolveWithExprs (mutDecl->withExprs, newStmts);
     535
     536                        if (mutDecl->stmts) {
     537                                auto mutStmt = mutDecl->stmts.get_and_mutate();
     538                                mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
     539                                mutDecl->stmts = mutStmt;
     540                        }
     541
     542                        symtab.leaveScope();
     543
     544                        mutDecl->type = renamedType;
     545                        mutDecl->mangleName = Mangle::mangle(mutDecl);
     546                        mutDecl->isTypeFixed = true;
     547                        functionDecl = mutDecl;
     548                }
     549                managedTypes.handleDWT(functionDecl);
     550
     551                functionReturn = extractResultType( functionDecl->type );
     552                return functionDecl;
     553        }
     554
     555        const ast::FunctionDecl * Resolver::postvisit( const ast::FunctionDecl * functionDecl ) {
     556                // default value expressions have an environment which shouldn't be there and trips up
     557                // later passes.
     558                assert( functionDecl->unique() );
     559                ast::FunctionType * mutType = mutate( functionDecl->type.get() );
     560
     561                for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) {
     562                        if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {
     563                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
     564                                        if ( init->value->env == nullptr ) continue;
     565                                        // clone initializer minus the initializer environment
     566                                        auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() );
     567                                        auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() );
     568                                        auto mutValue = mutate( mutInit->value.get() );
     569
     570                                        mutValue->env = nullptr;
     571                                        mutInit->value = mutValue;
     572                                        mutParam->init = mutInit;
     573                                        mutType->params[i] = mutParam;
     574
     575                                        assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env);
     576                                }
     577                        }
     578                }
     579                mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
     580                return functionDecl;
     581        }
     582
     583        const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) {
     584                // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
     585                // class-variable `initContext` is changed multiple times because the LHS is analyzed
     586                // twice. The second analysis changes `initContext` because a function type can contain
     587                // object declarations in the return and parameter types. Therefore each value of
     588                // `initContext` is retained so the type on the first analysis is preserved and used for
     589                // selecting the RHS.
     590                GuardValue( currentObject );
     591
     592                if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
     593                        // enumerator initializers should not use the enum type to initialize, since the
     594                        // enum type is still incomplete at this point. Use `int` instead.
     595
     596                        if ( auto enumBase = dynamic_cast< const ast::EnumInstType * >
     597                                ( objectDecl->get_type() )->base->base ) {
     598                                objectDecl = fixObjectType( objectDecl, context );
     599                                currentObject = ast::CurrentObject{
     600                                        objectDecl->location,
     601                                        enumBase
     602                                };
    473603                        } else {
    474                                 SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
    475                         }
    476                 }
    477                 return attr;
    478         }
    479 }
    480 
    481 const ast::FunctionDecl * Resolver::previsit( const ast::FunctionDecl * functionDecl ) {
    482         GuardValue( functionReturn );
    483 
    484         assert (functionDecl->unique());
    485         if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
    486                 SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
    487         }
    488 
    489         if (!functionDecl->isTypeFixed) {
    490                 auto mutDecl = mutate(functionDecl);
    491                 auto mutType = mutDecl->type.get_and_mutate();
    492 
    493                 for (auto & attr: mutDecl->attributes) {
    494                         attr = handleAttribute(mutDecl->location, attr, context );
    495                 }
    496 
    497                 // handle assertions
    498 
    499                 symtab.enterScope();
    500                 mutType->forall.clear();
    501                 mutType->assertions.clear();
    502                 for (auto & typeParam : mutDecl->type_params) {
    503                         symtab.addType(typeParam);
    504                         mutType->forall.emplace_back(new ast::TypeInstType(typeParam));
    505                 }
    506                 for (auto & asst : mutDecl->assertions) {
    507                         asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context);
    508                         symtab.addId(asst);
    509                         mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
    510                 }
    511 
    512                 // temporarily adds params to symbol table.
    513                 // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
    514 
    515                 std::vector<ast::ptr<ast::Type>> paramTypes;
    516                 std::vector<ast::ptr<ast::Type>> returnTypes;
    517 
    518                 for (auto & param : mutDecl->params) {
    519                         param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context);
    520                         symtab.addId(param);
    521                         paramTypes.emplace_back(param->get_type());
    522                 }
    523                 for (auto & ret : mutDecl->returns) {
    524                         ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context);
    525                         returnTypes.emplace_back(ret->get_type());
    526                 }
    527                 // since function type in decl is just a view of param types, need to update that as well
    528                 mutType->params = std::move(paramTypes);
    529                 mutType->returns = std::move(returnTypes);
    530 
    531                 auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID));
    532 
    533                 std::list<ast::ptr<ast::Stmt>> newStmts;
    534                 resolveWithExprs (mutDecl->withExprs, newStmts);
    535 
    536                 if (mutDecl->stmts) {
    537                         auto mutStmt = mutDecl->stmts.get_and_mutate();
    538                         mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
    539                         mutDecl->stmts = mutStmt;
    540                 }
    541 
    542                 symtab.leaveScope();
    543 
    544                 mutDecl->type = renamedType;
    545                 mutDecl->mangleName = Mangle::mangle(mutDecl);
    546                 mutDecl->isTypeFixed = true;
    547                 functionDecl = mutDecl;
    548         }
    549         managedTypes.handleDWT(functionDecl);
    550 
    551         functionReturn = extractResultType( functionDecl->type );
    552         return functionDecl;
    553 }
    554 
    555 const ast::FunctionDecl * Resolver::postvisit( const ast::FunctionDecl * functionDecl ) {
    556         // default value expressions have an environment which shouldn't be there and trips up
    557         // later passes.
    558         assert( functionDecl->unique() );
    559         ast::FunctionType * mutType = mutate( functionDecl->type.get() );
    560 
    561         for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) {
    562                 if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {
    563                         if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    564                                 if ( init->value->env == nullptr ) continue;
    565                                 // clone initializer minus the initializer environment
    566                                 auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() );
    567                                 auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() );
    568                                 auto mutValue = mutate( mutInit->value.get() );
    569 
    570                                 mutValue->env = nullptr;
    571                                 mutInit->value = mutValue;
    572                                 mutParam->init = mutInit;
    573                                 mutType->params[i] = mutParam;
    574 
    575                                 assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env);
    576                         }
    577                 }
    578         }
    579         mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
    580         return functionDecl;
    581 }
    582 
    583 const ast::ObjectDecl * Resolver::previsit( const ast::ObjectDecl * objectDecl ) {
    584         // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
    585         // class-variable `initContext` is changed multiple times because the LHS is analyzed
    586         // twice. The second analysis changes `initContext` because a function type can contain
    587         // object declarations in the return and parameter types. Therefore each value of
    588         // `initContext` is retained so the type on the first analysis is preserved and used for
    589         // selecting the RHS.
    590         GuardValue( currentObject );
    591 
    592         if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
    593                 // enumerator initializers should not use the enum type to initialize, since the
    594                 // enum type is still incomplete at this point. Use `int` instead.
    595 
    596                 if ( auto enumBase = dynamic_cast< const ast::EnumInstType * >
    597                         ( objectDecl->get_type() )->base->base ) {
    598                         objectDecl = fixObjectType( objectDecl, context );
    599                         currentObject = ast::CurrentObject{
    600                                 objectDecl->location,
    601                                 enumBase
    602                         };
    603                 } else {
    604                         objectDecl = fixObjectType( objectDecl, context );
    605                         currentObject = ast::CurrentObject{
    606                                 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
    607                 }
    608         } else {
    609                 if ( !objectDecl->isTypeFixed ) {
    610                         auto newDecl = fixObjectType(objectDecl, context);
    611                         auto mutDecl = mutate(newDecl);
    612 
    613                         // generate CtorInit wrapper when necessary.
    614                         // in certain cases, fixObjectType is called before reaching
    615                         // this object in visitor pass, thus disabling CtorInit codegen.
    616                         // this happens on aggregate members and function parameters.
    617                         if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
    618                                 // constructed objects cannot be designated
    619                                 if ( InitTweak::isDesignated( mutDecl->init ) ) {
    620                                         ast::Pass<ResolveDesignators> res( context );
    621                                         maybe_accept( mutDecl->init.get(), res );
    622                                         if ( !res.core.result ) {
    623                                                 SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object.\n"
    624                                                                            "If this is really what you want, initialize with @=." );
     604                                objectDecl = fixObjectType( objectDecl, context );
     605                                currentObject = ast::CurrentObject{
     606                                        objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
     607                        }
     608
     609                }
     610                else {
     611                        if ( !objectDecl->isTypeFixed ) {
     612                                auto newDecl = fixObjectType(objectDecl, context);
     613                                auto mutDecl = mutate(newDecl);
     614
     615                                // generate CtorInit wrapper when necessary.
     616                                // in certain cases, fixObjectType is called before reaching
     617                                // this object in visitor pass, thus disabling CtorInit codegen.
     618                                // this happens on aggregate members and function parameters.
     619                                if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
     620                                        // constructed objects cannot be designated
     621                                        if ( InitTweak::isDesignated( mutDecl->init ) ) {
     622                                                ast::Pass<ResolveDesignators> res( context );
     623                                                maybe_accept( mutDecl->init.get(), res );
     624                                                if ( !res.core.result ) {
     625                                                        SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object.\n"
     626                                                                                   "If this is really what you want, initialize with @=." );
     627                                                }
     628                                        }
     629                                        // constructed objects should not have initializers nested too deeply
     630                                        if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
     631
     632                                        mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
     633                                }
     634
     635                                objectDecl = mutDecl;
     636                        }
     637                        currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     638                }
     639
     640                return objectDecl;
     641        }
     642
     643        void Resolver::previsit( const ast::AggregateDecl * _aggDecl ) {
     644                auto aggDecl = mutate(_aggDecl);
     645                assertf(aggDecl == _aggDecl, "type declarations must be unique");
     646
     647                for (auto & member: aggDecl->members) {
     648                        // nested type decls are hoisted already. no need to do anything
     649                        if (auto obj = member.as<ast::ObjectDecl>()) {
     650                                member = fixObjectType(obj, context);
     651                        }
     652                }
     653        }
     654
     655        void Resolver::previsit( const ast::StructDecl * structDecl ) {
     656                previsit(static_cast<const ast::AggregateDecl *>(structDecl));
     657                managedTypes.handleStruct(structDecl);
     658        }
     659
     660        void Resolver::previsit( const ast::EnumDecl * ) {
     661                // in case we decide to allow nested enums
     662                GuardValue( inEnumDecl );
     663                inEnumDecl = true;
     664                // don't need to fix types for enum fields
     665        }
     666
     667        const ast::StaticAssertDecl * Resolver::previsit(
     668                const ast::StaticAssertDecl * assertDecl
     669        ) {
     670                return ast::mutate_field(
     671                        assertDecl, &ast::StaticAssertDecl::cond,
     672                        findIntegralExpression( assertDecl->cond, context ) );
     673        }
     674
     675        template< typename PtrType >
     676        const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) {
     677                if ( type->dimension ) {
     678                        const ast::Type * sizeType = context.global.sizeType.get();
     679                        ast::ptr< ast::Expr > dimension = findSingleExpression( type->dimension, sizeType, context );
     680                        assertf(dimension->env->empty(), "array dimension expr has nonempty env");
     681                        dimension.get_and_mutate()->env = nullptr;
     682                        ast::mutate_field( type, &PtrType::dimension, dimension );
     683                }
     684                return type;
     685        }
     686
     687        const ast::ArrayType * Resolver::previsit( const ast::ArrayType * at ) {
     688                return handlePtrType( at, context );
     689        }
     690
     691        const ast::PointerType * Resolver::previsit( const ast::PointerType * pt ) {
     692                return handlePtrType( pt, context );
     693        }
     694
     695        const ast::ExprStmt * Resolver::previsit( const ast::ExprStmt * exprStmt ) {
     696                visit_children = false;
     697                assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
     698
     699                return ast::mutate_field(
     700                        exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) );
     701        }
     702
     703        const ast::AsmExpr * Resolver::previsit( const ast::AsmExpr * asmExpr ) {
     704                visit_children = false;
     705
     706                asmExpr = ast::mutate_field(
     707                        asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) );
     708
     709                return asmExpr;
     710        }
     711
     712        const ast::AsmStmt * Resolver::previsit( const ast::AsmStmt * asmStmt ) {
     713                visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
     714                visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
     715                visit_children = false;
     716                return asmStmt;
     717        }
     718
     719        const ast::IfStmt * Resolver::previsit( const ast::IfStmt * ifStmt ) {
     720                return ast::mutate_field(
     721                        ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) );
     722        }
     723
     724        const ast::WhileDoStmt * Resolver::previsit( const ast::WhileDoStmt * whileDoStmt ) {
     725                return ast::mutate_field(
     726                        whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) );
     727        }
     728
     729        const ast::ForStmt * Resolver::previsit( const ast::ForStmt * forStmt ) {
     730                if ( forStmt->cond ) {
     731                        forStmt = ast::mutate_field(
     732                                forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) );
     733                }
     734
     735                if ( forStmt->inc ) {
     736                        forStmt = ast::mutate_field(
     737                                forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) );
     738                }
     739
     740                return forStmt;
     741        }
     742
     743        const ast::SwitchStmt * Resolver::previsit( const ast::SwitchStmt * switchStmt ) {
     744                GuardValue( currentObject );
     745                switchStmt = ast::mutate_field(
     746                        switchStmt, &ast::SwitchStmt::cond,
     747                        findIntegralExpression( switchStmt->cond, context ) );
     748                currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
     749                return switchStmt;
     750        }
     751
     752        const ast::CaseClause * Resolver::previsit( const ast::CaseClause * caseStmt ) {
     753                if ( caseStmt->cond ) {
     754                        std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
     755                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
     756                                "expression." );
     757
     758                        ast::ptr< ast::Expr > untyped =
     759                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
     760                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context );
     761
     762                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     763                        // whether it would perform a conversion.
     764                        if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
     765                                swap_and_save_env( newExpr, castExpr->arg );
     766                        }
     767
     768                        caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr );
     769                }
     770                return caseStmt;
     771        }
     772
     773        const ast::BranchStmt * Resolver::previsit( const ast::BranchStmt * branchStmt ) {
     774                visit_children = false;
     775                // must resolve the argument of a computed goto
     776                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
     777                        // computed goto argument is void*
     778                        ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
     779                        branchStmt = ast::mutate_field(
     780                                branchStmt, &ast::BranchStmt::computedTarget,
     781                                findSingleExpression( branchStmt->computedTarget, target, context ) );
     782                }
     783                return branchStmt;
     784        }
     785
     786        const ast::ReturnStmt * Resolver::previsit( const ast::ReturnStmt * returnStmt ) {
     787                visit_children = false;
     788                if ( returnStmt->expr ) {
     789                        returnStmt = ast::mutate_field(
     790                                returnStmt, &ast::ReturnStmt::expr,
     791                                findSingleExpression( returnStmt->expr, functionReturn, context ) );
     792                }
     793                return returnStmt;
     794        }
     795
     796        const ast::ThrowStmt * Resolver::previsit( const ast::ThrowStmt * throwStmt ) {
     797                visit_children = false;
     798                if ( throwStmt->expr ) {
     799                        const ast::StructDecl * exceptionDecl =
     800                                symtab.lookupStruct( "__cfaehm_base_exception_t" );
     801                        assert( exceptionDecl );
     802                        ast::ptr< ast::Type > exceptType =
     803                                new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
     804                        throwStmt = ast::mutate_field(
     805                                throwStmt, &ast::ThrowStmt::expr,
     806                                findSingleExpression( throwStmt->expr, exceptType, context ) );
     807                }
     808                return throwStmt;
     809        }
     810
     811        const ast::CatchClause * Resolver::previsit( const ast::CatchClause * catchClause ) {
     812                // Until we are very sure this invarent (ifs that move between passes have then)
     813                // holds, check it. This allows a check for when to decode the mangling.
     814                if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) {
     815                        assert( ifStmt->then );
     816                }
     817                // Encode the catchStmt so the condition can see the declaration.
     818                if ( catchClause->cond ) {
     819                        ast::CatchClause * clause = mutate( catchClause );
     820                        clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body );
     821                        clause->cond = nullptr;
     822                        return clause;
     823                }
     824                return catchClause;
     825        }
     826
     827        const ast::CatchClause * Resolver::postvisit( const ast::CatchClause * catchClause ) {
     828                // Decode the catchStmt so everything is stored properly.
     829                const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>();
     830                if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
     831                        assert( ifStmt->cond );
     832                        assert( ifStmt->else_ );
     833                        ast::CatchClause * clause = ast::mutate( catchClause );
     834                        clause->cond = ifStmt->cond;
     835                        clause->body = ifStmt->else_;
     836                        // ifStmt should be implicately deleted here.
     837                        return clause;
     838                }
     839                return catchClause;
     840        }
     841
     842        const ast::WaitForStmt * Resolver::previsit( const ast::WaitForStmt * stmt ) {
     843                visit_children = false;
     844
     845                // Resolve all clauses first
     846                for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
     847                        const ast::WaitForClause & clause = *stmt->clauses[i];
     848
     849                        ast::TypeEnvironment env;
     850                        CandidateFinder funcFinder( context, env );
     851
     852                        // Find all candidates for a function in canonical form
     853                        funcFinder.find( clause.target, ResolveMode::withAdjustment() );
     854
     855                        if ( funcFinder.candidates.empty() ) {
     856                                stringstream ss;
     857                                ss << "Use of undeclared indentifier '";
     858                                ss << clause.target.strict_as< ast::NameExpr >()->name;
     859                                ss << "' in call to waitfor";
     860                                SemanticError( stmt->location, ss.str() );
     861                        }
     862
     863                        if ( clause.target_args.empty() ) {
     864                                SemanticError( stmt->location,
     865                                        "Waitfor clause must have at least one mutex parameter");
     866                        }
     867
     868                        // Find all alternatives for all arguments in canonical form
     869                        std::vector< CandidateFinder > argFinders =
     870                                funcFinder.findSubExprs( clause.target_args );
     871
     872                        // List all combinations of arguments
     873                        std::vector< CandidateList > possibilities;
     874                        combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );
     875
     876                        // For every possible function:
     877                        // * try matching the arguments to the parameters, not the other way around because
     878                        //   more arguments than parameters
     879                        CandidateList funcCandidates;
     880                        std::vector< CandidateList > argsCandidates;
     881                        SemanticErrorException errors;
     882                        for ( CandidateRef & func : funcFinder.candidates ) {
     883                                try {
     884                                        auto pointerType = dynamic_cast< const ast::PointerType * >(
     885                                                func->expr->result->stripReferences() );
     886                                        if ( ! pointerType ) {
     887                                                SemanticError( stmt->location, func->expr->result.get(),
     888                                                        "candidate not viable: not a pointer type\n" );
     889                                        }
     890
     891                                        auto funcType = pointerType->base.as< ast::FunctionType >();
     892                                        if ( ! funcType ) {
     893                                                SemanticError( stmt->location, func->expr->result.get(),
     894                                                        "candidate not viable: not a function type\n" );
     895                                        }
     896
     897                                        {
     898                                                auto param    = funcType->params.begin();
     899                                                auto paramEnd = funcType->params.end();
     900
     901                                                if( ! nextMutex( param, paramEnd ) ) {
     902                                                        SemanticError( stmt->location, funcType,
     903                                                                "candidate function not viable: no mutex parameters\n");
     904                                                }
     905                                        }
     906
     907                                        CandidateRef func2{ new Candidate{ *func } };
     908                                        // strip reference from function
     909                                        func2->expr = referenceToRvalueConversion( func->expr, func2->cost );
     910
     911                                        // Each argument must be matched with a parameter of the current candidate
     912                                        for ( auto & argsList : possibilities ) {
     913                                                try {
     914                                                        // Declare data structures needed for resolution
     915                                                        ast::OpenVarSet open;
     916                                                        ast::AssertionSet need, have;
     917                                                        ast::TypeEnvironment resultEnv{ func->env };
     918                                                        // Add all type variables as open so that those not used in the
     919                                                        // parameter list are still considered open
     920                                                        resultEnv.add( funcType->forall );
     921
     922                                                        // load type variables from arguments into one shared space
     923                                                        for ( auto & arg : argsList ) {
     924                                                                resultEnv.simpleCombine( arg->env );
     925                                                        }
     926
     927                                                        // Make sure we don't widen any existing bindings
     928                                                        resultEnv.forbidWidening();
     929
     930                                                        // Find any unbound type variables
     931                                                        resultEnv.extractOpenVars( open );
     932
     933                                                        auto param = funcType->params.begin();
     934                                                        auto paramEnd = funcType->params.end();
     935
     936                                                        unsigned n_mutex_param = 0;
     937
     938                                                        // For every argument of its set, check if it matches one of the
     939                                                        // parameters. The order is important
     940                                                        for ( auto & arg : argsList ) {
     941                                                                // Ignore non-mutex arguments
     942                                                                if ( ! nextMutex( param, paramEnd ) ) {
     943                                                                        // We ran out of parameters but still have arguments.
     944                                                                        // This function doesn't match
     945                                                                        SemanticError( stmt->location, funcType,
     946                                                                                toString("candidate function not viable: too many mutex "
     947                                                                                "arguments, expected ", n_mutex_param, "\n" ) );
     948                                                                }
     949
     950                                                                ++n_mutex_param;
     951
     952                                                                // Check if the argument matches the parameter type in the current scope.
     953                                                                // ast::ptr< ast::Type > paramType = (*param)->get_type();
     954
     955                                                                if (
     956                                                                        ! unify(
     957                                                                                arg->expr->result, *param, resultEnv, need, have, open )
     958                                                                ) {
     959                                                                        // Type doesn't match
     960                                                                        stringstream ss;
     961                                                                        ss << "candidate function not viable: no known conversion "
     962                                                                                "from '";
     963                                                                        ast::print( ss, *param );
     964                                                                        ss << "' to '";
     965                                                                        ast::print( ss, arg->expr->result );
     966                                                                        ss << "' with env '";
     967                                                                        ast::print( ss, resultEnv );
     968                                                                        ss << "'\n";
     969                                                                        SemanticError( stmt->location, funcType, ss.str() );
     970                                                                }
     971
     972                                                                ++param;
     973                                                        }
     974
     975                                                        // All arguments match!
     976
     977                                                        // Check if parameters are missing
     978                                                        if ( nextMutex( param, paramEnd ) ) {
     979                                                                do {
     980                                                                        ++n_mutex_param;
     981                                                                        ++param;
     982                                                                } while ( nextMutex( param, paramEnd ) );
     983
     984                                                                // We ran out of arguments but still have parameters left; this
     985                                                                // function doesn't match
     986                                                                SemanticError( stmt->location, funcType,
     987                                                                        toString( "candidate function not viable: too few mutex "
     988                                                                        "arguments, expected ", n_mutex_param, "\n" ) );
     989                                                        }
     990
     991                                                        // All parameters match!
     992
     993                                                        // Finish the expressions to tie in proper environments
     994                                                        finishExpr( func2->expr, resultEnv );
     995                                                        for ( CandidateRef & arg : argsList ) {
     996                                                                finishExpr( arg->expr, resultEnv );
     997                                                        }
     998
     999                                                        // This is a match, store it and save it for later
     1000                                                        funcCandidates.emplace_back( std::move( func2 ) );
     1001                                                        argsCandidates.emplace_back( std::move( argsList ) );
     1002
     1003                                                } catch ( SemanticErrorException & e ) {
     1004                                                        errors.append( e );
     1005                                                }
     1006                                        }
     1007                                } catch ( SemanticErrorException & e ) {
     1008                                        errors.append( e );
     1009                                }
     1010                        }
     1011
     1012                        // Make sure correct number of arguments
     1013                        if( funcCandidates.empty() ) {
     1014                                SemanticErrorException top( stmt->location,
     1015                                        "No alternatives for function in call to waitfor" );
     1016                                top.append( errors );
     1017                                throw top;
     1018                        }
     1019
     1020                        if( argsCandidates.empty() ) {
     1021                                SemanticErrorException top( stmt->location,
     1022                                        "No alternatives for arguments in call to waitfor" );
     1023                                top.append( errors );
     1024                                throw top;
     1025                        }
     1026
     1027                        if( funcCandidates.size() > 1 ) {
     1028                                SemanticErrorException top( stmt->location,
     1029                                        "Ambiguous function in call to waitfor" );
     1030                                top.append( errors );
     1031                                throw top;
     1032                        }
     1033                        if( argsCandidates.size() > 1 ) {
     1034                                SemanticErrorException top( stmt->location,
     1035                                        "Ambiguous arguments in call to waitfor" );
     1036                                top.append( errors );
     1037                                throw top;
     1038                        }
     1039                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
     1040
     1041                        // build new clause
     1042                        auto clause2 = new ast::WaitForClause( clause.location );
     1043
     1044                        clause2->target = funcCandidates.front()->expr;
     1045
     1046                        clause2->target_args.reserve( clause.target_args.size() );
     1047                        const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" );
     1048                        for ( auto arg : argsCandidates.front() ) {
     1049                                const auto & loc = stmt->location;
     1050
     1051                                ast::Expr * init = new ast::CastExpr( loc,
     1052                                        new ast::UntypedExpr( loc,
     1053                                                new ast::NameExpr( loc, "get_monitor" ),
     1054                                                { arg->expr }
     1055                                        ),
     1056                                        new ast::PointerType(
     1057                                                new ast::StructInstType(
     1058                                                        decl_monitor
     1059                                                )
     1060                                        )
     1061                                );
     1062
     1063                                clause2->target_args.emplace_back( findSingleExpression( init, context ) );
     1064                        }
     1065
     1066                        // Resolve the conditions as if it were an IfStmt, statements normally
     1067                        clause2->when_cond = findSingleExpression( clause.when_cond, context );
     1068                        clause2->stmt = clause.stmt->accept( *visitor );
     1069
     1070                        // set results into stmt
     1071                        auto n = mutate( stmt );
     1072                        n->clauses[i] = clause2;
     1073                        stmt = n;
     1074                }
     1075
     1076                if ( stmt->timeout_stmt ) {
     1077                        // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
     1078                        ast::ptr< ast::Type > target =
     1079                                new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
     1080                        auto timeout_time = findSingleExpression( stmt->timeout_time, target, context );
     1081                        auto timeout_cond = findSingleExpression( stmt->timeout_cond, context );
     1082                        auto timeout_stmt = stmt->timeout_stmt->accept( *visitor );
     1083
     1084                        // set results into stmt
     1085                        auto n = mutate( stmt );
     1086                        n->timeout_time = std::move( timeout_time );
     1087                        n->timeout_cond = std::move( timeout_cond );
     1088                        n->timeout_stmt = std::move( timeout_stmt );
     1089                        stmt = n;
     1090                }
     1091
     1092                if ( stmt->else_stmt ) {
     1093                        // resolve the condition like IfStmt, stmts normally
     1094                        auto else_cond = findSingleExpression( stmt->else_cond, context );
     1095                        auto else_stmt = stmt->else_stmt->accept( *visitor );
     1096
     1097                        // set results into stmt
     1098                        auto n = mutate( stmt );
     1099                        n->else_cond = std::move( else_cond );
     1100                        n->else_stmt = std::move( else_stmt );
     1101                        stmt = n;
     1102                }
     1103
     1104                return stmt;
     1105        }
     1106
     1107        const ast::WithStmt * Resolver::previsit( const ast::WithStmt * withStmt ) {
     1108                auto mutStmt = mutate(withStmt);
     1109                resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
     1110                return mutStmt;
     1111        }
     1112
     1113        void Resolver::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
     1114                for (auto & expr : exprs) {
     1115                        // only struct- and union-typed expressions are viable candidates
     1116                        expr = findKindExpression( expr, context, structOrUnion, "with expression" );
     1117
     1118                        // if with expression might be impure, create a temporary so that it is evaluated once
     1119                        if ( Tuples::maybeImpure( expr ) ) {
     1120                                static UniqueName tmpNamer( "_with_tmp_" );
     1121                                const CodeLocation loc = expr->location;
     1122                                auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
     1123                                expr = new ast::VariableExpr( loc, tmp );
     1124                                stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
     1125                                if ( InitTweak::isConstructable( tmp->type ) ) {
     1126                                        // generate ctor/dtor and resolve them
     1127                                        tmp->init = InitTweak::genCtorInit( loc, tmp );
     1128                                }
     1129                                // since tmp is freshly created, this should modify tmp in-place
     1130                                tmp->accept( *visitor );
     1131                        }
     1132                        else if (expr->env && expr->env->empty()) {
     1133                                expr = ast::mutate_field(expr.get(), &ast::Expr::env, nullptr);
     1134                        }
     1135                }
     1136        }
     1137
     1138
     1139        const ast::SingleInit * Resolver::previsit( const ast::SingleInit * singleInit ) {
     1140                visit_children = false;
     1141                // resolve initialization using the possibilities as determined by the `currentObject`
     1142                // cursor.
     1143                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
     1144                        singleInit->location, singleInit->value, currentObject.getOptions() };
     1145                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context );
     1146                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
     1147
     1148                // move cursor to the object that is actually initialized
     1149                currentObject.setNext( initExpr->designation );
     1150
     1151                // discard InitExpr wrapper and retain relevant pieces.
     1152                // `initExpr` may have inferred params in the case where the expression specialized a
     1153                // function pointer, and newExpr may already have inferParams of its own, so a simple
     1154                // swap is not sufficient
     1155                ast::Expr::InferUnion inferred = initExpr->inferred;
     1156                swap_and_save_env( newExpr, initExpr->expr );
     1157                newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );
     1158
     1159                // get the actual object's type (may not exactly match what comes back from the resolver
     1160                // due to conversions)
     1161                const ast::Type * initContext = currentObject.getCurrentType();
     1162
     1163                removeExtraneousCast( newExpr );
     1164
     1165                // check if actual object's type is char[]
     1166                if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {
     1167                        if ( isCharType( at->base ) ) {
     1168                                // check if the resolved type is char*
     1169                                if ( auto pt = newExpr->result.as< ast::PointerType >() ) {
     1170                                        if ( isCharType( pt->base ) ) {
     1171                                                // strip cast if we're initializing a char[] with a char*
     1172                                                // e.g. char x[] = "hello"
     1173                                                if ( auto ce = newExpr.as< ast::CastExpr >() ) {
     1174                                                        swap_and_save_env( newExpr, ce->arg );
     1175                                                }
    6251176                                        }
    6261177                                }
    627                                 // constructed objects should not have initializers nested too deeply
    628                                 if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
    629 
    630                                 mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
    631                         }
    632 
    633                         objectDecl = mutDecl;
    634                 }
    635                 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
    636         }
    637 
    638         return objectDecl;
    639 }
    640 
    641 void Resolver::previsit( const ast::AggregateDecl * _aggDecl ) {
    642         auto aggDecl = mutate(_aggDecl);
    643         assertf(aggDecl == _aggDecl, "type declarations must be unique");
    644 
    645         for (auto & member: aggDecl->members) {
    646                 // nested type decls are hoisted already. no need to do anything
    647                 if (auto obj = member.as<ast::ObjectDecl>()) {
    648                         member = fixObjectType(obj, context);
    649                 }
    650         }
    651 }
    652 
    653 void Resolver::previsit( const ast::StructDecl * structDecl ) {
    654         previsit(static_cast<const ast::AggregateDecl *>(structDecl));
    655         managedTypes.handleStruct(structDecl);
    656 }
    657 
    658 void Resolver::previsit( const ast::EnumDecl * ) {
    659         // in case we decide to allow nested enums
    660         GuardValue( inEnumDecl );
    661         inEnumDecl = true;
    662         // don't need to fix types for enum fields
    663 }
    664 
    665 const ast::StaticAssertDecl * Resolver::previsit(
    666         const ast::StaticAssertDecl * assertDecl
    667 ) {
    668         return ast::mutate_field(
    669                 assertDecl, &ast::StaticAssertDecl::cond,
    670                 findIntegralExpression( assertDecl->cond, context ) );
    671 }
    672 
    673 template< typename PtrType >
    674 const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) {
    675         if ( type->dimension ) {
    676                 const ast::Type * sizeType = context.global.sizeType.get();
    677                 ast::ptr< ast::Expr > dimension = findSingleExpression( type->dimension, sizeType, context );
    678                 assertf(dimension->env->empty(), "array dimension expr has nonempty env");
    679                 dimension.get_and_mutate()->env = nullptr;
    680                 ast::mutate_field( type, &PtrType::dimension, dimension );
    681         }
    682         return type;
    683 }
    684 
    685 const ast::ArrayType * Resolver::previsit( const ast::ArrayType * at ) {
    686         return handlePtrType( at, context );
    687 }
    688 
    689 const ast::PointerType * Resolver::previsit( const ast::PointerType * pt ) {
    690         return handlePtrType( pt, context );
    691 }
    692 
    693 const ast::ExprStmt * Resolver::previsit( const ast::ExprStmt * exprStmt ) {
    694         visit_children = false;
    695         assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
    696 
    697         return ast::mutate_field(
    698                 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) );
    699 }
    700 
    701 const ast::AsmExpr * Resolver::previsit( const ast::AsmExpr * asmExpr ) {
    702         visit_children = false;
    703 
    704         asmExpr = ast::mutate_field(
    705                 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) );
    706 
    707         return asmExpr;
    708 }
    709 
    710 const ast::AsmStmt * Resolver::previsit( const ast::AsmStmt * asmStmt ) {
    711         visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
    712         visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
    713         visit_children = false;
    714         return asmStmt;
    715 }
    716 
    717 const ast::IfStmt * Resolver::previsit( const ast::IfStmt * ifStmt ) {
    718         return ast::mutate_field(
    719                 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) );
    720 }
    721 
    722 const ast::WhileDoStmt * Resolver::previsit( const ast::WhileDoStmt * whileDoStmt ) {
    723         return ast::mutate_field(
    724                 whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) );
    725 }
    726 
    727 const ast::ForStmt * Resolver::previsit( const ast::ForStmt * forStmt ) {
    728         if ( forStmt->cond ) {
    729                 forStmt = ast::mutate_field(
    730                         forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) );
    731         }
    732 
    733         if ( forStmt->inc ) {
    734                 forStmt = ast::mutate_field(
    735                         forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) );
    736         }
    737 
    738         return forStmt;
    739 }
    740 
    741 const ast::SwitchStmt * Resolver::previsit( const ast::SwitchStmt * switchStmt ) {
    742         GuardValue( currentObject );
    743         switchStmt = ast::mutate_field(
    744                 switchStmt, &ast::SwitchStmt::cond,
    745                 findIntegralExpression( switchStmt->cond, context ) );
    746         currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
    747         return switchStmt;
    748 }
    749 
    750 const ast::CaseClause * Resolver::previsit( const ast::CaseClause * caseStmt ) {
    751         if ( caseStmt->cond ) {
    752                 std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
    753                 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
    754                         "expression." );
    755 
    756                 ast::ptr< ast::Expr > untyped =
    757                         new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    758                 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context );
    759 
    760                 // case condition cannot have a cast in C, so it must be removed here, regardless of
    761                 // whether it would perform a conversion.
    762                 if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
    763                         swap_and_save_env( newExpr, castExpr->arg );
    764                 }
    765 
    766                 caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr );
    767         }
    768         return caseStmt;
    769 }
    770 
    771 const ast::BranchStmt * Resolver::previsit( const ast::BranchStmt * branchStmt ) {
    772         visit_children = false;
    773         // must resolve the argument of a computed goto
    774         if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    775                 // computed goto argument is void*
    776                 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    777                 branchStmt = ast::mutate_field(
    778                         branchStmt, &ast::BranchStmt::computedTarget,
    779                         findSingleExpression( branchStmt->computedTarget, target, context ) );
    780         }
    781         return branchStmt;
    782 }
    783 
    784 const ast::ReturnStmt * Resolver::previsit( const ast::ReturnStmt * returnStmt ) {
    785         visit_children = false;
    786         if ( returnStmt->expr ) {
    787                 returnStmt = ast::mutate_field(
    788                         returnStmt, &ast::ReturnStmt::expr,
    789                         findSingleExpression( returnStmt->expr, functionReturn, context ) );
    790         }
    791         return returnStmt;
    792 }
    793 
    794 const ast::ThrowStmt * Resolver::previsit( const ast::ThrowStmt * throwStmt ) {
    795         visit_children = false;
    796         if ( throwStmt->expr ) {
    797                 const ast::StructDecl * exceptionDecl =
    798                         symtab.lookupStruct( "__cfaehm_base_exception_t" );
    799                 assert( exceptionDecl );
    800                 ast::ptr< ast::Type > exceptType =
    801                         new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
    802                 throwStmt = ast::mutate_field(
    803                         throwStmt, &ast::ThrowStmt::expr,
    804                         findSingleExpression( throwStmt->expr, exceptType, context ) );
    805         }
    806         return throwStmt;
    807 }
    808 
    809 const ast::CatchClause * Resolver::previsit( const ast::CatchClause * catchClause ) {
    810         // Until we are very sure this invarent (ifs that move between passes have then)
    811         // holds, check it. This allows a check for when to decode the mangling.
    812         if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) {
    813                 assert( ifStmt->then );
    814         }
    815         // Encode the catchStmt so the condition can see the declaration.
    816         if ( catchClause->cond ) {
    817                 ast::CatchClause * clause = mutate( catchClause );
    818                 clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body );
    819                 clause->cond = nullptr;
    820                 return clause;
    821         }
    822         return catchClause;
    823 }
    824 
    825 const ast::CatchClause * Resolver::postvisit( const ast::CatchClause * catchClause ) {
    826         // Decode the catchStmt so everything is stored properly.
    827         const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>();
    828         if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
    829                 assert( ifStmt->cond );
    830                 assert( ifStmt->else_ );
    831                 ast::CatchClause * clause = ast::mutate( catchClause );
    832                 clause->cond = ifStmt->cond;
    833                 clause->body = ifStmt->else_;
    834                 // ifStmt should be implicately deleted here.
    835                 return clause;
    836         }
    837         return catchClause;
    838 }
    839 
    840 const ast::WaitForStmt * Resolver::previsit( const ast::WaitForStmt * stmt ) {
    841         visit_children = false;
    842 
    843         // Resolve all clauses first
    844         for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
    845                 const ast::WaitForClause & clause = *stmt->clauses[i];
    846 
    847                 ast::TypeEnvironment env;
    848                 CandidateFinder funcFinder( context, env );
    849 
    850                 // Find all candidates for a function in canonical form
    851                 funcFinder.find( clause.target, ResolveMode::withAdjustment() );
    852 
    853                 if ( funcFinder.candidates.empty() ) {
    854                         stringstream ss;
    855                         ss << "Use of undeclared indentifier '";
    856                         ss << clause.target.strict_as< ast::NameExpr >()->name;
    857                         ss << "' in call to waitfor";
    858                         SemanticError( stmt->location, ss.str() );
    859                 }
    860 
    861                 if ( clause.target_args.empty() ) {
    862                         SemanticError( stmt->location,
    863                                 "Waitfor clause must have at least one mutex parameter");
    864                 }
    865 
    866                 // Find all alternatives for all arguments in canonical form
    867                 std::vector< CandidateFinder > argFinders =
    868                         funcFinder.findSubExprs( clause.target_args );
    869 
    870                 // List all combinations of arguments
    871                 std::vector< CandidateList > possibilities;
    872                 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );
    873 
    874                 // For every possible function:
    875                 // * try matching the arguments to the parameters, not the other way around because
    876                 //   more arguments than parameters
    877                 CandidateList funcCandidates;
    878                 std::vector< CandidateList > argsCandidates;
    879                 SemanticErrorException errors;
    880                 for ( CandidateRef & func : funcFinder.candidates ) {
    881                         try {
    882                                 auto pointerType = dynamic_cast< const ast::PointerType * >(
    883                                         func->expr->result->stripReferences() );
    884                                 if ( ! pointerType ) {
    885                                         SemanticError( stmt->location, func->expr->result.get(),
    886                                                 "candidate not viable: not a pointer type\n" );
    887                                 }
    888 
    889                                 auto funcType = pointerType->base.as< ast::FunctionType >();
    890                                 if ( ! funcType ) {
    891                                         SemanticError( stmt->location, func->expr->result.get(),
    892                                                 "candidate not viable: not a function type\n" );
    893                                 }
    894 
    895                                 {
    896                                         auto param    = funcType->params.begin();
    897                                         auto paramEnd = funcType->params.end();
    898 
    899                                         if( ! nextMutex( param, paramEnd ) ) {
    900                                                 SemanticError( stmt->location, funcType,
    901                                                         "candidate function not viable: no mutex parameters\n");
    902                                         }
    903                                 }
    904 
    905                                 CandidateRef func2{ new Candidate{ *func } };
    906                                 // strip reference from function
    907                                 func2->expr = referenceToRvalueConversion( func->expr, func2->cost );
    908 
    909                                 // Each argument must be matched with a parameter of the current candidate
    910                                 for ( auto & argsList : possibilities ) {
    911                                         try {
    912                                                 // Declare data structures needed for resolution
    913                                                 ast::OpenVarSet open;
    914                                                 ast::AssertionSet need, have;
    915                                                 ast::TypeEnvironment resultEnv{ func->env };
    916                                                 // Add all type variables as open so that those not used in the
    917                                                 // parameter list are still considered open
    918                                                 resultEnv.add( funcType->forall );
    919 
    920                                                 // load type variables from arguments into one shared space
    921                                                 for ( auto & arg : argsList ) {
    922                                                         resultEnv.simpleCombine( arg->env );
    923                                                 }
    924 
    925                                                 // Make sure we don't widen any existing bindings
    926                                                 resultEnv.forbidWidening();
    927 
    928                                                 // Find any unbound type variables
    929                                                 resultEnv.extractOpenVars( open );
    930 
    931                                                 auto param = funcType->params.begin();
    932                                                 auto paramEnd = funcType->params.end();
    933 
    934                                                 unsigned n_mutex_param = 0;
    935 
    936                                                 // For every argument of its set, check if it matches one of the
    937                                                 // parameters. The order is important
    938                                                 for ( auto & arg : argsList ) {
    939                                                         // Ignore non-mutex arguments
    940                                                         if ( ! nextMutex( param, paramEnd ) ) {
    941                                                                 // We ran out of parameters but still have arguments.
    942                                                                 // This function doesn't match
    943                                                                 SemanticError( stmt->location, funcType,
    944                                                                         toString("candidate function not viable: too many mutex "
    945                                                                         "arguments, expected ", n_mutex_param, "\n" ) );
    946                                                         }
    947 
    948                                                         ++n_mutex_param;
    949 
    950                                                         // Check if the argument matches the parameter type in the current scope.
    951                                                         // ast::ptr< ast::Type > paramType = (*param)->get_type();
    952 
    953                                                         if (
    954                                                                 ! unify(
    955                                                                         arg->expr->result, *param, resultEnv, need, have, open )
    956                                                         ) {
    957                                                                 // Type doesn't match
    958                                                                 stringstream ss;
    959                                                                 ss << "candidate function not viable: no known conversion "
    960                                                                         "from '";
    961                                                                 ast::print( ss, *param );
    962                                                                 ss << "' to '";
    963                                                                 ast::print( ss, arg->expr->result );
    964                                                                 ss << "' with env '";
    965                                                                 ast::print( ss, resultEnv );
    966                                                                 ss << "'\n";
    967                                                                 SemanticError( stmt->location, funcType, ss.str() );
    968                                                         }
    969 
    970                                                         ++param;
    971                                                 }
    972 
    973                                                 // All arguments match!
    974 
    975                                                 // Check if parameters are missing
    976                                                 if ( nextMutex( param, paramEnd ) ) {
    977                                                         do {
    978                                                                 ++n_mutex_param;
    979                                                                 ++param;
    980                                                         } while ( nextMutex( param, paramEnd ) );
    981 
    982                                                         // We ran out of arguments but still have parameters left; this
    983                                                         // function doesn't match
    984                                                         SemanticError( stmt->location, funcType,
    985                                                                 toString( "candidate function not viable: too few mutex "
    986                                                                 "arguments, expected ", n_mutex_param, "\n" ) );
    987                                                 }
    988 
    989                                                 // All parameters match!
    990 
    991                                                 // Finish the expressions to tie in proper environments
    992                                                 finishExpr( func2->expr, resultEnv );
    993                                                 for ( CandidateRef & arg : argsList ) {
    994                                                         finishExpr( arg->expr, resultEnv );
    995                                                 }
    996 
    997                                                 // This is a match, store it and save it for later
    998                                                 funcCandidates.emplace_back( std::move( func2 ) );
    999                                                 argsCandidates.emplace_back( std::move( argsList ) );
    1000 
    1001                                         } catch ( SemanticErrorException & e ) {
    1002                                                 errors.append( e );
    1003                                         }
    1004                                 }
    1005                         } catch ( SemanticErrorException & e ) {
    1006                                 errors.append( e );
    1007                         }
    1008                 }
    1009 
    1010                 // Make sure correct number of arguments
    1011                 if( funcCandidates.empty() ) {
    1012                         SemanticErrorException top( stmt->location,
    1013                                 "No alternatives for function in call to waitfor" );
    1014                         top.append( errors );
    1015                         throw top;
    1016                 }
    1017 
    1018                 if( argsCandidates.empty() ) {
    1019                         SemanticErrorException top( stmt->location,
    1020                                 "No alternatives for arguments in call to waitfor" );
    1021                         top.append( errors );
    1022                         throw top;
    1023                 }
    1024 
    1025                 if( funcCandidates.size() > 1 ) {
    1026                         SemanticErrorException top( stmt->location,
    1027                                 "Ambiguous function in call to waitfor" );
    1028                         top.append( errors );
    1029                         throw top;
    1030                 }
    1031                 if( argsCandidates.size() > 1 ) {
    1032                         SemanticErrorException top( stmt->location,
    1033                                 "Ambiguous arguments in call to waitfor" );
    1034                         top.append( errors );
    1035                         throw top;
    1036                 }
    1037                 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    1038 
    1039                 // build new clause
    1040                 auto clause2 = new ast::WaitForClause( clause.location );
    1041 
    1042                 clause2->target = funcCandidates.front()->expr;
    1043 
    1044                 clause2->target_args.reserve( clause.target_args.size() );
    1045                 const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" );
    1046                 for ( auto arg : argsCandidates.front() ) {
    1047                         const auto & loc = stmt->location;
    1048 
    1049                         ast::Expr * init = new ast::CastExpr( loc,
    1050                                 new ast::UntypedExpr( loc,
    1051                                         new ast::NameExpr( loc, "get_monitor" ),
    1052                                         { arg->expr }
    1053                                 ),
    1054                                 new ast::PointerType(
    1055                                         new ast::StructInstType(
    1056                                                 decl_monitor
    1057                                         )
    1058                                 )
    1059                         );
    1060 
    1061                         clause2->target_args.emplace_back( findSingleExpression( init, context ) );
    1062                 }
    1063 
    1064                 // Resolve the conditions as if it were an IfStmt, statements normally
    1065                 clause2->when_cond = findSingleExpression( clause.when_cond, context );
    1066                 clause2->stmt = clause.stmt->accept( *visitor );
    1067 
    1068                 // set results into stmt
    1069                 auto n = mutate( stmt );
    1070                 n->clauses[i] = clause2;
    1071                 stmt = n;
    1072         }
    1073 
    1074         if ( stmt->timeout_stmt ) {
    1075                 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
    1076                 ast::ptr< ast::Type > target =
    1077                         new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
    1078                 auto timeout_time = findSingleExpression( stmt->timeout_time, target, context );
    1079                 auto timeout_cond = findSingleExpression( stmt->timeout_cond, context );
    1080                 auto timeout_stmt = stmt->timeout_stmt->accept( *visitor );
    1081 
    1082                 // set results into stmt
    1083                 auto n = mutate( stmt );
    1084                 n->timeout_time = std::move( timeout_time );
    1085                 n->timeout_cond = std::move( timeout_cond );
    1086                 n->timeout_stmt = std::move( timeout_stmt );
    1087                 stmt = n;
    1088         }
    1089 
    1090         if ( stmt->else_stmt ) {
    1091                 // resolve the condition like IfStmt, stmts normally
    1092                 auto else_cond = findSingleExpression( stmt->else_cond, context );
    1093                 auto else_stmt = stmt->else_stmt->accept( *visitor );
    1094 
    1095                 // set results into stmt
    1096                 auto n = mutate( stmt );
    1097                 n->else_cond = std::move( else_cond );
    1098                 n->else_stmt = std::move( else_stmt );
    1099                 stmt = n;
    1100         }
    1101 
    1102         return stmt;
    1103 }
    1104 
    1105 const ast::WithStmt * Resolver::previsit( const ast::WithStmt * withStmt ) {
    1106         auto mutStmt = mutate(withStmt);
    1107         resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
    1108         return mutStmt;
    1109 }
    1110 
    1111 void Resolver::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
    1112         for (auto & expr : exprs) {
    1113                 // only struct- and union-typed expressions are viable candidates
    1114                 expr = findKindExpression( expr, context, structOrUnion, "with expression" );
    1115 
    1116                 // if with expression might be impure, create a temporary so that it is evaluated once
    1117                 if ( Tuples::maybeImpure( expr ) ) {
    1118                         static UniqueName tmpNamer( "_with_tmp_" );
    1119                         const CodeLocation loc = expr->location;
    1120                         auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
    1121                         expr = new ast::VariableExpr( loc, tmp );
    1122                         stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
    1123                         if ( InitTweak::isConstructable( tmp->type ) ) {
    1124                                 // generate ctor/dtor and resolve them
    1125                                 tmp->init = InitTweak::genCtorInit( loc, tmp );
    1126                         }
    1127                         // since tmp is freshly created, this should modify tmp in-place
    1128                         tmp->accept( *visitor );
    1129                 } else if (expr->env && expr->env->empty()) {
    1130                         expr = ast::mutate_field(expr.get(), &ast::Expr::env, nullptr);
    1131                 }
    1132         }
    1133 }
    1134 
    1135 const ast::SingleInit * Resolver::previsit( const ast::SingleInit * singleInit ) {
    1136         visit_children = false;
    1137         // resolve initialization using the possibilities as determined by the `currentObject`
    1138         // cursor.
    1139         ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    1140                 singleInit->location, singleInit->value, currentObject.getOptions() };
    1141         ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context );
    1142         const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    1143 
    1144         // move cursor to the object that is actually initialized
    1145         currentObject.setNext( initExpr->designation );
    1146 
    1147         // discard InitExpr wrapper and retain relevant pieces.
    1148         // `initExpr` may have inferred params in the case where the expression specialized a
    1149         // function pointer, and newExpr may already have inferParams of its own, so a simple
    1150         // swap is not sufficient
    1151         ast::Expr::InferUnion inferred = initExpr->inferred;
    1152         swap_and_save_env( newExpr, initExpr->expr );
    1153         newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );
    1154 
    1155         // get the actual object's type (may not exactly match what comes back from the resolver
    1156         // due to conversions)
    1157         const ast::Type * initContext = currentObject.getCurrentType();
    1158 
    1159         removeExtraneousCast( newExpr );
    1160 
    1161         // check if actual object's type is char[]
    1162         if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {
    1163                 if ( isCharType( at->base ) ) {
    1164                         // check if the resolved type is char*
    1165                         if ( auto pt = newExpr->result.as< ast::PointerType >() ) {
    1166                                 if ( isCharType( pt->base ) ) {
    1167                                         // strip cast if we're initializing a char[] with a char*
    1168                                         // e.g. char x[] = "hello"
    1169                                         if ( auto ce = newExpr.as< ast::CastExpr >() ) {
    1170                                                 swap_and_save_env( newExpr, ce->arg );
    1171                                         }
    1172                                 }
    1173                         }
    1174                 }
    1175         }
    1176 
    1177         // move cursor to next object in preparation for next initializer
    1178         currentObject.increment();
    1179 
    1180         // set initializer expression to resolved expression
    1181         return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );
    1182 }
    1183 
    1184 const ast::ListInit * Resolver::previsit( const ast::ListInit * listInit ) {
    1185         // move cursor into brace-enclosed initializer-list
    1186         currentObject.enterListInit( listInit->location );
    1187 
    1188         assert( listInit->designations.size() == listInit->initializers.size() );
    1189         for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {
    1190                 // iterate designations and initializers in pairs, moving the cursor to the current
    1191                 // designated object and resolving the initializer against that object
    1192                 listInit = ast::mutate_field_index(
    1193                         listInit, &ast::ListInit::designations, i,
    1194                         currentObject.findNext( listInit->designations[i] ) );
    1195                 listInit = ast::mutate_field_index(
    1196                         listInit, &ast::ListInit::initializers, i,
    1197                         listInit->initializers[i]->accept( *visitor ) );
    1198         }
    1199 
    1200         // move cursor out of brace-enclosed initializer-list
    1201         currentObject.exitListInit();
    1202 
    1203         visit_children = false;
    1204         return listInit;
    1205 }
    1206 
    1207 const ast::ConstructorInit * Resolver::previsit( const ast::ConstructorInit * ctorInit ) {
    1208         visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
    1209         visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
    1210 
    1211         // found a constructor - can get rid of C-style initializer
    1212         // xxx - Rob suggests this field is dead code
    1213         ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );
    1214 
    1215         // intrinsic single-parameter constructors and destructors do nothing. Since this was
    1216         // implicitly generated, there's no way for it to have side effects, so get rid of it to
    1217         // clean up generated code
    1218         if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
    1219                 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );
    1220         }
    1221         if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
    1222                 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );
    1223         }
    1224 
    1225         return ctorInit;
    1226 }
    1227 
    1228 // suppress error on autogen functions and mark invalid autogen as deleted.
    1229 bool Resolver::on_error(ast::ptr<ast::Decl> & decl) {
    1230         if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
    1231                 // xxx - can intrinsic gen ever fail?
    1232                 if (functionDecl->linkage == ast::Linkage::AutoGen) {
    1233                         auto mutDecl = mutate(functionDecl);
    1234                         mutDecl->isDeleted = true;
    1235                         mutDecl->stmts = nullptr;
    1236                         decl = mutDecl;
    1237                         return false;
    1238                 }
    1239         }
    1240         return true;
    1241 }
     1178                        }
     1179                }
     1180
     1181                // move cursor to next object in preparation for next initializer
     1182                currentObject.increment();
     1183
     1184                // set initializer expression to resolved expression
     1185                return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );
     1186        }
     1187
     1188        const ast::ListInit * Resolver::previsit( const ast::ListInit * listInit ) {
     1189                // move cursor into brace-enclosed initializer-list
     1190                currentObject.enterListInit( listInit->location );
     1191
     1192                assert( listInit->designations.size() == listInit->initializers.size() );
     1193                for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {
     1194                        // iterate designations and initializers in pairs, moving the cursor to the current
     1195                        // designated object and resolving the initializer against that object
     1196                        listInit = ast::mutate_field_index(
     1197                                listInit, &ast::ListInit::designations, i,
     1198                                currentObject.findNext( listInit->designations[i] ) );
     1199                        listInit = ast::mutate_field_index(
     1200                                listInit, &ast::ListInit::initializers, i,
     1201                                listInit->initializers[i]->accept( *visitor ) );
     1202                }
     1203
     1204                // move cursor out of brace-enclosed initializer-list
     1205                currentObject.exitListInit();
     1206
     1207                visit_children = false;
     1208                return listInit;
     1209        }
     1210
     1211        const ast::ConstructorInit * Resolver::previsit( const ast::ConstructorInit * ctorInit ) {
     1212                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
     1213                visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
     1214
     1215                // found a constructor - can get rid of C-style initializer
     1216                // xxx - Rob suggests this field is dead code
     1217                ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );
     1218
     1219                // intrinsic single-parameter constructors and destructors do nothing. Since this was
     1220                // implicitly generated, there's no way for it to have side effects, so get rid of it to
     1221                // clean up generated code
     1222                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
     1223                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );
     1224                }
     1225                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
     1226                        ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );
     1227                }
     1228
     1229                return ctorInit;
     1230        }
     1231
     1232        // suppress error on autogen functions and mark invalid autogen as deleted.
     1233        bool Resolver::on_error(ast::ptr<ast::Decl> & decl) {
     1234                if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
     1235                        // xxx - can intrinsic gen ever fail?
     1236                        if (functionDecl->linkage == ast::Linkage::AutoGen) {
     1237                                auto mutDecl = mutate(functionDecl);
     1238                                mutDecl->isDeleted = true;
     1239                                mutDecl->stmts = nullptr;
     1240                                decl = mutDecl;
     1241                                return false;
     1242                        }
     1243                }
     1244                return true;
     1245        }
    12421246
    12431247} // namespace ResolvExpr
Note: See TracChangeset for help on using the changeset viewer.