Ignore:
Timestamp:
Nov 8, 2023, 2:01:11 PM (12 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
3e4bf0d, f5ec35a
Parents:
790d835
Message:

Remove BaseSyntaxNode? and clean-up.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r790d835 rc6b4432  
    1919#include <vector>                        // for vector
    2020
    21 #include "Alternative.h"                 // for Alternative, AltList
    22 #include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
    2321#include "Candidate.hpp"
    2422#include "CandidateFinder.hpp"
     
    4038#include "Common/Eval.h"                 // for eval
    4139#include "Common/Iterate.hpp"            // for group_iterate
    42 #include "Common/PassVisitor.h"          // for PassVisitor
    4340#include "Common/SemanticError.h"        // for SemanticError
    4441#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    4542#include "Common/ToString.hpp"           // for toCString
     43#include "Common/UniqueName.h"           // for UniqueName
    4644#include "InitTweak/GenInit.h"
    4745#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
    5146#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
    5947#include "Tuples/Tuples.h"
    6048#include "Validate/FindSpecialDecls.h"   // for SizeType
     
    6351
    6452namespace 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 
    60453        template< typename iterator_t >
    60554        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
     
    61059                return it != end;
    61160        }
    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         ///////////////////////////////////////////////////////////////////////////
    97061
    97162        namespace {
Note: See TracChangeset for help on using the changeset viewer.