Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r33a25f9 re3e16bc  
    7070namespace InitTweak {
    7171        namespace {
     72                typedef std::unordered_map< Expression *, TypeSubstitution * > EnvMap;
    7273                typedef std::unordered_map< int, int > UnqCount;
    7374
    74                 struct InsertImplicitCalls : public WithTypeSubstitution {
     75                class InsertImplicitCalls : public WithTypeSubstitution {
     76                public:
    7577                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
    7678                        /// function calls need their parameters to be copy constructed
    77                         static void insert( std::list< Declaration * > & translationUnit );
     79                        static void insert( std::list< Declaration * > & translationUnit, EnvMap & envMap );
     80
     81                        InsertImplicitCalls( EnvMap & envMap ) : envMap( envMap ) {}
    7882
    7983                        Expression * postmutate( ApplicationExpr * appExpr );
     84                        void premutate( StmtExpr * stmtExpr );
     85
     86                        // collects environments for relevant nodes
     87                        EnvMap & envMap;
    8088                };
    8189
    82                 struct ResolveCopyCtors final : public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution {
     90                class ResolveCopyCtors final : public SymTab::Indexer {
     91                public:
    8392                        /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
    8493                        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
    8594                        /// arguments and return value temporaries
    86                         static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount );
    87 
    88                         ResolveCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ) {}
    89 
    90                         void postvisit( ImplicitCopyCtorExpr * impCpCtorExpr );
    91                         void postvisit( StmtExpr * stmtExpr );
    92                         void previsit( UniqueExpr * unqExpr );
    93                         void postvisit( UniqueExpr * unqExpr );
     95                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap, UnqCount & unqCount );
     96
     97                        typedef SymTab::Indexer Parent;
     98                        using Parent::visit;
     99
     100                        ResolveCopyCtors( const EnvMap & envMap, UnqCount & unqCount ) : envMap( envMap ), unqCount( unqCount ) {}
     101
     102                        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
     103                        virtual void visit( UniqueExpr * unqExpr ) override;
     104                        virtual void visit( StmtExpr * stmtExpr ) override;
    94105
    95106                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
     
    100111                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    101112
     113                        TypeSubstitution * env;
     114                        const EnvMap & envMap;
    102115                        UnqCount & unqCount; // count the number of times each unique expr ID appears
    103                         std::unordered_set< int > vars;
    104116                };
    105117
     
    226238                };
    227239
    228                 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer {
     240                class GenStructMemberCalls final : public SymTab::Indexer {
     241                  public:
     242                        typedef Indexer Parent;
    229243                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
    230244                        /// for any member that is missing a corresponding ctor/dtor call.
     
    232246                        static void generate( std::list< Declaration * > & translationUnit );
    233247
    234                         void previsit( FunctionDecl * funcDecl );
    235                         void postvisit( FunctionDecl * funcDecl );
    236 
    237                         void previsit( MemberExpr * memberExpr );
    238                         void previsit( ApplicationExpr * appExpr );
     248                        using Parent::visit;
     249
     250                        virtual void visit( FunctionDecl * funcDecl ) override;
     251
     252                        virtual void visit( MemberExpr * memberExpr ) override;
     253                        virtual void visit( ApplicationExpr * appExpr ) override;
    239254
    240255                        SemanticError errors;
     
    280295                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
    281296
     297                EnvMap envMap;
    282298                UnqCount unqCount;
    283299
    284                 InsertImplicitCalls::insert( translationUnit );
    285                 ResolveCopyCtors::resolveImplicitCalls( translationUnit, unqCount );
     300                InsertImplicitCalls::insert( translationUnit, envMap );
     301                ResolveCopyCtors::resolveImplicitCalls( translationUnit, envMap, unqCount );
    286302                InsertDtors::insert( translationUnit );
    287303                FixInit::fixInitializers( translationUnit );
     
    302318
    303319        namespace {
    304                 void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {
    305                         PassVisitor<InsertImplicitCalls> inserter;
     320                void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit, EnvMap & envMap ) {
     321                        PassVisitor<InsertImplicitCalls> inserter( envMap );
    306322                        mutateAll( translationUnit, inserter );
    307323                }
    308324
    309                 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    310                         PassVisitor<ResolveCopyCtors> resolver( unqCount );
     325                void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap, UnqCount & unqCount ) {
     326                        ResolveCopyCtors resolver( envMap, unqCount );
    311327                        acceptAll( translationUnit, resolver );
    312328                }
     
    344360
    345361                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    346                         PassVisitor<GenStructMemberCalls> warner;
     362                        GenStructMemberCalls warner;
    347363                        acceptAll( translationUnit, warner );
    348364                }
     
    382398                        // wrap each function call so that it is easy to identify nodes that have to be copy constructed
    383399                        ImplicitCopyCtorExpr * expr = new ImplicitCopyCtorExpr( appExpr );
    384                         // Move the type substitution to the new top-level, if it is attached to the appExpr.
     400                        // save the type substitution into the envMap so that it is easy to find.
    385401                        // Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion.
    386402                        // The substitution is needed to obtain the type of temporary variables so that copy constructor
    387                         // calls can be resolved.
     403                        // calls can be resolved. Normally this is what PolyMutator is for, but the pass that resolves
     404                        // copy constructor calls must be an Indexer. We could alternatively make a PolyIndexer which
     405                        // saves the environment, or compute the types of temporaries here, but it's much simpler to
     406                        // save the environment here, and more cohesive to compute temporary variables and resolve copy
     407                        // constructor calls together.
    388408                        assert( env );
    389                         std::swap( expr->env, appExpr->env );
     409                        envMap[expr] = env;
    390410                        return expr;
     411                }
     412
     413                void InsertImplicitCalls::premutate( StmtExpr * stmtExpr ) {
     414                        assert( env );
     415                        envMap[stmtExpr] = env;
    391416                }
    392417
     
    406431                        // (VariableExpr and already resolved expression)
    407432                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    408                         Expression * resolved = ResolvExpr::findVoidExpression( untyped, indexer );
     433                        Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this );
    409434                        assert( resolved );
    410435                        if ( resolved->get_env() ) {
     
    455480                }
    456481
    457                 void ResolveCopyCtors::postvisit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
     482                void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
    458483                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
     484                        Parent::visit( impCpCtorExpr );
     485                        env = envMap.at(impCpCtorExpr);
     486                        assert( env );
    459487
    460488                        ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
     
    485513                }
    486514
    487                 void ResolveCopyCtors::postvisit( StmtExpr * stmtExpr ) {
    488                         assert( env );
     515                void ResolveCopyCtors::visit( StmtExpr * stmtExpr ) {
     516                        Parent::visit( stmtExpr );
     517                        env = envMap.at(stmtExpr);
    489518                        assert( stmtExpr->get_result() );
    490519                        Type * result = stmtExpr->get_result();
     
    508537                                stmtExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
    509538                        } // if
    510                 }
    511 
    512                 void ResolveCopyCtors::previsit( UniqueExpr * unqExpr ) {
     539
     540                }
     541
     542                void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) {
     543                        static std::unordered_set< int > vars;
    513544                        unqCount[ unqExpr->get_id() ]++;  // count the number of unique expressions for each ID
    514545                        if ( vars.count( unqExpr->get_id() ) ) {
    515546                                // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
    516                                 visit_children = false;
    517                         }
    518                 }
    519 
    520                 void ResolveCopyCtors::postvisit( UniqueExpr * unqExpr ) {
    521                         if ( vars.count( unqExpr->get_id() ) ) {
    522                                 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
    523547                                return;
    524548                        }
    525549
     550                        Parent::visit( unqExpr );
    526551                        // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
    527552                        assert( unqExpr->get_result() );
     
    560585
    561586                        // xxx - update to work with multiple return values
    562                         ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
     587                        ObjectDecl * returnDecl = returnDecls.empty() ? NULL : returnDecls.front();
    563588                        Expression * callExpr = impCpCtorExpr->get_callExpr();
    564589
     
    569594                        tempDecls.clear();
    570595                        returnDecls.clear();
    571                         impCpCtorExpr->set_callExpr( nullptr );
    572                         std::swap( impCpCtorExpr->env, callExpr->env );
    573                         assert( impCpCtorExpr->env == nullptr );
     596                        impCpCtorExpr->set_callExpr( NULL );
     597                        impCpCtorExpr->set_env( NULL );
    574598                        delete impCpCtorExpr;
    575599
     
    954978                }
    955979
    956                 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
    957                         GuardValue( funcDecl );
    958                         GuardValue( unhandled );
    959                         GuardValue( usedUninit );
    960                         GuardValue( thisParam );
    961                         GuardValue( isCtor );
    962                         GuardValue( structDecl );
     980                void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) {
     981                        ValueGuard< FunctionDecl * > oldFunction( funcDecl );
     982                        ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled );
     983                        ValueGuard< std::map< DeclarationWithType *, CodeLocation > > oldUsedUninit( usedUninit );
     984                        ValueGuard< ObjectDecl * > oldThisParam( thisParam );
     985                        ValueGuard< bool > oldIsCtor( isCtor );
     986                        ValueGuard< StructDecl * > oldStructDecl( structDecl );
    963987                        errors = SemanticError();  // clear previous errors
    964988
     
    9861010                                }
    9871011                        }
    988                 }
    989 
    990                 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {
    991                         for ( auto d : decls ) {
    992                                 indexer.addId( d );
    993                         }
    994                 }
    995 
    996                 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {
    997                         for ( auto td : tds ) {
    998                                 indexer.addType( td );
    999                                 addIds( indexer, td->assertions );
    1000                         }
    1001                 }
    1002 
    1003                 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {
     1012                        Parent::visit( function );
     1013
    10041014                        // remove the unhandled objects from usedUninit, because a call is inserted
    10051015                        // to handle them - only objects that are later constructed are used uninitialized.
     
    10221032                        if ( ! unhandled.empty() ) {
    10231033                                // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors
    1024                                 auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this]() { indexer.leaveScope(); } );
    1025                                 addTypes( indexer, function->type->forall );
    1026                                 addIds( indexer, function->type->returnVals );
    1027                                 addIds( indexer, function->type->parameters );
     1034                                enterScope();
     1035                                maybeAccept( function->get_functionType(), *this );
    10281036
    10291037                                // need to iterate through members in reverse in order for
     
    10551063                                                Statement * callStmt = stmt.front();
    10561064
    1057                                                 MutatingResolver resolver( indexer );
     1065                                                MutatingResolver resolver( *this );
    10581066                                                try {
    10591067                                                        callStmt->acceptMutator( resolver );
     
    10691077                                        }
    10701078                                }
     1079                                leaveScope();
    10711080                        }
    10721081                        if (! errors.isEmpty()) {
     
    10981107                }
    10991108
    1100                 void GenStructMemberCalls::previsit( ApplicationExpr * appExpr ) {
    1101                         if ( ! checkWarnings( function ) ) {
    1102                                 visit_children = false;
    1103                                 return;
    1104                         }
     1109                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
     1110                        if ( ! checkWarnings( function ) ) return;
    11051111
    11061112                        std::string fname = getFunctionName( appExpr );
     
    11211127                                }
    11221128                        }
    1123                 }
    1124 
    1125                 void GenStructMemberCalls::previsit( MemberExpr * memberExpr ) {
    1126                         if ( ! checkWarnings( function ) || ! isCtor ) {
    1127                                 visit_children = false;
    1128                                 return;
    1129                         }
     1129                        Parent::visit( appExpr );
     1130                }
     1131
     1132                void GenStructMemberCalls::visit( MemberExpr * memberExpr ) {
     1133                        if ( ! checkWarnings( function ) ) return;
     1134                        if ( ! isCtor ) return;
    11301135
    11311136                        if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     
    11351140                                }
    11361141                        }
     1142                        Parent::visit( memberExpr );
    11371143                }
    11381144
     
    11551161                        // in generated code. If this changes, add mutate methods for entities with
    11561162                        // scope and call {enter,leave}Scope explicitly.
    1157                         indexer.addId( objectDecl );
     1163                        objectDecl->accept( indexer );
    11581164                        return objectDecl;
    11591165                }
Note: See TracChangeset for help on using the changeset viewer.