Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    rc6b4432 r4894239  
    1919#include <vector>                        // for vector
    2020
     21#include "Alternative.h"                 // for Alternative, AltList
     22#include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
    2123#include "Candidate.hpp"
    2224#include "CandidateFinder.hpp"
     
    3840#include "Common/Eval.h"                 // for eval
    3941#include "Common/Iterate.hpp"            // for group_iterate
     42#include "Common/PassVisitor.h"          // for PassVisitor
    4043#include "Common/SemanticError.h"        // for SemanticError
    4144#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    4245#include "Common/ToString.hpp"           // for toCString
    43 #include "Common/UniqueName.h"           // for UniqueName
    4446#include "InitTweak/GenInit.h"
    4547#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
     48#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     49#include "SymTab/Autogen.h"              // for SizeType
     50#include "SymTab/Indexer.h"              // for Indexer
    4651#include "SymTab/Mangler.h"              // for Mangler
     52#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
     53#include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
     54#include "SynTree/Initializer.h"         // for ConstructorInit, SingleInit
     55#include "SynTree/Statement.h"           // for ForStmt, Statement, BranchStmt
     56#include "SynTree/Type.h"                // for Type, BasicType, PointerType
     57#include "SynTree/TypeSubstitution.h"    // for TypeSubstitution
     58#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    4759#include "Tuples/Tuples.h"
    4860#include "Validate/FindSpecialDecls.h"   // for SizeType
     
    5163
    5264namespace ResolvExpr {
     65        struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
     66                Resolver_old() {}
     67                Resolver_old( const SymTab::Indexer & other ) {
     68                        indexer = other;
     69                }
     70
     71                void previsit( FunctionDecl * functionDecl );
     72                void postvisit( FunctionDecl * functionDecl );
     73                void previsit( ObjectDecl * objectDecll );
     74                void previsit( EnumDecl * enumDecl );
     75                void previsit( StaticAssertDecl * assertDecl );
     76
     77                void previsit( ArrayType * at );
     78                void previsit( PointerType * at );
     79
     80                void previsit( ExprStmt * exprStmt );
     81                void previsit( AsmExpr * asmExpr );
     82                void previsit( AsmStmt * asmStmt );
     83                void previsit( IfStmt * ifStmt );
     84                void previsit( WhileDoStmt * whileDoStmt );
     85                void previsit( ForStmt * forStmt );
     86                void previsit( SwitchStmt * switchStmt );
     87                void previsit( CaseStmt * caseStmt );
     88                void previsit( BranchStmt * branchStmt );
     89                void previsit( ReturnStmt * returnStmt );
     90                void previsit( ThrowStmt * throwStmt );
     91                void previsit( CatchStmt * catchStmt );
     92                void postvisit( CatchStmt * catchStmt );
     93                void previsit( WaitForStmt * stmt );
     94
     95                void previsit( SingleInit * singleInit );
     96                void previsit( ListInit * listInit );
     97                void previsit( ConstructorInit * ctorInit );
     98          private:
     99                typedef std::list< Initializer * >::iterator InitIterator;
     100
     101                template< typename PtrType >
     102                void handlePtrType( PtrType * type );
     103
     104                void fallbackInit( ConstructorInit * ctorInit );
     105
     106                Type * functionReturn = nullptr;
     107                CurrentObject currentObject = nullptr;
     108                bool inEnumDecl = false;
     109        };
     110
     111        struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
     112                void previsit( FunctionDecl * );
     113                void previsit( WithStmt * );
     114
     115                void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
     116        };
     117
     118        void resolve( std::list< Declaration * > translationUnit ) {
     119                PassVisitor<Resolver_old> resolver;
     120                acceptAll( translationUnit, resolver );
     121        }
     122
     123        void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
     124                PassVisitor<Resolver_old> resolver( indexer );
     125                maybeAccept( decl, resolver );
     126        }
     127
     128        namespace {
     129                struct DeleteFinder_old : public WithShortCircuiting    {
     130                        DeletedExpr * delExpr = nullptr;
     131                        void previsit( DeletedExpr * expr ) {
     132                                if ( delExpr ) visit_children = false;
     133                                else delExpr = expr;
     134                        }
     135
     136                        void previsit( Expression * ) {
     137                                if ( delExpr ) visit_children = false;
     138                        }
     139                };
     140        }
     141
     142        DeletedExpr * findDeletedExpr( Expression * expr ) {
     143                PassVisitor<DeleteFinder_old> finder;
     144                expr->accept( finder );
     145                return finder.pass.delExpr;
     146        }
     147
     148        namespace {
     149                struct StripCasts_old {
     150                        Expression * postmutate( CastExpr * castExpr ) {
     151                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     152                                        // generated cast is to the same type as its argument, so it's unnecessary -- remove it
     153                                        Expression * expr = castExpr->arg;
     154                                        castExpr->arg = nullptr;
     155                                        std::swap( expr->env, castExpr->env );
     156                                        return expr;
     157                                }
     158                                return castExpr;
     159                        }
     160
     161                        static void strip( Expression *& expr ) {
     162                                PassVisitor<StripCasts_old> stripper;
     163                                expr = expr->acceptMutator( stripper );
     164                        }
     165                };
     166
     167                void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
     168                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
     169                        env.makeSubstitution( *expr->env );
     170                        StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
     171                }
     172
     173                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
     174                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     175                                if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     176                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
     177                                        expr = castExpr->arg;
     178                                        castExpr->arg = nullptr;
     179                                        std::swap( expr->env, castExpr->env );
     180                                        delete castExpr;
     181                                }
     182                        }
     183                }
     184        } // namespace
     185
     186        namespace {
     187                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
     188                        assertf( untyped, "expected a non-null expression." );
     189
     190                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
     191                        static unsigned recursion_level = 0;
     192
     193                        ++recursion_level;
     194                        TypeEnvironment env;
     195                        AlternativeFinder finder( indexer, env );
     196                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     197                        --recursion_level;
     198
     199                        #if 0
     200                        if ( finder.get_alternatives().size() != 1 ) {
     201                                std::cerr << "untyped expr is ";
     202                                untyped->print( std::cerr );
     203                                std::cerr << std::endl << "alternatives are:";
     204                                for ( const Alternative & alt : finder.get_alternatives() ) {
     205                                        alt.print( std::cerr );
     206                                } // for
     207                        } // if
     208                        #endif
     209
     210                        // produce filtered list of alternatives
     211                        AltList candidates;
     212                        for ( Alternative & alt : finder.get_alternatives() ) {
     213                                if ( pred( alt ) ) {
     214                                        candidates.push_back( std::move( alt ) );
     215                                }
     216                        }
     217
     218                        // produce invalid error if no candidates
     219                        if ( candidates.empty() ) {
     220                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     221                        }
     222
     223                        // search for cheapest candidate
     224                        AltList winners;
     225                        bool seen_undeleted = false;
     226                        for ( unsigned i = 0; i < candidates.size(); ++i ) {
     227                                int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
     228
     229                                if ( c > 0 ) continue; // skip more expensive than winner
     230
     231                                if ( c < 0 ) {
     232                                        // reset on new cheapest
     233                                        seen_undeleted = ! findDeletedExpr( candidates[i].expr );
     234                                        winners.clear();
     235                                } else /* if ( c == 0 ) */ {
     236                                        if ( findDeletedExpr( candidates[i].expr ) ) {
     237                                                // skip deleted expression if already seen one equivalent-cost not
     238                                                if ( seen_undeleted ) continue;
     239                                        } else if ( ! seen_undeleted ) {
     240                                                // replace list of equivalent-cost deleted expressions with one non-deleted
     241                                                winners.clear();
     242                                                seen_undeleted = true;
     243                                        }
     244                                }
     245
     246                                winners.emplace_back( std::move( candidates[i] ) );
     247                        }
     248
     249                        // promote alternative.cvtCost to .cost
     250                        // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
     251                        for ( Alternative& winner : winners ) {
     252                                winner.cost = winner.cvtCost;
     253                        }
     254
     255                        // produce ambiguous errors, if applicable
     256                        if ( winners.size() != 1 ) {
     257                                std::ostringstream stream;
     258                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     259                                untyped->print( stream );
     260                                stream << " Alternatives are:\n";
     261                                printAlts( winners, stream, 1 );
     262                                SemanticError( untyped->location, stream.str() );
     263                        }
     264
     265                        // single selected choice
     266                        Alternative& choice = winners.front();
     267
     268                        // fail on only expression deleted
     269                        if ( ! seen_undeleted ) {
     270                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
     271                        }
     272
     273                        // xxx - check for ambiguous expressions
     274
     275                        // output selected choice
     276                        alt = std::move( choice );
     277                }
     278
     279                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
     280                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
     281                        if ( ! untyped ) return;
     282                        Alternative choice;
     283                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
     284                        finishExpr( choice.expr, choice.env, untyped->env );
     285                        delete untyped;
     286                        untyped = choice.expr;
     287                        choice.expr = nullptr;
     288                }
     289
     290                bool standardAlternativeFilter( const Alternative & ) {
     291                        // currently don't need to filter, under normal circumstances.
     292                        // in the future, this may be useful for removing deleted expressions
     293                        return true;
     294                }
     295        } // namespace
     296
     297        // used in resolveTypeof
     298        Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
     299                TypeEnvironment env;
     300                return resolveInVoidContext( expr, indexer, env );
     301        }
     302
     303        Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
     304                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
     305                // interpretations, an exception has already been thrown.
     306                assertf( expr, "expected a non-null expression." );
     307
     308                CastExpr * untyped = new CastExpr( expr ); // cast to void
     309                untyped->location = expr->location;
     310
     311                // set up and resolve expression cast to void
     312                Alternative choice;
     313                findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
     314                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
     315                assert( castExpr );
     316                env = std::move( choice.env );
     317
     318                // clean up resolved expression
     319                Expression * ret = castExpr->arg;
     320                castExpr->arg = nullptr;
     321
     322                // unlink the arg so that it isn't deleted twice at the end of the program
     323                untyped->arg = nullptr;
     324                return ret;
     325        }
     326
     327        void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     328                resetTyVarRenaming();
     329                TypeEnvironment env;
     330                Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
     331                finishExpr( newExpr, env, untyped->env );
     332                delete untyped;
     333                untyped = newExpr;
     334        }
     335
     336        void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     337                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
     338        }
     339
     340        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
     341                assert( untyped && type );
     342                // transfer location to generated cast for error purposes
     343                CodeLocation location = untyped->location;
     344                untyped = new CastExpr( untyped, type );
     345                untyped->location = location;
     346                findSingleExpression( untyped, indexer );
     347                removeExtraneousCast( untyped, indexer );
     348        }
     349
     350        namespace {
     351                bool isIntegralType( const Alternative & alt ) {
     352                        Type * type = alt.expr->result;
     353                        if ( dynamic_cast< EnumInstType * >( type ) ) {
     354                                return true;
     355                        } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
     356                                return bt->isInteger();
     357                        } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
     358                                return true;
     359                        } else {
     360                                return false;
     361                        } // if
     362                }
     363
     364                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     365                        findKindExpression( untyped, indexer, "condition", isIntegralType );
     366                }
     367        }
     368
     369
     370        bool isStructOrUnion( const Alternative & alt ) {
     371                Type * t = alt.expr->result->stripReferences();
     372                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     373        }
     374
     375        void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
     376                PassVisitor<ResolveWithExprs> resolver;
     377                acceptAll( translationUnit, resolver );
     378        }
     379
     380        void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
     381                for ( Expression *& expr : withExprs )  {
     382                        // only struct- and union-typed expressions are viable candidates
     383                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
     384
     385                        // if with expression might be impure, create a temporary so that it is evaluated once
     386                        if ( Tuples::maybeImpure( expr ) ) {
     387                                static UniqueName tmpNamer( "_with_tmp_" );
     388                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
     389                                expr = new VariableExpr( tmp );
     390                                newStmts.push_back( new DeclStmt( tmp ) );
     391                                if ( InitTweak::isConstructable( tmp->type ) ) {
     392                                        // generate ctor/dtor and resolve them
     393                                        tmp->init = InitTweak::genCtorInit( tmp );
     394                                        tmp->accept( *visitor );
     395                                }
     396                        }
     397                }
     398        }
     399
     400        void ResolveWithExprs::previsit( WithStmt * withStmt ) {
     401                resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
     402        }
     403
     404        void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
     405                {
     406                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
     407                        // front of the function body.
     408                        auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
     409                        indexer.addFunctionType( functionDecl->type );
     410                        std::list< Statement * > newStmts;
     411                        resolveWithExprs( functionDecl->withExprs, newStmts );
     412                        if ( functionDecl->statements ) {
     413                                functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
     414                        } else {
     415                                assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
     416                        }
     417                }
     418        }
     419
     420        void Resolver_old::previsit( ObjectDecl * objectDecl ) {
     421                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
     422                // class-variable initContext is changed multiple time because the LHS is analysed twice.
     423                // The second analysis changes initContext because of a function type can contain object
     424                // declarations in the return and parameter types. So each value of initContext is
     425                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
     426                GuardValue( currentObject );
     427                currentObject = CurrentObject( objectDecl->get_type() );
     428                if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
     429                        // enumerator initializers should not use the enum type to initialize, since
     430                        // the enum type is still incomplete at this point. Use signed int instead.
     431                        // TODO: BasicType::SignedInt may not longer be true
     432                        currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     433                }
     434        }
     435
     436        template< typename PtrType >
     437        void Resolver_old::handlePtrType( PtrType * type ) {
     438                if ( type->get_dimension() ) {
     439                        findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
     440                }
     441        }
     442
     443        void Resolver_old::previsit( ArrayType * at ) {
     444                handlePtrType( at );
     445        }
     446
     447        void Resolver_old::previsit( PointerType * pt ) {
     448                handlePtrType( pt );
     449        }
     450
     451        void Resolver_old::previsit( FunctionDecl * functionDecl ) {
     452#if 0
     453                std::cerr << "resolver visiting functiondecl ";
     454                functionDecl->print( std::cerr );
     455                std::cerr << std::endl;
     456#endif
     457                GuardValue( functionReturn );
     458                functionReturn = ResolvExpr::extractResultType( functionDecl->type );
     459        }
     460
     461        void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
     462                // default value expressions have an environment which shouldn't be there and trips up
     463                // later passes.
     464                // xxx - it might be necessary to somehow keep the information from this environment, but I
     465                // can't currently see how it's useful.
     466                for ( Declaration * d : functionDecl->type->parameters ) {
     467                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     468                                if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) {
     469                                        delete init->value->env;
     470                                        init->value->env = nullptr;
     471                                }
     472                        }
     473                }
     474        }
     475
     476        void Resolver_old::previsit( EnumDecl * ) {
     477                // in case we decide to allow nested enums
     478                GuardValue( inEnumDecl );
     479                inEnumDecl = true;
     480        }
     481
     482        void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
     483                findIntegralExpression( assertDecl->condition, indexer );
     484        }
     485
     486        void Resolver_old::previsit( ExprStmt * exprStmt ) {
     487                visit_children = false;
     488                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
     489                findVoidExpression( exprStmt->expr, indexer );
     490        }
     491
     492        void Resolver_old::previsit( AsmExpr * asmExpr ) {
     493                visit_children = false;
     494                findVoidExpression( asmExpr->operand, indexer );
     495        }
     496
     497        void Resolver_old::previsit( AsmStmt * asmStmt ) {
     498                visit_children = false;
     499                acceptAll( asmStmt->get_input(), *visitor );
     500                acceptAll( asmStmt->get_output(), *visitor );
     501        }
     502
     503        void Resolver_old::previsit( IfStmt * ifStmt ) {
     504                findIntegralExpression( ifStmt->condition, indexer );
     505        }
     506
     507        void Resolver_old::previsit( WhileDoStmt * whileDoStmt ) {
     508                findIntegralExpression( whileDoStmt->condition, indexer );
     509        }
     510
     511        void Resolver_old::previsit( ForStmt * forStmt ) {
     512                if ( forStmt->condition ) {
     513                        findIntegralExpression( forStmt->condition, indexer );
     514                } // if
     515
     516                if ( forStmt->increment ) {
     517                        findVoidExpression( forStmt->increment, indexer );
     518                } // if
     519        }
     520
     521        void Resolver_old::previsit( SwitchStmt * switchStmt ) {
     522                GuardValue( currentObject );
     523                findIntegralExpression( switchStmt->condition, indexer );
     524
     525                currentObject = CurrentObject( switchStmt->condition->result );
     526        }
     527
     528        void Resolver_old::previsit( CaseStmt * caseStmt ) {
     529                if ( caseStmt->condition ) {
     530                        std::list< InitAlternative > initAlts = currentObject.getOptions();
     531                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
     532                        // must remove cast from case statement because RangeExpr cannot be cast.
     533                        Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
     534                        findSingleExpression( newExpr, indexer );
     535                        // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
     536                        // Ideally we would perform the conversion internally here.
     537                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
     538                                newExpr = castExpr->arg;
     539                                castExpr->arg = nullptr;
     540                                std::swap( newExpr->env, castExpr->env );
     541                                delete castExpr;
     542                        }
     543                        caseStmt->condition = newExpr;
     544                }
     545        }
     546
     547        void Resolver_old::previsit( BranchStmt * branchStmt ) {
     548                visit_children = false;
     549                // must resolve the argument for a computed goto
     550                if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
     551                        if ( branchStmt->computedTarget ) {
     552                                // computed goto argument is void *
     553                                findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer );
     554                        } // if
     555                } // if
     556        }
     557
     558        void Resolver_old::previsit( ReturnStmt * returnStmt ) {
     559                visit_children = false;
     560                if ( returnStmt->expr ) {
     561                        findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer );
     562                } // if
     563        }
     564
     565        void Resolver_old::previsit( ThrowStmt * throwStmt ) {
     566                visit_children = false;
     567                // TODO: Replace *exception type with &exception type.
     568                if ( throwStmt->get_expr() ) {
     569                        const StructDecl * exception_decl = indexer.lookupStruct( "__cfaehm_base_exception_t" );
     570                        assert( exception_decl );
     571                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
     572                        findSingleExpression( throwStmt->expr, exceptType, indexer );
     573                }
     574        }
     575
     576        void Resolver_old::previsit( CatchStmt * catchStmt ) {
     577                // Until we are very sure this invarent (ifs that move between passes have then)
     578                // holds, check it. This allows a check for when to decode the mangling.
     579                if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) {
     580                        assert( ifStmt->then );
     581                }
     582                // Encode the catchStmt so the condition can see the declaration.
     583                if ( catchStmt->cond ) {
     584                        IfStmt * ifStmt = new IfStmt( catchStmt->cond, nullptr, catchStmt->body );
     585                        catchStmt->cond = nullptr;
     586                        catchStmt->body = ifStmt;
     587                }
     588        }
     589
     590        void Resolver_old::postvisit( CatchStmt * catchStmt ) {
     591                // Decode the catchStmt so everything is stored properly.
     592                IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body );
     593                if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
     594                        assert( ifStmt->condition );
     595                        assert( ifStmt->else_ );
     596                        catchStmt->cond = ifStmt->condition;
     597                        catchStmt->body = ifStmt->else_;
     598                        ifStmt->condition = nullptr;
     599                        ifStmt->else_ = nullptr;
     600                        delete ifStmt;
     601                }
     602        }
     603
    53604        template< typename iterator_t >
    54605        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
     
    59610                return it != end;
    60611        }
     612
     613        void Resolver_old::previsit( WaitForStmt * stmt ) {
     614                visit_children = false;
     615
     616                // Resolve all clauses first
     617                for( auto& clause : stmt->clauses ) {
     618
     619                        TypeEnvironment env;
     620                        AlternativeFinder funcFinder( indexer, env );
     621
     622                        // Find all alternatives for a function in canonical form
     623                        funcFinder.findWithAdjustment( clause.target.function );
     624
     625                        if ( funcFinder.get_alternatives().empty() ) {
     626                                stringstream ss;
     627                                ss << "Use of undeclared indentifier '";
     628                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
     629                                ss << "' in call to waitfor";
     630                                SemanticError( stmt->location, ss.str() );
     631                        }
     632
     633                        if(clause.target.arguments.empty()) {
     634                                SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
     635                        }
     636
     637                        // Find all alternatives for all arguments in canonical form
     638                        std::vector< AlternativeFinder > argAlternatives;
     639                        funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
     640
     641                        // List all combinations of arguments
     642                        std::vector< AltList > possibilities;
     643                        combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
     644
     645                        AltList                func_candidates;
     646                        std::vector< AltList > args_candidates;
     647
     648                        // For every possible function :
     649                        //      try matching the arguments to the parameters
     650                        //      not the other way around because we have more arguments than parameters
     651                        SemanticErrorException errors;
     652                        for ( Alternative & func : funcFinder.get_alternatives() ) {
     653                                try {
     654                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
     655                                        if( !pointer ) {
     656                                                SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
     657                                        }
     658
     659                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
     660                                        if( !function ) {
     661                                                SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
     662                                        }
     663
     664
     665                                        {
     666                                                auto param     = function->parameters.begin();
     667                                                auto param_end = function->parameters.end();
     668
     669                                                if( !advance_to_mutex( param, param_end ) ) {
     670                                                        SemanticError(function, "candidate function not viable: no mutex parameters\n");
     671                                                }
     672                                        }
     673
     674                                        Alternative newFunc( func );
     675                                        // Strip reference from function
     676                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
     677
     678                                        // For all the set of arguments we have try to match it with the parameter of the current function alternative
     679                                        for ( auto & argsList : possibilities ) {
     680
     681                                                try {
     682                                                        // Declare data structures need for resolution
     683                                                        OpenVarSet openVars;
     684                                                        AssertionSet resultNeed, resultHave;
     685                                                        TypeEnvironment resultEnv( func.env );
     686                                                        makeUnifiableVars( function, openVars, resultNeed );
     687                                                        // add all type variables as open variables now so that those not used in the parameter
     688                                                        // list are still considered open.
     689                                                        resultEnv.add( function->forall );
     690
     691                                                        // Load type variables from arguemnts into one shared space
     692                                                        simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
     693
     694                                                        // Make sure we don't widen any existing bindings
     695                                                        resultEnv.forbidWidening();
     696
     697                                                        // Find any unbound type variables
     698                                                        resultEnv.extractOpenVars( openVars );
     699
     700                                                        auto param     = function->parameters.begin();
     701                                                        auto param_end = function->parameters.end();
     702
     703                                                        int n_mutex_param = 0;
     704
     705                                                        // For every arguments of its set, check if it matches one of the parameter
     706                                                        // The order is important
     707                                                        for( auto & arg : argsList ) {
     708
     709                                                                // Ignore non-mutex arguments
     710                                                                if( !advance_to_mutex( param, param_end ) ) {
     711                                                                        // We ran out of parameters but still have arguments
     712                                                                        // this function doesn't match
     713                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
     714                                                                }
     715
     716                                                                n_mutex_param++;
     717
     718                                                                // Check if the argument matches the parameter type in the current scope
     719                                                                if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
     720                                                                        // Type doesn't match
     721                                                                        stringstream ss;
     722                                                                        ss << "candidate function not viable: no known convertion from '";
     723                                                                        (*param)->get_type()->print( ss );
     724                                                                        ss << "' to '";
     725                                                                        arg.expr->get_result()->print( ss );
     726                                                                        ss << "' with env '";
     727                                                                        resultEnv.print(ss);
     728                                                                        ss << "'\n";
     729                                                                        SemanticError( function, ss.str() );
     730                                                                }
     731
     732                                                                param++;
     733                                                        }
     734
     735                                                        // All arguments match !
     736
     737                                                        // Check if parameters are missing
     738                                                        if( advance_to_mutex( param, param_end ) ) {
     739                                                                do {
     740                                                                        n_mutex_param++;
     741                                                                        param++;
     742                                                                } while( advance_to_mutex( param, param_end ) );
     743
     744                                                                // We ran out of arguments but still have parameters left
     745                                                                // this function doesn't match
     746                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
     747                                                        }
     748
     749                                                        // All parameters match !
     750
     751                                                        // Finish the expressions to tie in the proper environments
     752                                                        finishExpr( newFunc.expr, resultEnv );
     753                                                        for( Alternative & alt : argsList ) {
     754                                                                finishExpr( alt.expr, resultEnv );
     755                                                        }
     756
     757                                                        // This is a match store it and save it for later
     758                                                        func_candidates.push_back( newFunc );
     759                                                        args_candidates.push_back( argsList );
     760
     761                                                }
     762                                                catch( SemanticErrorException & e ) {
     763                                                        errors.append( e );
     764                                                }
     765                                        }
     766                                }
     767                                catch( SemanticErrorException & e ) {
     768                                        errors.append( e );
     769                                }
     770                        }
     771
     772                        // Make sure we got the right number of arguments
     773                        if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     774                        if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     775                        if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     776                        if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     777                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
     778
     779                        // Swap the results from the alternative with the unresolved values.
     780                        // Alternatives will handle deletion on destruction
     781                        std::swap( clause.target.function, func_candidates.front().expr );
     782                        for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
     783                                std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
     784                        }
     785
     786                        // Resolve the conditions as if it were an IfStmt
     787                        // Resolve the statments normally
     788                        findSingleExpression( clause.condition, this->indexer );
     789                        clause.statement->accept( *visitor );
     790                }
     791
     792
     793                if( stmt->timeout.statement ) {
     794                        // Resolve the timeout as an size_t for now
     795                        // Resolve the conditions as if it were an IfStmt
     796                        // Resolve the statments normally
     797                        findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
     798                        findSingleExpression( stmt->timeout.condition, this->indexer );
     799                        stmt->timeout.statement->accept( *visitor );
     800                }
     801
     802                if( stmt->orelse.statement ) {
     803                        // Resolve the conditions as if it were an IfStmt
     804                        // Resolve the statments normally
     805                        findSingleExpression( stmt->orelse.condition, this->indexer );
     806                        stmt->orelse.statement->accept( *visitor );
     807                }
     808        }
     809
     810        bool isCharType( Type * t ) {
     811                if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
     812                        return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
     813                                bt->get_kind() == BasicType::UnsignedChar;
     814                }
     815                return false;
     816        }
     817
     818        void Resolver_old::previsit( SingleInit * singleInit ) {
     819                visit_children = false;
     820                // resolve initialization using the possibilities as determined by the currentObject cursor
     821                Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() );
     822                findSingleExpression( newExpr, indexer );
     823                InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
     824
     825                // move cursor to the object that is actually initialized
     826                currentObject.setNext( initExpr->get_designation() );
     827
     828                // discard InitExpr wrapper and retain relevant pieces
     829                newExpr = initExpr->expr;
     830                initExpr->expr = nullptr;
     831                std::swap( initExpr->env, newExpr->env );
     832                // InitExpr may have inferParams in the case where the expression specializes a function
     833                // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
     834                // sufficient.
     835                newExpr->spliceInferParams( initExpr );
     836                delete initExpr;
     837
     838                // get the actual object's type (may not exactly match what comes back from the resolver
     839                // due to conversions)
     840                Type * initContext = currentObject.getCurrentType();
     841
     842                removeExtraneousCast( newExpr, indexer );
     843
     844                // check if actual object's type is char[]
     845                if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
     846                        if ( isCharType( at->get_base() ) ) {
     847                                // check if the resolved type is char *
     848                                if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
     849                                        if ( isCharType( pt->get_base() ) ) {
     850                                                if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) {
     851                                                        // strip cast if we're initializing a char[] with a char *,
     852                                                        // e.g.  char x[] = "hello";
     853                                                        newExpr = ce->get_arg();
     854                                                        ce->set_arg( nullptr );
     855                                                        std::swap( ce->env, newExpr->env );
     856                                                        delete ce;
     857                                                }
     858                                        }
     859                                }
     860                        }
     861                }
     862
     863                // set initializer expr to resolved express
     864                singleInit->value = newExpr;
     865
     866                // move cursor to next object in preparation for next initializer
     867                currentObject.increment();
     868        }
     869
     870        void Resolver_old::previsit( ListInit * listInit ) {
     871                visit_children = false;
     872                // move cursor into brace-enclosed initializer-list
     873                currentObject.enterListInit();
     874                // xxx - fix this so that the list isn't copied, iterator should be used to change current
     875                // element
     876                std::list<Designation *> newDesignations;
     877                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
     878                        // iterate designations and initializers in pairs, moving the cursor to the current
     879                        // designated object and resolving the initializer against that object.
     880                        Designation * des = std::get<0>(p);
     881                        Initializer * init = std::get<1>(p);
     882                        newDesignations.push_back( currentObject.findNext( des ) );
     883                        init->accept( *visitor );
     884                }
     885                // set the set of 'resolved' designations and leave the brace-enclosed initializer-list
     886                listInit->get_designations() = newDesignations; // xxx - memory management
     887                currentObject.exitListInit();
     888
     889                // xxx - this part has not be folded into CurrentObject yet
     890                // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
     891                //      Type * base = tt->get_baseType()->get_base();
     892                //      if ( base ) {
     893                //              // know the implementation type, so try using that as the initContext
     894                //              ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr );
     895                //              currentObject = &tmpObj;
     896                //              visit( listInit );
     897                //      } else {
     898                //              // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
     899                //              Parent::visit( listInit );
     900                //      }
     901                // } else {
     902        }
     903
     904        // ConstructorInit - fall back on C-style initializer
     905        void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
     906                // could not find valid constructor, or found an intrinsic constructor
     907                // fall back on C-style initializer
     908                delete ctorInit->get_ctor();
     909                ctorInit->set_ctor( nullptr );
     910                delete ctorInit->get_dtor();
     911                ctorInit->set_dtor( nullptr );
     912                maybeAccept( ctorInit->get_init(), *visitor );
     913        }
     914
     915        // needs to be callable from outside the resolver, so this is a standalone function
     916        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
     917                assert( ctorInit );
     918                PassVisitor<Resolver_old> resolver( indexer );
     919                ctorInit->accept( resolver );
     920        }
     921
     922        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
     923                assert( stmtExpr );
     924                PassVisitor<Resolver_old> resolver( indexer );
     925                stmtExpr->accept( resolver );
     926                stmtExpr->computeResult();
     927                // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
     928        }
     929
     930        void Resolver_old::previsit( ConstructorInit * ctorInit ) {
     931                visit_children = false;
     932                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
     933                maybeAccept( ctorInit->ctor, *visitor );
     934                maybeAccept( ctorInit->dtor, *visitor );
     935
     936                // found a constructor - can get rid of C-style initializer
     937                delete ctorInit->init;
     938                ctorInit->init = nullptr;
     939
     940                // intrinsic single parameter constructors and destructors do nothing. Since this was
     941                // implicitly generated, there's no way for it to have side effects, so get rid of it
     942                // to clean up generated code.
     943                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
     944                        delete ctorInit->ctor;
     945                        ctorInit->ctor = nullptr;
     946                }
     947
     948                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
     949                        delete ctorInit->dtor;
     950                        ctorInit->dtor = nullptr;
     951                }
     952
     953                // xxx - todo -- what about arrays?
     954                // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     955                //      // can reduce the constructor down to a SingleInit using the
     956                //      // second argument from the ctor call, since
     957                //      delete ctorInit->get_ctor();
     958                //      ctorInit->set_ctor( nullptr );
     959
     960                //      Expression * arg =
     961                //      ctorInit->set_init( new SingleInit( arg ) );
     962                // }
     963        }
     964
     965        ///////////////////////////////////////////////////////////////////////////
     966        //
     967        // *** NEW RESOLVER ***
     968        //
     969        ///////////////////////////////////////////////////////////////////////////
    61970
    62971        namespace {
Note: See TracChangeset for help on using the changeset viewer.