Changes in src/InitTweak/FixInit.cc [b0f601fa:1bc749f]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
rb0f601fa r1bc749f 54 54 #include "SynTree/Type.h" // for Type, Type::StorageClasses 55 55 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution, operator<< 56 #include "SynTree/VarExprReplacer.h" // for VarExprReplacer 56 57 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 57 58 … … 158 159 using Parent::previsit; 159 160 160 void previsit( ObjectDecl * objDecl );161 161 void previsit( FunctionDecl * funcDecl ); 162 162 163 void previsit( CompoundStmt * compoundStmt );164 void postvisit( CompoundStmt * compoundStmt );165 void previsit( ReturnStmt * returnStmt );166 163 void previsit( BranchStmt * stmt ); 167 164 private: … … 179 176 180 177 DeclarationWithType * postmutate( ObjectDecl *objDecl ); 178 179 DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * dtor ); 181 180 182 181 std::list< Declaration * > staticDtorDecls; … … 214 213 void emit( CodeLocation, const Params &... params ); 215 214 216 FunctionDecl * function = nullptr;215 FunctionDecl * function = 0; 217 216 std::set< DeclarationWithType * > unhandled; 218 217 std::map< DeclarationWithType *, CodeLocation > usedUninit; 219 ObjectDecl * thisParam = nullptr;218 ObjectDecl * thisParam = 0; 220 219 bool isCtor = false; // true if current function is a constructor 221 StructDecl * structDecl = nullptr;220 StructDecl * structDecl = 0; 222 221 }; 223 222 … … 624 623 } 625 624 625 DeclarationWithType * FixInit::getDtorFunc( ObjectDecl * objDecl, Statement * dtor ) { 626 if ( dynamic_cast< ExprStmt * >( dtor ) ) { 627 if ( DeclarationWithType * func = getFunction( getCtorDtorCall( dtor ) ) ) { 628 // cleanup argument must be a function, not an object (including function pointer) 629 if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) { 630 if ( dtorFunc->type->forall.empty() ) { 631 // simple case where the destructor is a monomorphic function call - can simply 632 // use that function as the cleanup function. 633 delete dtor; 634 return func; 635 } 636 } 637 } 638 } 639 640 // otherwise the cleanup is more complicated - need to build a single argument cleanup function that 641 // wraps the more complicated code. 642 static UniqueName dtorNamer( "__cleanup_dtor" ); 643 FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type ), new CompoundStmt( noLabels ) ); 644 stmtsToAddBefore.push_back( new DeclStmt( noLabels, dtorFunc ) ); 645 646 // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter. 647 ObjectDecl * thisParam = getThisParam( dtorFunc->type ); 648 VarExprReplacer::replace( dtor, { std::make_pair( objDecl, thisParam ) } ); 649 dtorFunc->statements->push_back( dtor ); 650 651 return dtorFunc; 652 } 653 626 654 DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) { 627 655 // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate) … … 722 750 } else { 723 751 ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * > ( ctor ); 724 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit-> callStmt);752 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->get_callStmt() ); 725 753 ApplicationExpr * ctorCall = nullptr; 726 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt-> expr)) && ctorCall->get_args().size() == 2 ) {754 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->get_expr() )) && ctorCall->get_args().size() == 2 ) { 727 755 // clean up intrinsic copy constructor calls by making them into SingleInits 728 objDecl-> init = new SingleInit( ctorCall->args.back() );729 ctorCall-> args.pop_back();756 objDecl->set_init( new SingleInit( ctorCall->get_args().back() ) ); 757 ctorCall->get_args().pop_back(); 730 758 } else { 731 759 stmtsToAddAfter.push_back( ctor ); 732 objDecl->init = nullptr; 733 ctorInit->ctor = nullptr; 760 objDecl->set_init( nullptr ); 761 ctorInit->set_ctor( nullptr ); 762 } 763 764 Statement * dtor = ctorInit->dtor; 765 if ( dtor ) { 766 ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor ); 767 Statement * dtorStmt = implicit->callStmt; 768 // don't need to call intrinsic dtor, because it does nothing, but 769 // non-intrinsic dtors must be called 770 if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) { 771 // set dtor location to the object's location for error messages 772 DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt ); 773 objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) ); 774 // objDecl->attributes.push_back( new Attribute( "cleanup", { new NameExpr( dtorFunc->name ) } ) ); 775 ctorInit->dtor = nullptr; 776 } // if 734 777 } 735 778 } // if 736 } else if ( Initializer * init = ctorInit-> init) {737 objDecl-> init = init;738 ctorInit-> init = nullptr;779 } else if ( Initializer * init = ctorInit->get_init() ) { 780 objDecl->set_init( init ); 781 ctorInit->set_init( nullptr ); 739 782 } else { 740 783 // no constructor and no initializer, which is okay 741 objDecl-> init = nullptr;784 objDecl->set_init( nullptr ); 742 785 } // if 743 786 delete ctorInit; … … 774 817 } 775 818 776 777 template<typename Iterator, typename OutputIterator>778 void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {779 for ( Iterator it = begin ; it != end ; ++it ) {780 // extract destructor statement from the object decl and insert it into the output. Note that this is781 // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually782 // calls an intrinsic dtor then the call must (and will) still be generated since the argument may783 // contain side effects.784 ObjectDecl * objDecl = *it;785 ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() );786 assert( ctorInit && ctorInit->get_dtor() );787 *out++ = ctorInit->get_dtor()->clone();788 } // for789 }790 791 void InsertDtors::previsit( ObjectDecl * objDecl ) {792 // remember non-static destructed objects so that their destructors can be inserted later793 if ( ! objDecl->get_storageClasses().is_static ) {794 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {795 // a decision should have been made by the resolver, so ctor and init are not both non-NULL796 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );797 Statement * dtor = ctorInit->get_dtor();798 // don't need to call intrinsic dtor, because it does nothing, but799 // non-intrinsic dtors must be called800 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {801 // set dtor location to the object's location for error messages802 ctorInit->dtor->location = objDecl->location;803 reverseDeclOrder.front().push_front( objDecl );804 } // if805 } // if806 } // if807 }808 819 809 820 void InsertDtors::previsit( FunctionDecl * funcDecl ) { … … 815 826 816 827 // all labels for this function have been collected, insert destructors as appropriate via implicit recursion. 817 }818 819 void InsertDtors::previsit( CompoundStmt * compoundStmt ) {820 // visit statements - this will also populate reverseDeclOrder list. don't want to dump all destructors821 // when block is left, just the destructors associated with variables defined in this block, so push a new822 // list to the top of the stack so that we can differentiate scopes823 reverseDeclOrder.push_front( OrderedDecls() );824 Parent::previsit( compoundStmt );825 }826 827 void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {828 // add destructors for the current scope that we're exiting, unless the last statement is a return, which829 // causes unreachable code warnings830 std::list< Statement * > & statements = compoundStmt->get_kids();831 if ( ! statements.empty() && ! dynamic_cast< ReturnStmt * >( statements.back() ) ) {832 insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( statements ) );833 }834 reverseDeclOrder.pop_front();835 }836 837 void InsertDtors::previsit( ReturnStmt * ) {838 // return exits all scopes, so dump destructors for all scopes839 for ( OrderedDecls & od : reverseDeclOrder ) {840 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );841 } // for842 828 } 843 829 … … 869 855 if ( ! diff.empty() ) { 870 856 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt ); 871 } // if872 // S_G-S_L results in set of objects that must be destructed873 diff.clear();874 std::set_difference( curVars.begin(), curVars.end(), lvars.begin(), lvars.end(), std::inserter( diff, diff.end() ) );875 DTOR_PRINT(876 std::cerr << "S_G-S_L = " << printSet( diff ) << std::endl;877 )878 if ( ! diff.empty() ) {879 // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages.880 std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() );881 882 // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor883 OrderedDecls ordered;884 for ( OrderedDecls & rdo : reverseDeclOrder ) {885 // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.886 copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );887 } // for888 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );889 857 } // if 890 858 } … … 912 880 } 913 881 914 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {915 for ( auto d : decls ) {916 indexer.addId( d );917 }918 }919 920 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {921 for ( auto td : tds ) {922 indexer.addType( td );923 addIds( indexer, td->assertions );924 }925 }926 927 882 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) { 928 GuardValue( func tion);883 GuardValue( funcDecl ); 929 884 GuardValue( unhandled ); 930 885 GuardValue( usedUninit ); … … 959 914 } 960 915 916 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) { 917 for ( auto d : decls ) { 918 indexer.addId( d ); 919 } 920 } 921 922 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) { 923 for ( auto td : tds ) { 924 indexer.addType( td ); 925 addIds( indexer, td->assertions ); 926 } 927 } 928 961 929 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) { 962 930 // remove the unhandled objects from usedUninit, because a call is inserted
Note:
See TracChangeset
for help on using the changeset viewer.