Changeset 2a6292d


Ignore:
Timestamp:
Aug 21, 2018, 3:59:45 PM (6 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
Children:
305581d
Parents:
cdbab55
Message:

Resolve with expressions earlier to ensure new local variables are present before other user-code is resolved

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    rcdbab55 r2a6292d  
    7575                void previsit( CatchStmt *catchStmt );
    7676                void previsit( WaitForStmt * stmt );
    77                 void previsit( WithStmt * withStmt );
    7877
    7978                void previsit( SingleInit *singleInit );
     
    8685                void handlePtrType( PtrType * type );
    8786
    88                 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    8987                void fallbackInit( ConstructorInit * ctorInit );
    9088
     
    9290                CurrentObject currentObject = nullptr;
    9391                bool inEnumDecl = false;
     92        };
     93
     94        struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
     95                void previsit( FunctionDecl * );
     96                void previsit( WithStmt * );
     97
     98                void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    9499        };
    95100
     
    300305        }
    301306
     307
     308        bool isStructOrUnion( const Alternative & alt ) {
     309                Type * t = alt.expr->result->stripReferences();
     310                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     311        }
     312
     313        void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
     314                PassVisitor<ResolveWithExprs> resolver;
     315                acceptAll( translationUnit, resolver );
     316        }
     317
     318        void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
     319                for ( Expression *& expr : withExprs )  {
     320                        // only struct- and union-typed expressions are viable candidates
     321                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
     322
     323                        // if with expression might be impure, create a temporary so that it is evaluated once
     324                        if ( Tuples::maybeImpure( expr ) ) {
     325                                static UniqueName tmpNamer( "_with_tmp_" );
     326                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
     327                                expr = new VariableExpr( tmp );
     328                                newStmts.push_back( new DeclStmt( tmp ) );
     329                                if ( InitTweak::isConstructable( tmp->type ) ) {
     330                                        // generate ctor/dtor and resolve them
     331                                        tmp->init = InitTweak::genCtorInit( tmp );
     332                                        tmp->accept( *visitor );
     333                                }
     334                        }
     335                }
     336        }
     337
     338        void ResolveWithExprs::previsit( WithStmt * withStmt ) {
     339                resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
     340        }
     341
     342        void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
     343                {
     344                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
     345                        // front of the function body.
     346                        auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
     347                        indexer.addFunctionType( functionDecl->type );
     348                        std::list< Statement * > newStmts;
     349                        resolveWithExprs( functionDecl->withExprs, newStmts );
     350                        if ( functionDecl->statements ) {
     351                                functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
     352                        } else {
     353                                assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
     354                        }
     355                }
     356        }
     357
    302358        void Resolver::previsit( ObjectDecl *objectDecl ) {
    303359                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
     
    338394                GuardValue( functionReturn );
    339395                functionReturn = ResolvExpr::extractResultType( functionDecl->type );
    340 
    341                 {
    342                         // resolve with-exprs with parameters in scope and add any newly generated declarations to the
    343                         // front of the function body.
    344                         auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
    345                         indexer.addFunctionType( functionDecl->type );
    346                         std::list< Statement * > newStmts;
    347                         resolveWithExprs( functionDecl->withExprs, newStmts );
    348                         if ( functionDecl->statements ) {
    349                                 functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
    350                         } else {
    351                                 assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
    352                         }
    353                 }
    354396        }
    355397
     
    682724                        stmt->orelse.statement->accept( *visitor );
    683725                }
    684         }
    685 
    686         bool isStructOrUnion( const Alternative & alt ) {
    687                 Type * t = alt.expr->result->stripReferences();
    688                 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    689         }
    690 
    691         void Resolver::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
    692                 for ( Expression *& expr : withExprs )  {
    693                         // only struct- and union-typed expressions are viable candidates
    694                         findKindExpression( expr, indexer, "with statement", isStructOrUnion );
    695 
    696                         // if with expression might be impure, create a temporary so that it is evaluated once
    697                         if ( Tuples::maybeImpure( expr ) ) {
    698                                 static UniqueName tmpNamer( "_with_tmp_" );
    699                                 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
    700                                 expr = new VariableExpr( tmp );
    701                                 newStmts.push_back( new DeclStmt( tmp ) );
    702                                 if ( InitTweak::isConstructable( tmp->type ) ) {
    703                                         // generate ctor/dtor and resolve them
    704                                         tmp->init = InitTweak::genCtorInit( tmp );
    705                                         tmp->accept( *visitor );
    706                                 }
    707                         }
    708                 }
    709         }
    710 
    711         void Resolver::previsit( WithStmt * withStmt ) {
    712                 resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
    713726        }
    714727
  • src/ResolvExpr/Resolver.h

    rcdbab55 r2a6292d  
    3838        /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    3939        DeletedExpr * findDeletedExpr( Expression * expr );
     40        /// Resolves with-stmts and with-clauses on functions
     41        void resolveWithExprs( std::list< Declaration * > & translationUnit );
    4042} // namespace ResolvExpr
    4143
  • src/SymTab/Validate.cc

    rcdbab55 r2a6292d  
    322322                Concurrency::implementThreadStarter( translationUnit );
    323323                mutateAll( translationUnit, compoundliteral );
     324                ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables
    324325                FixObjectType::fix( translationUnit );
    325326                ArrayLength::computeLength( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.