Ignore:
Timestamp:
Aug 27, 2018, 4:40:34 PM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
b7c89aa
Parents:
f9feab8 (diff), 305581d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into cleanup-dtors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    rf9feab8 r90152a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Aug  8 16:06:00 2017
    13 // Update Count     : 212
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb 17 11:19:40 2018
     13// Update Count     : 213
    1414//
    1515
     
    3030#include "RenameVars.h"                  // for RenameVars, global_renamer
    3131#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    32 #include "ResolveTypeof.h"               // for resolveTypeof
    3332#include "Resolver.h"
    3433#include "SymTab/Autogen.h"              // for SizeType
     
    5756                void postvisit( FunctionDecl *functionDecl );
    5857                void previsit( ObjectDecl *objectDecll );
    59                 void previsit( TypeDecl *typeDecl );
    6058                void previsit( EnumDecl * enumDecl );
     59                void previsit( StaticAssertDecl * assertDecl );
    6160
    6261                void previsit( ArrayType * at );
     
    7675                void previsit( CatchStmt *catchStmt );
    7776                void previsit( WaitForStmt * stmt );
    78                 void previsit( WithStmt * withStmt );
    7977
    8078                void previsit( SingleInit *singleInit );
     
    8280                void previsit( ConstructorInit *ctorInit );
    8381          private:
    84         typedef std::list< Initializer * >::iterator InitIterator;
     82                typedef std::list< Initializer * >::iterator InitIterator;
    8583
    8684                template< typename PtrType >
    8785                void handlePtrType( PtrType * type );
    8886
    89           void resolveAggrInit( ReferenceToType *, InitIterator &, InitIterator & );
    90           void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator &, TypeSubstitution sub );
    91           void fallbackInit( ConstructorInit * ctorInit );
     87                void fallbackInit( ConstructorInit * ctorInit );
    9288
    9389                Type * functionReturn = nullptr;
     
    9692        };
    9793
     94        struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
     95                void previsit( FunctionDecl * );
     96                void previsit( WithStmt * );
     97
     98                void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
     99        };
     100
    98101        void resolve( std::list< Declaration * > translationUnit ) {
    99102                PassVisitor<Resolver> resolver;
     
    106109        }
    107110
    108         // used in resolveTypeof
    109         Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
    110                 TypeEnvironment env;
    111                 return resolveInVoidContext( expr, indexer, env );
    112         }
    113 
    114111        namespace {
    115                 void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
     112                struct DeleteFinder : public WithShortCircuiting        {
     113                        DeletedExpr * delExpr = nullptr;
     114                        void previsit( DeletedExpr * expr ) {
     115                                if ( delExpr ) visit_children = false;
     116                                else delExpr = expr;
     117                        }
     118
     119                        void previsit( Expression * ) {
     120                                if ( delExpr ) visit_children = false;
     121                        }
     122                };
     123        }
     124
     125        DeletedExpr * findDeletedExpr( Expression * expr ) {
     126                PassVisitor<DeleteFinder> finder;
     127                expr->accept( finder );
     128                return finder.pass.delExpr;
     129        }
     130
     131        namespace {
     132                struct StripCasts {
     133                        Expression * postmutate( CastExpr * castExpr ) {
     134                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     135                                        // generated cast is to the same type as its argument, so it's unnecessary -- remove it
     136                                        Expression * expr = castExpr->arg;
     137                                        castExpr->arg = nullptr;
     138                                        std::swap( expr->env, castExpr->env );
     139                                        return expr;
     140                                }
     141                                return castExpr;
     142                        }
     143
     144                        static void strip( Expression *& expr ) {
     145                                PassVisitor<StripCasts> stripper;
     146                                expr = expr->acceptMutator( stripper );
     147                        }
     148                };
     149
     150                void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
    116151                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    117                         env.makeSubstitution( *expr->get_env() );
     152                        env.makeSubstitution( *expr->env );
     153                        StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
    118154                }
    119155
     
    131167        } // namespace
    132168
     169        namespace {
     170                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     171                        assertf( untyped, "expected a non-null expression." );
     172                        TypeEnvironment env;
     173                        AlternativeFinder finder( indexer, env );
     174                        finder.find( untyped, adjust, prune, failFast );
     175
     176                        #if 0
     177                        if ( finder.get_alternatives().size() != 1 ) {
     178                                std::cerr << "untyped expr is ";
     179                                untyped->print( std::cerr );
     180                                std::cerr << std::endl << "alternatives are:";
     181                                for ( const Alternative & alt : finder.get_alternatives() ) {
     182                                        alt.print( std::cerr );
     183                                } // for
     184                        } // if
     185                        #endif
     186
     187                        AltList candidates;
     188                        for ( Alternative & alt : finder.get_alternatives() ) {
     189                                if ( pred( alt ) ) {
     190                                        candidates.push_back( std::move( alt ) );
     191                                }
     192                        }
     193
     194                        // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
     195                        // choose the lowest cost expression among the candidates
     196                        AltList winners;
     197                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     198                        if ( winners.size() == 0 ) {
     199                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     200                        } else if ( winners.size() != 1 ) {
     201                                std::ostringstream stream;
     202                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     203                                untyped->print( stream );
     204                                stream << " Alternatives are:\n";
     205                                printAlts( winners, stream, 1 );
     206                                SemanticError( untyped->location, stream.str() );
     207                        }
     208
     209                        // there is one unambiguous interpretation - move the expression into the with statement
     210                        Alternative & choice = winners.front();
     211                        if ( findDeletedExpr( choice.expr ) ) {
     212                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
     213                        }
     214                        alt = std::move( choice );
     215                }
     216
     217                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
     218                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     219                        if ( ! untyped ) return;
     220                        Alternative choice;
     221                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     222                        finishExpr( choice.expr, choice.env, untyped->env );
     223                        delete untyped;
     224                        untyped = choice.expr;
     225                        choice.expr = nullptr;
     226                }
     227
     228                bool standardAlternativeFilter( const Alternative & ) {
     229                        // currently don't need to filter, under normal circumstances.
     230                        // in the future, this may be useful for removing deleted expressions
     231                        return true;
     232                }
     233        } // namespace
     234
     235        // used in resolveTypeof
     236        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
     237                TypeEnvironment env;
     238                return resolveInVoidContext( expr, indexer, env );
     239        }
     240
     241        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
     242                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
     243                // interpretations, an exception has already been thrown.
     244                assertf( expr, "expected a non-null expression." );
     245
     246                static CastExpr untyped( nullptr ); // cast to void
     247                untyped.location = expr->location;
     248
     249                // set up and resolve expression cast to void
     250                untyped.arg = expr;
     251                Alternative choice;
     252                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     253                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
     254                env = std::move( choice.env );
     255
     256                // clean up resolved expression
     257                Expression * ret = castExpr->arg;
     258                castExpr->arg = nullptr;
     259
     260                // unlink the arg so that it isn't deleted twice at the end of the program
     261                untyped.arg = nullptr;
     262                return ret;
     263        }
     264
    133265        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    134                 global_renamer.reset();
     266                resetTyVarRenaming();
    135267                TypeEnvironment env;
    136                 Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
     268                Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
    137269                finishExpr( newExpr, env, untyped->env );
    138270                delete untyped;
     
    141273
    142274        void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
    143                 if ( ! untyped ) return;
    144                 TypeEnvironment env;
    145                 AlternativeFinder finder( indexer, env );
    146                 finder.find( untyped );
    147                 #if 0
    148                 if ( finder.get_alternatives().size() != 1 ) {
    149                         std::cerr << "untyped expr is ";
    150                         untyped->print( std::cerr );
    151                         std::cerr << std::endl << "alternatives are:";
    152                         for ( const Alternative & alt : finder.get_alternatives() ) {
    153                                 alt.print( std::cerr );
    154                         } // for
    155                 } // if
    156                 #endif
    157                 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
    158                 Alternative &choice = finder.get_alternatives().front();
    159                 Expression *newExpr = choice.expr->clone();
    160                 finishExpr( newExpr, choice.env, untyped->env );
    161                 delete untyped;
    162                 untyped = newExpr;
     275                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    163276        }
    164277
    165278        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
    166279                assert( untyped && type );
     280                // transfer location to generated cast for error purposes
     281                CodeLocation location = untyped->location;
    167282                untyped = new CastExpr( untyped, type );
     283                untyped->location = location;
    168284                findSingleExpression( untyped, indexer );
    169285                removeExtraneousCast( untyped, indexer );
     
    171287
    172288        namespace {
    173                 bool isIntegralType( Type *type ) {
     289                bool isIntegralType( const Alternative & alt ) {
     290                        Type * type = alt.expr->result;
    174291                        if ( dynamic_cast< EnumInstType * >( type ) ) {
    175292                                return true;
     
    184301
    185302                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    186                         TypeEnvironment env;
    187                         AlternativeFinder finder( indexer, env );
    188                         finder.find( untyped );
    189 #if 0
    190                         if ( finder.get_alternatives().size() != 1 ) {
    191                                 std::cout << "untyped expr is ";
    192                                 untyped->print( std::cout );
    193                                 std::cout << std::endl << "alternatives are:";
    194                                 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    195                                         i->print( std::cout );
    196                                 } // for
    197                         } // if
    198 #endif
    199                         Expression *newExpr = 0;
    200                         const TypeEnvironment *newEnv = 0;
    201                         for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    202                                 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) {
    203                                         if ( newExpr ) {
    204                                                 throw SemanticError( "Too many interpretations for case control expression", untyped );
    205                                         } else {
    206                                                 newExpr = i->expr->clone();
    207                                                 newEnv = &i->env;
    208                                         } // if
    209                                 } // if
    210                         } // for
    211                         if ( ! newExpr ) {
    212                                 throw SemanticError( "No interpretations for case control expression", untyped );
    213                         } // if
    214                         finishExpr( newExpr, *newEnv, untyped->env );
    215                         delete untyped;
    216                         untyped = newExpr;
    217                 }
    218 
     303                        findKindExpression( untyped, indexer, "condition", isIntegralType );
     304                }
     305        }
     306
     307
     308        bool isStructOrUnion( const Alternative & alt ) {
     309                Type * t = alt.expr->result->stripReferences();
     310                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     311        }
     312
     313        void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
     314                PassVisitor<ResolveWithExprs> resolver;
     315                acceptAll( translationUnit, resolver );
     316        }
     317
     318        void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
     319                for ( Expression *& expr : withExprs )  {
     320                        // only struct- and union-typed expressions are viable candidates
     321                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
     322
     323                        // if with expression might be impure, create a temporary so that it is evaluated once
     324                        if ( Tuples::maybeImpure( expr ) ) {
     325                                static UniqueName tmpNamer( "_with_tmp_" );
     326                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
     327                                expr = new VariableExpr( tmp );
     328                                newStmts.push_back( new DeclStmt( tmp ) );
     329                                if ( InitTweak::isConstructable( tmp->type ) ) {
     330                                        // generate ctor/dtor and resolve them
     331                                        tmp->init = InitTweak::genCtorInit( tmp );
     332                                        tmp->accept( *visitor );
     333                                }
     334                        }
     335                }
     336        }
     337
     338        void ResolveWithExprs::previsit( WithStmt * withStmt ) {
     339                resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
     340        }
     341
     342        void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
     343                {
     344                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
     345                        // front of the function body.
     346                        auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
     347                        indexer.addFunctionType( functionDecl->type );
     348                        std::list< Statement * > newStmts;
     349                        resolveWithExprs( functionDecl->withExprs, newStmts );
     350                        if ( functionDecl->statements ) {
     351                                functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
     352                        } else {
     353                                assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
     354                        }
     355                }
    219356        }
    220357
    221358        void Resolver::previsit( ObjectDecl *objectDecl ) {
    222                 Type *new_type = resolveTypeof( objectDecl->get_type(), indexer );
    223                 objectDecl->set_type( new_type );
    224359                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
    225360                // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes
     
    251386        }
    252387
    253         void Resolver::previsit( TypeDecl *typeDecl ) {
    254                 if ( typeDecl->get_base() ) {
    255                         Type *new_type = resolveTypeof( typeDecl->get_base(), indexer );
    256                         typeDecl->set_base( new_type );
    257                 } // if
    258         }
    259 
    260388        void Resolver::previsit( FunctionDecl *functionDecl ) {
    261389#if 0
     
    264392                std::cerr << std::endl;
    265393#endif
    266                 Type *new_type = resolveTypeof( functionDecl->get_type(), indexer );
    267                 functionDecl->set_type( new_type );
    268394                GuardValue( functionReturn );
    269                 functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
     395                functionReturn = ResolvExpr::extractResultType( functionDecl->type );
    270396        }
    271397
     
    274400                // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
    275401                // see how it's useful.
    276                 for ( Declaration * d : functionDecl->get_functionType()->get_parameters() ) {
     402                for ( Declaration * d : functionDecl->type->parameters ) {
    277403                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
    278                                 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->get_init() ) ) {
    279                                         delete init->get_value()->get_env();
    280                                         init->get_value()->set_env( nullptr );
     404                                if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) {
     405                                        delete init->value->env;
     406                                        init->value->env = nullptr;
    281407                                }
    282408                        }
     
    290416        }
    291417
     418        void Resolver::previsit( StaticAssertDecl * assertDecl ) {
     419                findIntegralExpression( assertDecl->condition, indexer );
     420        }
     421
    292422        void Resolver::previsit( ExprStmt *exprStmt ) {
    293423                visit_children = false;
     
    311441
    312442        void Resolver::previsit( IfStmt *ifStmt ) {
    313                 findSingleExpression( ifStmt->condition, indexer );
     443                findIntegralExpression( ifStmt->condition, indexer );
    314444        }
    315445
    316446        void Resolver::previsit( WhileStmt *whileStmt ) {
    317                 findSingleExpression( whileStmt->condition, indexer );
     447                findIntegralExpression( whileStmt->condition, indexer );
    318448        }
    319449
    320450        void Resolver::previsit( ForStmt *forStmt ) {
    321451                if ( forStmt->condition ) {
    322                         findSingleExpression( forStmt->condition, indexer );
     452                        findIntegralExpression( forStmt->condition, indexer );
    323453                } // if
    324454
     
    336466
    337467        void Resolver::previsit( CaseStmt *caseStmt ) {
    338                 if ( caseStmt->get_condition() ) {
     468                if ( caseStmt->condition ) {
    339469                        std::list< InitAlternative > initAlts = currentObject.getOptions();
    340470                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
     
    342472                        Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
    343473                        findSingleExpression( newExpr, indexer );
    344                         CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
    345                         caseStmt->condition = castExpr->arg;
    346                         castExpr->arg = nullptr;
    347                         delete castExpr;
     474                        // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
     475                        // Ideally we would perform the conversion internally here.
     476                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
     477                                newExpr = castExpr->arg;
     478                                castExpr->arg = nullptr;
     479                                std::swap( newExpr->env, castExpr->env );
     480                                delete castExpr;
     481                        }
     482                        caseStmt->condition = newExpr;
    348483                }
    349484        }
     
    411546                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
    412547                                ss << "' in call to waitfor";
    413                                 throw SemanticError( ss.str() );
     548                                SemanticError( stmt->location, ss.str() );
     549                        }
     550
     551                        if(clause.target.arguments.empty()) {
     552                                SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
    414553                        }
    415554
     
    428567                        //      try matching the arguments to the parameters
    429568                        //      not the other way around because we have more arguments than parameters
    430                         SemanticError errors;
     569                        SemanticErrorException errors;
    431570                        for ( Alternative & func : funcFinder.get_alternatives() ) {
    432571                                try {
    433572                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
    434573                                        if( !pointer ) {
    435                                                 throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
     574                                                SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
    436575                                        }
    437576
    438577                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
    439578                                        if( !function ) {
    440                                                 throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
     579                                                SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
    441580                                        }
    442581
     
    447586
    448587                                                if( !advance_to_mutex( param, param_end ) ) {
    449                                                         throw SemanticError("candidate function not viable: no mutex parameters\n", function);
     588                                                        SemanticError(function, "candidate function not viable: no mutex parameters\n");
    450589                                                }
    451590                                        }
     
    453592                                        Alternative newFunc( func );
    454593                                        // Strip reference from function
    455                                         referenceToRvalueConversion( newFunc.expr );
     594                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    456595
    457596                                        // For all the set of arguments we have try to match it with the parameter of the current function alternative
     
    462601                                                        OpenVarSet openVars;
    463602                                                        AssertionSet resultNeed, resultHave;
    464                                                         TypeEnvironment resultEnv;
     603                                                        TypeEnvironment resultEnv( func.env );
     604                                                        makeUnifiableVars( function, openVars, resultNeed );
     605                                                        // add all type variables as open variables now so that those not used in the parameter
     606                                                        // list are still considered open.
     607                                                        resultEnv.add( function->forall );
    465608
    466609                                                        // Load type variables from arguemnts into one shared space
     
    468611
    469612                                                        // Make sure we don't widen any existing bindings
    470                                                         for ( auto & i : resultEnv ) {
    471                                                                 i.allowWidening = false;
    472                                                         }
     613                                                        resultEnv.forbidWidening();
    473614
    474615                                                        // Find any unbound type variables
     
    477618                                                        auto param     = function->parameters.begin();
    478619                                                        auto param_end = function->parameters.end();
     620
     621                                                        int n_mutex_param = 0;
    479622
    480623                                                        // For every arguments of its set, check if it matches one of the parameter
     
    486629                                                                        // We ran out of parameters but still have arguments
    487630                                                                        // this function doesn't match
    488                                                                         throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
     631                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
    489632                                                                }
    490633
     634                                                                n_mutex_param++;
     635
    491636                                                                // Check if the argument matches the parameter type in the current scope
    492                                                                 if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
     637                                                                if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
    493638                                                                        // Type doesn't match
    494639                                                                        stringstream ss;
    495640                                                                        ss << "candidate function not viable: no known convertion from '";
     641                                                                        (*param)->get_type()->print( ss );
     642                                                                        ss << "' to '";
    496643                                                                        arg.expr->get_result()->print( ss );
    497                                                                         ss << "' to '";
    498                                                                         (*param)->get_type()->print( ss );
     644                                                                        ss << "' with env '";
     645                                                                        resultEnv.print(ss);
    499646                                                                        ss << "'\n";
    500                                                                         throw SemanticError(ss.str(), function);
     647                                                                        SemanticError( function, ss.str() );
    501648                                                                }
    502649
     
    508655                                                        // Check if parameters are missing
    509656                                                        if( advance_to_mutex( param, param_end ) ) {
     657                                                                do {
     658                                                                        n_mutex_param++;
     659                                                                        param++;
     660                                                                } while( advance_to_mutex( param, param_end ) );
     661
    510662                                                                // We ran out of arguments but still have parameters left
    511663                                                                // this function doesn't match
    512                                                                 throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
     664                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
    513665                                                        }
    514666
     
    526678
    527679                                                }
    528                                                 catch( SemanticError &e ) {
     680                                                catch( SemanticErrorException &e ) {
    529681                                                        errors.append( e );
    530682                                                }
    531683                                        }
    532684                                }
    533                                 catch( SemanticError &e ) {
     685                                catch( SemanticErrorException &e ) {
    534686                                        errors.append( e );
    535687                                }
     
    537689
    538690                        // Make sure we got the right number of arguments
    539                         if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
    540                         if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
    541                         if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
    542                         if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
    543 
     691                        if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     692                        if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     693                        if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     694                        if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     695                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    544696
    545697                        // Swap the results from the alternative with the unresolved values.
     
    574726        }
    575727
    576         bool isStructOrUnion( Type * t ) {
    577                 t = t->stripReferences();
    578                 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    579         }
    580 
    581         void Resolver::previsit( WithStmt * withStmt ) {
    582                 for ( Expression *& expr : withStmt->exprs )  {
    583                         TypeEnvironment env;
    584                         AlternativeFinder finder( indexer, env );
    585                         finder.findWithAdjustment( expr );
    586 
    587                         // only struct- and union-typed expressions are viable candidates
    588                         AltList candidates;
    589                         for ( Alternative & alt : finder.get_alternatives() ) {
    590                                 if ( isStructOrUnion( alt.expr->result ) ) {
    591                                         candidates.push_back( std::move( alt ) );
    592                                 }
    593                         }
    594 
    595                         // choose the lowest cost expression among the candidates
    596                         AltList winners;
    597                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    598                         if ( winners.size() == 0 ) {
    599                                 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr );
    600                         } else if ( winners.size() != 1 ) {
    601                                 std::ostringstream stream;
    602                                 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n";
    603                                 expr->print( stream );
    604                                 stream << "Alternatives are:\n";
    605                                 printAlts( winners, stream, 1 );
    606                                 throw SemanticError( stream.str() );
    607                         }
    608 
    609                         // there is one unambiguous interpretation - move the expression into the with statement
    610                         Alternative & alt = winners.front();
    611                         finishExpr( alt.expr, alt.env, expr->env );
    612                         delete expr;
    613                         expr = alt.expr;
    614                         alt.expr = nullptr;
    615 
    616                         // if with expression might be impure, create a temporary so that it is evaluated once
    617                         if ( Tuples::maybeImpure( expr ) ) {
    618                                 static UniqueName tmpNamer( "_with_tmp_" );
    619                                 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
    620                                 expr = new VariableExpr( tmp );
    621                                 stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
    622                                 if ( InitTweak::isConstructable( tmp->type ) ) {
    623                                         // generate ctor/dtor and resolve them
    624                                         tmp->init = InitTweak::genCtorInit( tmp );
    625                                         tmp->accept( *visitor );
    626                                 }
    627                         }
    628                 }
    629         }
    630 
    631728        template< typename T >
    632729        bool isCharType( T t ) {
     
    652749                initExpr->expr = nullptr;
    653750                std::swap( initExpr->env, newExpr->env );
    654                 std::swap( initExpr->inferParams, newExpr->inferParams ) ;
     751                // InitExpr may have inferParams in the case where the expression specializes a function pointer,
     752                // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
     753                newExpr->spliceInferParams( initExpr );
    655754                delete initExpr;
    656755
     
    740839                PassVisitor<Resolver> resolver( indexer );
    741840                stmtExpr->accept( resolver );
     841                stmtExpr->computeResult();
     842                // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
    742843        }
    743844
     
    745846                visit_children = false;
    746847                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
    747                 maybeAccept( ctorInit->get_ctor(), *visitor );
    748                 maybeAccept( ctorInit->get_dtor(), *visitor );
     848                maybeAccept( ctorInit->ctor, *visitor );
     849                maybeAccept( ctorInit->dtor, *visitor );
    749850
    750851                // found a constructor - can get rid of C-style initializer
    751                 delete ctorInit->get_init();
    752                 ctorInit->set_init( NULL );
     852                delete ctorInit->init;
     853                ctorInit->init = nullptr;
    753854
    754855                // intrinsic single parameter constructors and destructors do nothing. Since this was
    755856                // implicitly generated, there's no way for it to have side effects, so get rid of it
    756857                // to clean up generated code.
    757                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
    758                         delete ctorInit->get_ctor();
    759                         ctorInit->set_ctor( NULL );
    760                 }
    761 
    762                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
    763                         delete ctorInit->get_dtor();
    764                         ctorInit->set_dtor( NULL );
     858                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
     859                        delete ctorInit->ctor;
     860                        ctorInit->ctor = nullptr;
     861                }
     862
     863                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
     864                        delete ctorInit->dtor;
     865                        ctorInit->dtor = nullptr;
    765866                }
    766867
Note: See TracChangeset for help on using the changeset viewer.