source: src/ResolvExpr/Resolver.cc @ 7583c02

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 7583c02 was 7583c02, checked in by Fangren Yu <f37yu@…>, 3 years ago

partially improve #226: resolver environment size reduced to O(n)

generated code still has exponential size. should cache resolved implicits
and reuse thunks to reduce generated code size.
assertion fails cannot exit early and may have a minor performance
reduction.

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