Changeset 2f86ddf


Ignore:
Timestamp:
Sep 6, 2018, 10:51:37 AM (3 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
arm-eh, cleanup-dtors, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
9b086ca
Parents:
ec42ff2e
Message:

Add Destructor handlers for argument and return temporaries, merge and simplify ResolveCopyCtors/FixCopyCtors? passes, simplify ImplicitCopyCtorExpr?

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/Common/PassVisitor.impl.h

    rec42ff2e r2f86ddf  
    17781778        VISIT_START( node );
    17791779
    1780         indexerScopedAccept( node->result     , *this );
    1781         maybeAccept_impl   ( node->callExpr   , *this );
    1782         maybeAccept_impl   ( node->tempDecls  , *this );
    1783         maybeAccept_impl   ( node->returnDecls, *this );
    1784         maybeAccept_impl   ( node->dtors      , *this );
     1780        indexerScopedAccept( node->result    , *this );
     1781        maybeAccept_impl   ( node->callExpr  , *this );
    17851782
    17861783        VISIT_END( node );
     
    17911788        MUTATE_START( node );
    17921789
    1793         indexerScopedMutate( node->env        , *this );
    1794         indexerScopedMutate( node->result     , *this );
    1795         maybeMutate_impl   ( node->callExpr   , *this );
    1796         maybeMutate_impl   ( node->tempDecls  , *this );
    1797         maybeMutate_impl   ( node->returnDecls, *this );
    1798         maybeMutate_impl   ( node->dtors      , *this );
     1790        indexerScopedMutate( node->env       , *this );
     1791        indexerScopedMutate( node->result    , *this );
     1792        maybeMutate_impl   ( node->callExpr  , *this );
    17991793
    18001794        MUTATE_END( Expression, node );
  • src/InitTweak/FixInit.cc

    rec42ff2e r2f86ddf  
    6868namespace InitTweak {
    6969        namespace {
    70                 typedef std::unordered_map< int, int > UnqCount;
    71 
    7270                struct SelfAssignChecker {
    7371                        void previsit( ApplicationExpr * appExpr );
     
    8280                };
    8381
    84                 struct ResolveCopyCtors final : public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution {
     82                struct ResolveCopyCtors final : public WithStmtsToAdd, public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution, public WithVisitorRef<ResolveCopyCtors> {
    8583                        /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
    8684                        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
    8785                        /// arguments and return value temporaries
    88                         static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount );
    89 
    90                         ResolveCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ) {}
    91 
    92                         void postvisit( ImplicitCopyCtorExpr * impCpCtorExpr );
    93                         void postvisit( StmtExpr * stmtExpr );
    94                         void previsit( UniqueExpr * unqExpr );
    95                         void postvisit( UniqueExpr * unqExpr );
     86                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
     87
     88                        Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     89                        void premutate( StmtExpr * stmtExpr );
     90                        void premutate( UniqueExpr * unqExpr );
    9691
    9792                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
     
    10095                        bool skipCopyConstruct( Type * type );
    10196                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
    102                         void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    103 
    104                         UnqCount & unqCount; // count the number of times each unique expr ID appears
    105                         std::unordered_set< int > vars;
     97                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr, Expression *& arg );
    10698                };
    10799
     
    185177                };
    186178
    187                 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution {
    188                   public:
    189                         FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
    190                         /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression,
    191                         /// and destructors
    192                         static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
    193 
    194                         Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
    195                         void premutate( StmtExpr * stmtExpr );
    196                         void premutate( UniqueExpr * unqExpr );
    197 
    198                         UnqCount & unqCount;
    199                 };
    200 
    201179                struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> {
    202180                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
     
    251229                InitTweak::fixGlobalInit( translationUnit, inLibrary );
    252230
    253                 UnqCount unqCount;
    254 
    255231                // must happen before ResolveCopyCtors because temporaries have to be inserted into the correct scope
    256232                SplitExpressions::split( translationUnit );
    257233
    258234                InsertImplicitCalls::insert( translationUnit );
    259                 ResolveCopyCtors::resolveImplicitCalls( translationUnit, unqCount );
     235
     236                // Needs to happen before ResolveCopyCtors, because argument/return temporaries should not be considered in
     237                // error checking branch statements
    260238                InsertDtors::insert( translationUnit );
     239
     240                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
    261241                FixInit::fixInitializers( translationUnit );
    262 
    263                 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly
    264                 FixCopyCtors::fixCopyCtors( translationUnit, unqCount );
    265 
    266242                GenStructMemberCalls::generate( translationUnit );
    267243
     
    335311                }
    336312
    337                 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    338                         PassVisitor<ResolveCopyCtors> resolver( unqCount );
    339                         acceptAll( translationUnit, resolver );
     313                void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) {
     314                        PassVisitor<ResolveCopyCtors> resolver;
     315                        mutateAll( translationUnit, resolver );
    340316                }
    341317
     
    363339                        PassVisitor<InsertDtors> inserter( finder );
    364340                        acceptAll( translationUnit, inserter );
    365                 }
    366 
    367                 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    368                         PassVisitor<FixCopyCtors> fixer( unqCount );
    369                         mutateAll( translationUnit, fixer );
    370341                }
    371342
     
    529500                        if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) {
    530501                                // fix newly generated StmtExpr
    531                                 postvisit( assign->stmtExpr );
     502                                premutate( assign->stmtExpr );
    532503                        }
    533504                        return resolved;
     
    569540
    570541                        // replace argument to function call with temporary
    571                         arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
    572                         impCpCtorExpr->tempDecls.push_back( tmp );
    573                         impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
    574                 }
    575 
    576                 void ResolveCopyCtors::destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) {
    577                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
    578                 }
    579 
    580                 void ResolveCopyCtors::postvisit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
     542                        stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
     543                        arg = cpCtor;
     544                        destructRet( tmp, impCpCtorExpr, arg );
     545
     546                        // impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
     547                }
     548
     549                void ResolveCopyCtors::destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr, Expression *& arg ) {
     550                        // TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places
     551                        // check for existing cleanup attribute before adding another(?)
     552                        // need to add __Destructor for _tmp_cp variables as well
     553
     554                        assertf( Validate::dtorStruct && Validate::dtorStruct->members.size() == 2, "Destructor generation requires __Destructor definition." );
     555                        assertf( Validate::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );
     556
     557                        // generate a __Destructor for ret that calls the destructor
     558                        Expression * dtor = makeCtorDtor( "^?{}", ret );
     559
     560                        // // xxx - check if intrinsic and elide if so
     561                        // if ( arg && isIntrinsicCallExpr( dtor ) ) {
     562                        //      arg = new CommaExpr( arg, new VariableExpr( ret ) );
     563                        //      return;
     564                        // }
     565
     566                        if ( ! dtor->env ) dtor->env = maybeClone( env );
     567                        DeclarationWithType * dtorFunc = getDtorFunc( ret, new ExprStmt( dtor ), stmtsToAddBefore );
     568
     569                        StructInstType * dtorStructType = new StructInstType( Type::Qualifiers(), Validate::dtorStruct );
     570                        dtorStructType->parameters.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     571
     572                        // cast destructor pointer to void (*)(void *), to silence GCC incompatible pointer warnings
     573                        FunctionType * dtorFtype = new FunctionType( Type::Qualifiers(), false );
     574                        dtorFtype->parameters.push_back( ObjectDecl::newObject( "", new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), nullptr ) );
     575                        Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
     576
     577                        static UniqueName namer( "_ret_dtor" );
     578                        ObjectDecl * retDtor = ObjectDecl::newObject( namer.newName(), dtorStructType, new ListInit( { new SingleInit( new ConstantExpr( Constant::null() ) ), new SingleInit( new CastExpr( new VariableExpr( dtorFunc ), dtorType ) ) } ) );
     579                        retDtor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( Validate::dtorStructDestroy ) } ) );
     580                        stmtsToAddBefore.push_back( new DeclStmt( retDtor ) );
     581
     582                        if ( arg ) {
     583                                Expression * member = new MemberExpr( strict_dynamic_cast<DeclarationWithType *>( Validate::dtorStruct->members.front() ), new VariableExpr( retDtor ) );
     584                                Expression * object = new CastExpr( new AddressExpr( new VariableExpr( ret ) ), new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ) );
     585                                Expression * assign = createBitwiseAssignment( member, object );
     586                                arg = new CommaExpr( new CommaExpr( arg, assign ), new VariableExpr( ret ) );
     587                        }
     588
     589                        // impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
     590                }
     591
     592                Expression * ResolveCopyCtors::postmutate( ImplicitCopyCtorExpr *impCpCtorExpr ) {
    581593                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    582594
    583595                        ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
     596                        ObjectDecl * returnDecl = nullptr;
    584597
    585598                        // take each argument and attempt to copy construct it.
     
    590603                        for ( Expression * & arg : appExpr->args ) {
    591604                                Type * formal = nullptr;
    592                                 if ( iter != params.end() ) {
     605                                if ( iter != params.end() ) { // does not copy construct C-style variadic arguments
    593606                                        DeclarationWithType * param = *iter++;
    594607                                        formal = param->get_type();
     
    608621                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    609622                                ret->type->set_const( false );
    610                                 impCpCtorExpr->returnDecls.push_back( ret );
     623                                returnDecl = ret;
     624                                stmtsToAddBefore.push_back( new DeclStmt( ret ) );
    611625                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
     626                        } // for
     627                        CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
     628                        // ------------------------------------------------------
     629
     630                        CP_CTOR_PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; )
     631
     632                        // detach fields from wrapper node so that it can be deleted without deleting too much
     633                        impCpCtorExpr->callExpr = nullptr;
     634                        std::swap( impCpCtorExpr->env, appExpr->env );
     635                        assert( impCpCtorExpr->env == nullptr );
     636                        delete impCpCtorExpr;
     637
     638                        if ( returnDecl ) {
     639                                Expression * assign = createBitwiseAssignment( new VariableExpr( returnDecl ), appExpr );
    612640                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    613641                                        // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    614                                         destructRet( ret, impCpCtorExpr );
    615                                 }
     642                                        destructRet( returnDecl, impCpCtorExpr, assign );
     643                                } else {
     644                                        assign = new CommaExpr( assign, new VariableExpr( returnDecl ) );
     645                                }
     646                                // move env from appExpr to retExpr
     647                                std::swap( assign->env, appExpr->env );
     648                                return assign;
     649                        } else {
     650                                return appExpr;
     651                        } // if
     652                }
     653
     654                void ResolveCopyCtors::premutate( StmtExpr * stmtExpr ) {
     655                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
     656                        // since temporaries can be shared across sub-expressions, e.g.
     657                        //   [A, A] f();
     658                        //   g([A] x, [A] y);
     659                        //   g(f());
     660                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
     661                        // Explicitly mutating children instead of mutating the inner compound statement forces the temporaries to be added
     662                        // to the outer context, rather than inside of the statement expression.
     663                        visit_children = false;
     664
     665                        assert( env );
     666
     667                        // visit all statements
     668                        std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
     669                        for ( Statement *& stmt : stmts ) {
     670                                stmt = stmt->acceptMutator( *visitor );
    616671                        } // for
    617                         CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
    618                 }
    619 
    620                 void ResolveCopyCtors::postvisit( StmtExpr * stmtExpr ) {
    621                         assert( env );
    622                         assert( stmtExpr->get_result() );
    623                         Type * result = stmtExpr->get_result();
     672
     673                        assert( stmtExpr->result );
     674                        Type * result = stmtExpr->result;
    624675                        if ( ! result->isVoid() ) {
    625676                                static UniqueName retNamer("_tmp_stmtexpr_ret");
     
    635686                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    636687                                ret->type->set_const( false );
    637                                 stmtExpr->returnDecls.push_front( ret );
     688                                stmtsToAddBefore.push_back( new DeclStmt( ret ) );
    638689
    639690                                // must have a non-empty body, otherwise it wouldn't have a result
    640691                                CompoundStmt * body = stmtExpr->statements;
    641                                 assert( ! body->get_kids().empty() );
     692                                assert( ! body->kids.empty() );
    642693                                // must be an ExprStmt, otherwise it wouldn't have a result
    643                                 ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->get_kids().back() );
    644                                 last->expr = makeCtorDtor( "?{}", ret, last->get_expr() );
    645 
    646                                 stmtExpr->dtors.push_front( makeCtorDtor( "^?{}", ret ) );
     694                                ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->kids.back() );
     695                                last->expr = makeCtorDtor( "?{}", ret, last->expr );
     696
     697                                // add destructors after current statement
     698                                stmtsToAddAfter.push_back( new ExprStmt( makeCtorDtor( "^?{}", ret ) ) );
     699
     700                                // must have a non-empty body, otherwise it wouldn't have a result
     701                                assert( ! stmts.empty() );
     702
     703                                // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
     704                                stmts.push_back( new ExprStmt( new VariableExpr( ret ) ) );
    647705                        } // if
    648                 }
    649 
    650                 void ResolveCopyCtors::previsit( UniqueExpr * unqExpr ) {
    651                         unqCount[ unqExpr->get_id() ]++;  // count the number of unique expressions for each ID
    652                         if ( vars.count( unqExpr->get_id() ) ) {
    653                                 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
    654                                 visit_children = false;
    655                         }
     706
     707                        assert( stmtExpr->returnDecls.empty() );
     708                        assert( stmtExpr->dtors.empty() );
    656709                }
    657710
     
    670723                }
    671724
    672                 void ResolveCopyCtors::postvisit( UniqueExpr * unqExpr ) {
    673                         if ( vars.count( unqExpr->get_id() ) ) {
    674                                 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
    675                                 return;
    676                         }
    677 
    678                         // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
    679                         assert( unqExpr->result );
    680                         if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->expr ) ) {
    681                                 // note the variable used as the result from the call
    682                                 assert( impCpCtorExpr->result && impCpCtorExpr->returnDecls.size() == 1 );
    683                                 unqExpr->set_var( new VariableExpr( impCpCtorExpr->returnDecls.front() ) );
     725                void ResolveCopyCtors::premutate( UniqueExpr * unqExpr ) {
     726                        visit_children = false;
     727                        // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
     728                        static std::unordered_map< int, UniqueExpr * > unqMap;
     729                        if ( ! unqMap.count( unqExpr->get_id() ) ) {
     730                                // resolve expr and find its
     731
     732                                ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( unqExpr->expr );
     733                                // PassVisitor<ResolveCopyCtors> fixer;
     734                                unqExpr->expr = unqExpr->expr->acceptMutator( *visitor );
     735
     736                                // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
     737                                assert( unqExpr->result );
     738                                if ( impCpCtorExpr ) {
     739                                        CommaExpr * comma = strict_dynamic_cast< CommaExpr * >( unqExpr->expr );
     740                                        VariableExpr * var = strict_dynamic_cast<VariableExpr *>( comma->arg2 );
     741                                        // note the variable used as the result from the call
     742                                        unqExpr->var = var->clone();
     743                                } else {
     744                                        // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
     745                                        unqExpr->object = ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->result->clone(), makeInit( unqExpr->result ) );
     746                                        unqExpr->var = new VariableExpr( unqExpr->object );
     747                                }
     748
     749                                // stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
     750                                // stmtsToAddAfter.splice( stmtsToAddAfter.end(), fixer.pass.stmtsToAddAfter );
     751                                unqMap[unqExpr->get_id()] = unqExpr;
    684752                        } else {
    685                                 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    686                                 unqExpr->object = ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->result->clone(), makeInit( unqExpr->result ) );
    687                                 unqExpr->var = new VariableExpr( unqExpr->object );
    688                         }
    689                         vars.insert( unqExpr->get_id() );
    690                 }
    691 
    692                 Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    693                         CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    694 
    695                         std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->tempDecls;
    696                         std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->returnDecls;
    697                         std::list< Expression * > & dtors = impCpCtorExpr->dtors;
    698 
    699                         // add all temporary declarations and their constructors
    700                         for ( ObjectDecl * obj : tempDecls ) {
    701                                 stmtsToAddBefore.push_back( new DeclStmt( obj ) );
    702                         } // for
    703                         for ( ObjectDecl * obj : returnDecls ) {
    704                                 stmtsToAddBefore.push_back( new DeclStmt( obj ) );
    705                         } // for
    706 
    707                         // add destructors after current statement
    708                         for ( Expression * dtor : dtors ) {
    709                                 // take relevant bindings from environment
    710                                 assert( ! dtor->env );
    711                                 dtor->env =  maybeClone( env );
    712                                 stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    713                         } // for
    714 
    715                         ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
    716                         Expression * callExpr = impCpCtorExpr->get_callExpr();
    717 
    718                         CP_CTOR_PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; )
    719 
    720                         // detach fields from wrapper node so that it can be deleted without deleting too much
    721                         dtors.clear();
    722                         tempDecls.clear();
    723                         returnDecls.clear();
    724                         impCpCtorExpr->callExpr = nullptr;
    725                         std::swap( impCpCtorExpr->env, callExpr->env );
    726                         assert( impCpCtorExpr->env == nullptr );
    727                         delete impCpCtorExpr;
    728 
    729                         if ( returnDecl ) {
    730                                 ApplicationExpr * assign = createBitwiseAssignment( new VariableExpr( returnDecl ), callExpr );
    731                                 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    732                                 // move env from callExpr to retExpr
    733                                 std::swap( retExpr->env, callExpr->env );
    734                                 return retExpr;
    735                         } else {
    736                                 return callExpr;
    737                         } // if
    738                 }
    739 
    740                 void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
    741                         // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    742                         // since temporaries can be shared across sub-expressions, e.g.
    743                         //   [A, A] f();
    744                         //   g([A] x, [A] y);
    745                         //   g(f());
    746                         // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
    747                         // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
    748                         // to the outer context, rather than inside of the statement expression.
    749                         visit_children = false;
    750                         std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
    751                         for ( Statement *& stmt : stmts ) {
    752                                 stmt = stmt->acceptMutator( *visitor );
    753                         } // for
    754                         assert( stmtExpr->result );
    755                         Type * result = stmtExpr->result;
    756                         if ( ! result->isVoid() ) {
    757                                 for ( ObjectDecl * obj : stmtExpr->returnDecls ) {
    758                                         stmtsToAddBefore.push_back( new DeclStmt( obj ) );
    759                                 } // for
    760                                 // add destructors after current statement
    761                                 for ( Expression * dtor : stmtExpr->dtors ) {
    762                                         stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    763                                 } // for
    764                                 // must have a non-empty body, otherwise it wouldn't have a result
    765                                 assert( ! stmts.empty() );
    766                                 assertf( ! stmtExpr->returnDecls.empty() || stmtExpr->dtors.empty(), "StmtExpr returns non-void, but no return decls: %s", toString( stmtExpr ).c_str() );
    767                                 // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
    768                                 if ( ! stmtExpr->returnDecls.empty() ) {
    769                                         stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->returnDecls.front() ) ) );
    770                                 }
    771                                 stmtExpr->returnDecls.clear();
    772                                 stmtExpr->dtors.clear();
    773                         }
    774                         assert( stmtExpr->returnDecls.empty() );
    775                         assert( stmtExpr->dtors.empty() );
    776                 }
    777 
    778                 void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
    779                         visit_children = false;
    780                         unqCount[ unqExpr->get_id() ]--;
    781                         static std::unordered_map< int, std::list< Statement * > > dtors;
    782                         static std::unordered_map< int, UniqueExpr * > unqMap;
    783                         // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    784                         if ( unqMap.count( unqExpr->get_id() ) ) {
    785753                                // take data from other UniqueExpr to ensure consistency
    786754                                delete unqExpr->get_expr();
    787                                 unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() );
    788                                 delete unqExpr->get_result();
    789                                 unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) );
    790                                 if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    791                                         stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    792                                 }
    793                                 return;
    794                         }
    795                         PassVisitor<FixCopyCtors> fixer( unqCount );
    796                         unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
    797                         stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
    798                         unqMap[unqExpr->get_id()] = unqExpr;
    799                         if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    800                                 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    801                         } else { // remember dtors for last instance of unique expr
    802                                 dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
    803                         }
    804                         return;
     755                                unqExpr->expr = unqMap[unqExpr->get_id()]->expr->clone();
     756                                delete unqExpr->result;
     757                                unqExpr->result = maybeClone( unqExpr->expr->result );
     758                        }
    805759                }
    806760
  • src/SynTree/Expression.cc

    rec42ff2e r2f86ddf  
    538538        assert( callExpr );
    539539        assert( callExpr->result );
    540         set_result( callExpr->get_result()->clone() );
     540        set_result( callExpr->result->clone() );
    541541}
    542542
    543543ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other ) : Expression( other ), callExpr( maybeClone( other.callExpr ) ) {
    544         cloneAll( other.tempDecls, tempDecls );
    545         cloneAll( other.returnDecls, returnDecls );
    546         cloneAll( other.dtors, dtors );
    547544}
    548545
     
    550547        set_env( nullptr ); // ImplicitCopyCtorExpr does not take ownership of an environment
    551548        delete callExpr;
    552         deleteAll( tempDecls );
    553         deleteAll( returnDecls );
    554         deleteAll( dtors );
    555549}
    556550
     
    558552        os <<  "Implicit Copy Constructor Expression: " << std::endl << indent+1;
    559553        callExpr->print( os, indent+1 );
    560         os << std::endl << indent << "... with temporaries:" << std::endl;
    561         printAll( tempDecls, os, indent+1 );
    562         os << std::endl << indent << "... with return temporaries:" << std::endl;
    563         printAll( returnDecls, os, indent+1 );
    564         Expression::print( os, indent );
    565554}
    566555
  • src/SynTree/Expression.h

    rec42ff2e r2f86ddf  
    591591class ImplicitCopyCtorExpr : public Expression {
    592592public:
    593         ApplicationExpr * callExpr;
    594         std::list< ObjectDecl * > tempDecls;
    595         std::list< ObjectDecl * > returnDecls;
    596         std::list< Expression * > dtors;
     593        ApplicationExpr * callExpr = nullptr;
    597594
    598595        ImplicitCopyCtorExpr( ApplicationExpr * callExpr );
    599596        ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other );
    600597        virtual ~ImplicitCopyCtorExpr();
    601 
    602         ApplicationExpr * get_callExpr() const { return callExpr; }
    603         void set_callExpr( ApplicationExpr * newValue ) { callExpr = newValue; }
    604 
    605         std::list< ObjectDecl * > & get_tempDecls() { return tempDecls; }
    606         std::list< ObjectDecl * > & get_returnDecls() { return returnDecls; }
    607         std::list< Expression * > & get_dtors() { return dtors; }
    608598
    609599        virtual ImplicitCopyCtorExpr * clone() const { return new ImplicitCopyCtorExpr( * this ); }
Note: See TracChangeset for help on using the changeset viewer.