Changeset 2f86ddf
- Timestamp:
- Sep 6, 2018, 10:51:37 AM (5 years ago)
- Branches:
- arm-eh, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 9b086ca
- Parents:
- ec42ff2e
- Location:
- src
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/PassVisitor.impl.h
rec42ff2e r2f86ddf 1778 1778 VISIT_START( node ); 1779 1779 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 ); 1785 1782 1786 1783 VISIT_END( node ); … … 1791 1788 MUTATE_START( node ); 1792 1789 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 ); 1799 1793 1800 1794 MUTATE_END( Expression, node ); -
src/InitTweak/FixInit.cc
rec42ff2e r2f86ddf 68 68 namespace InitTweak { 69 69 namespace { 70 typedef std::unordered_map< int, int > UnqCount;71 72 70 struct SelfAssignChecker { 73 71 void previsit( ApplicationExpr * appExpr ); … … 82 80 }; 83 81 84 struct ResolveCopyCtors final : public With Indexer, public WithShortCircuiting, public WithTypeSubstitution{82 struct ResolveCopyCtors final : public WithStmtsToAdd, public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution, public WithVisitorRef<ResolveCopyCtors> { 85 83 /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr, 86 84 /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both 87 85 /// 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 ); 96 91 97 92 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) … … 100 95 bool skipCopyConstruct( Type * type ); 101 96 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 ); 106 98 }; 107 99 … … 185 177 }; 186 178 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 destructors192 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 201 179 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> { 202 180 /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors … … 251 229 InitTweak::fixGlobalInit( translationUnit, inLibrary ); 252 230 253 UnqCount unqCount;254 255 231 // must happen before ResolveCopyCtors because temporaries have to be inserted into the correct scope 256 232 SplitExpressions::split( translationUnit ); 257 233 258 234 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 260 238 InsertDtors::insert( translationUnit ); 239 240 ResolveCopyCtors::resolveImplicitCalls( translationUnit ); 261 241 FixInit::fixInitializers( translationUnit ); 262 263 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly264 FixCopyCtors::fixCopyCtors( translationUnit, unqCount );265 266 242 GenStructMemberCalls::generate( translationUnit ); 267 243 … … 335 311 } 336 312 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 ); 340 316 } 341 317 … … 363 339 PassVisitor<InsertDtors> inserter( finder ); 364 340 acceptAll( translationUnit, inserter ); 365 }366 367 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {368 PassVisitor<FixCopyCtors> fixer( unqCount );369 mutateAll( translationUnit, fixer );370 341 } 371 342 … … 529 500 if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) { 530 501 // fix newly generated StmtExpr 531 p ostvisit( assign->stmtExpr );502 premutate( assign->stmtExpr ); 532 503 } 533 504 return resolved; … … 569 540 570 541 // 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 ) { 581 593 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 582 594 583 595 ApplicationExpr * appExpr = impCpCtorExpr->callExpr; 596 ObjectDecl * returnDecl = nullptr; 584 597 585 598 // take each argument and attempt to copy construct it. … … 590 603 for ( Expression * & arg : appExpr->args ) { 591 604 Type * formal = nullptr; 592 if ( iter != params.end() ) { 605 if ( iter != params.end() ) { // does not copy construct C-style variadic arguments 593 606 DeclarationWithType * param = *iter++; 594 607 formal = param->get_type(); … … 608 621 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 609 622 ret->type->set_const( false ); 610 impCpCtorExpr->returnDecls.push_back( ret ); 623 returnDecl = ret; 624 stmtsToAddBefore.push_back( new DeclStmt( ret ) ); 611 625 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 ); 612 640 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 613 641 // 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 ); 616 671 } // 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; 624 675 if ( ! result->isVoid() ) { 625 676 static UniqueName retNamer("_tmp_stmtexpr_ret"); … … 635 686 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 636 687 ret->type->set_const( false ); 637 stmt Expr->returnDecls.push_front( ret);688 stmtsToAddBefore.push_back( new DeclStmt( ret ) ); 638 689 639 690 // must have a non-empty body, otherwise it wouldn't have a result 640 691 CompoundStmt * body = stmtExpr->statements; 641 assert( ! body-> get_kids().empty() );692 assert( ! body->kids.empty() ); 642 693 // 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 ) ) ); 647 705 } // 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() ); 656 709 } 657 710 … … 670 723 } 671 724 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; 684 752 } else { 685 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression686 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 constructors700 for ( ObjectDecl * obj : tempDecls ) {701 stmtsToAddBefore.push_back( new DeclStmt( obj ) );702 } // for703 for ( ObjectDecl * obj : returnDecls ) {704 stmtsToAddBefore.push_back( new DeclStmt( obj ) );705 } // for706 707 // add destructors after current statement708 for ( Expression * dtor : dtors ) {709 // take relevant bindings from environment710 assert( ! dtor->env );711 dtor->env = maybeClone( env );712 stmtsToAddAfter.push_back( new ExprStmt( dtor ) );713 } // for714 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 much721 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 retExpr733 std::swap( retExpr->env, callExpr->env );734 return retExpr;735 } else {736 return callExpr;737 } // if738 }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 added748 // 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 } // for754 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 } // for760 // add destructors after current statement761 for ( Expression * dtor : stmtExpr->dtors ) {762 stmtsToAddAfter.push_back( new ExprStmt( dtor ) );763 } // for764 // must have a non-empty body, otherwise it wouldn't have a result765 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 returns768 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 passes784 if ( unqMap.count( unqExpr->get_id() ) ) {785 753 // take data from other UniqueExpr to ensure consistency 786 754 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 } 805 759 } 806 760 -
src/SynTree/Expression.cc
rec42ff2e r2f86ddf 538 538 assert( callExpr ); 539 539 assert( callExpr->result ); 540 set_result( callExpr-> get_result()->clone() );540 set_result( callExpr->result->clone() ); 541 541 } 542 542 543 543 ImplicitCopyCtorExpr::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 );547 544 } 548 545 … … 550 547 set_env( nullptr ); // ImplicitCopyCtorExpr does not take ownership of an environment 551 548 delete callExpr; 552 deleteAll( tempDecls );553 deleteAll( returnDecls );554 deleteAll( dtors );555 549 } 556 550 … … 558 552 os << "Implicit Copy Constructor Expression: " << std::endl << indent+1; 559 553 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 );565 554 } 566 555 -
src/SynTree/Expression.h
rec42ff2e r2f86ddf 591 591 class ImplicitCopyCtorExpr : public Expression { 592 592 public: 593 ApplicationExpr * callExpr; 594 std::list< ObjectDecl * > tempDecls; 595 std::list< ObjectDecl * > returnDecls; 596 std::list< Expression * > dtors; 593 ApplicationExpr * callExpr = nullptr; 597 594 598 595 ImplicitCopyCtorExpr( ApplicationExpr * callExpr ); 599 596 ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other ); 600 597 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; }608 598 609 599 virtual ImplicitCopyCtorExpr * clone() const { return new ImplicitCopyCtorExpr( * this ); }
Note: See TracChangeset
for help on using the changeset viewer.