Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    rba3706f rb3fc977  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FixInit.h --
     7// FixInit.cc --
    88//
    99// Author           : Rob Schluntz
     
    197197                };
    198198
    199                 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer {
     199                struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> {
    200200                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
    201201                        /// for any member that is missing a corresponding ctor/dtor call.
     
    203203                        static void generate( std::list< Declaration * > & translationUnit );
    204204
    205                         void previsit( FunctionDecl * funcDecl );
    206                         void postvisit( FunctionDecl * funcDecl );
    207 
    208                         void previsit( MemberExpr * memberExpr );
    209                         void previsit( ApplicationExpr * appExpr );
     205                        void premutate( FunctionDecl * funcDecl );
     206                        DeclarationWithType * postmutate( FunctionDecl * funcDecl );
     207
     208                        void premutate( MemberExpr * memberExpr );
     209                        void premutate( ApplicationExpr * appExpr );
     210
     211                        /// Note: this post mutate used to be in a separate visitor. If this pass breaks, one place to examine is whether it is
     212                        /// okay for this part of the recursion to occur alongside the rest.
     213                        Expression * postmutate( UntypedExpr * expr );
    210214
    211215                        SemanticError errors;
     
    220224                        bool isCtor = false; // true if current function is a constructor
    221225                        StructDecl * structDecl = nullptr;
    222                 };
    223 
    224                 // very simple resolver-like mutator class - used to
    225                 // resolve UntypedExprs that are found within newly
    226                 // generated constructor/destructor calls
    227                 class MutatingResolver final : public Mutator {
    228                   public:
    229                         MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
    230 
    231                         using Mutator::mutate;
    232                         virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override;
    233                         virtual Expression* mutate( UntypedExpr *untypedExpr ) override;
    234 
    235                   private:
    236                         SymTab::Indexer & indexer;
    237226                };
    238227
     
    315304                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    316305                        PassVisitor<GenStructMemberCalls> warner;
    317                         acceptAll( translationUnit, warner );
     306                        mutateAll( translationUnit, warner );
    318307                }
    319308
     
    365354                        // arrays are not copy constructed, so this should always be an ExprStmt
    366355                        ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg );
    367                         ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() );
     356                        assertf( stmt, "ResolveCopyCtors: genCtorDtor returned nullptr: %s / %s / %s", fname.c_str(), toString( var ).c_str(), toString( cpArg ).c_str() );
     357                        ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->callStmt );
    368358                        Expression * resolved = exprStmt->expr;
    369359                        exprStmt->expr = nullptr; // take ownership of expr
     
    382372                        } // if
    383373                        delete stmt;
     374                        if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) {
     375                                // fix newly generated StmtExpr
     376                                postvisit( assign->stmtExpr );
     377                        }
    384378                        return resolved;
    385379                }
     
    475469                                static UniqueName retNamer("_tmp_stmtexpr_ret");
    476470
    477                                 // create variable that will hold the result of the stmt expr
    478471                                result = result->clone();
    479472                                env->apply( result );
     473                                if ( ! InitTweak::isConstructable( result ) ) {
     474                                        delete result;
     475                                        return;
     476                                }
     477
     478                                // create variable that will hold the result of the stmt expr
    480479                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    481                                 ret->get_type()->set_const( false );
    482                                 stmtExpr->get_returnDecls().push_front( ret );
     480                                ret->type->set_const( false );
     481                                stmtExpr->returnDecls.push_front( ret );
    483482
    484483                                // must have a non-empty body, otherwise it wouldn't have a result
    485                                 CompoundStmt * body = stmtExpr->get_statements();
     484                                CompoundStmt * body = stmtExpr->statements;
    486485                                assert( ! body->get_kids().empty() );
    487486                                // must be an ExprStmt, otherwise it wouldn't have a result
    488487                                ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->get_kids().back() );
    489                                 last->set_expr( makeCtorDtor( "?{}", ret, last->get_expr() ) );
    490 
    491                                 stmtExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
     488                                last->expr = makeCtorDtor( "?{}", ret, last->get_expr() );
     489
     490                                stmtExpr->dtors.push_front( makeCtorDtor( "^?{}", ret ) );
    492491                        } // if
    493492                }
     
    590589                        // to the outer context, rather than inside of the statement expression.
    591590                        visit_children = false;
    592                         std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
     591                        std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
    593592                        for ( Statement *& stmt : stmts ) {
    594593                                stmt = stmt->acceptMutator( *visitor );
    595594                        } // for
    596                         assert( stmtExpr->get_result() );
    597                         Type * result = stmtExpr->get_result();
     595                        assert( stmtExpr->result );
     596                        Type * result = stmtExpr->result;
    598597                        if ( ! result->isVoid() ) {
    599                                 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
     598                                for ( ObjectDecl * obj : stmtExpr->returnDecls ) {
    600599                                        stmtsToAddBefore.push_back( new DeclStmt( obj ) );
    601600                                } // for
    602601                                // add destructors after current statement
    603                                 for ( Expression * dtor : stmtExpr->get_dtors() ) {
     602                                for ( Expression * dtor : stmtExpr->dtors ) {
    604603                                        stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    605604                                } // for
    606605                                // must have a non-empty body, otherwise it wouldn't have a result
    607606                                assert( ! stmts.empty() );
    608                                 assert( ! stmtExpr->get_returnDecls().empty() );
    609                                 stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    610                                 stmtExpr->get_returnDecls().clear();
    611                                 stmtExpr->get_dtors().clear();
    612                         }
    613                         assert( stmtExpr->get_returnDecls().empty() );
    614                         assert( stmtExpr->get_dtors().empty() );
     607                                assertf( ! stmtExpr->returnDecls.empty() || stmtExpr->dtors.empty(), "StmtExpr returns non-void, but no return decls: %s", toString( stmtExpr ).c_str() );
     608                                // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
     609                                if ( ! stmtExpr->returnDecls.empty() ) {
     610                                        stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->returnDecls.front() ) ) );
     611                                }
     612                                stmtExpr->returnDecls.clear();
     613                                stmtExpr->dtors.clear();
     614                        }
     615                        assert( stmtExpr->returnDecls.empty() );
     616                        assert( stmtExpr->dtors.empty() );
    615617                }
    616618
     
    937939                }
    938940
    939                 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
     941                void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) {
    940942                        GuardValue( function );
    941943                        GuardValue( unhandled );
     
    971973                }
    972974
    973                 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {
     975                DeclarationWithType * GenStructMemberCalls::postmutate( FunctionDecl * funcDecl ) {
    974976                        // remove the unhandled objects from usedUninit, because a call is inserted
    975977                        // to handle them - only objects that are later constructed are used uninitialized.
     
    10251027                                                Statement * callStmt = stmt.front();
    10261028
    1027                                                 MutatingResolver resolver( indexer );
    10281029                                                try {
    1029                                                         callStmt->acceptMutator( resolver );
     1030                                                        callStmt->acceptMutator( *visitor );
    10301031                                                        if ( isCtor ) {
    10311032                                                                function->get_statements()->push_front( callStmt );
     
    10431044                                throw errors;
    10441045                        }
     1046                        return funcDecl;
    10451047                }
    10461048
     
    10681070                }
    10691071
    1070                 void GenStructMemberCalls::previsit( ApplicationExpr * appExpr ) {
     1072                void GenStructMemberCalls::premutate( ApplicationExpr * appExpr ) {
    10711073                        if ( ! checkWarnings( function ) ) {
    10721074                                visit_children = false;
     
    10931095                }
    10941096
    1095                 void GenStructMemberCalls::previsit( MemberExpr * memberExpr ) {
     1097                void GenStructMemberCalls::premutate( MemberExpr * memberExpr ) {
    10961098                        if ( ! checkWarnings( function ) || ! isCtor ) {
    10971099                                visit_children = false;
     
    11211123                }
    11221124
    1123                 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {
    1124                         // add object to the indexer assumes that there will be no name collisions
    1125                         // in generated code. If this changes, add mutate methods for entities with
    1126                         // scope and call {enter,leave}Scope explicitly.
    1127                         indexer.addId( objectDecl );
    1128                         return objectDecl;
    1129                 }
    1130 
    1131                 Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) {
     1125                Expression * GenStructMemberCalls::postmutate( UntypedExpr * untypedExpr ) {
    11321126                        Expression * newExpr = untypedExpr;
    11331127                        ResolvExpr::findVoidExpression( newExpr, indexer );
Note: See TracChangeset for help on using the changeset viewer.