Changeset 1bc749f
- Timestamp:
- Sep 27, 2017, 4:19:01 PM (7 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- b96ec83
- Parents:
- a139c11
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
ra139c11 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; … … 624 623 } 625 624 626 DeclarationWithType *FixInit::postmutate( ObjectDecl *objDecl ) { 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 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) 628 656 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { … … 733 761 ctorInit->set_ctor( nullptr ); 734 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 777 } 735 778 } // if 736 779 } else if ( Initializer * init = ctorInit->get_init() ) { … … 775 818 776 819 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 809 820 void InsertDtors::previsit( FunctionDecl * funcDecl ) { 810 821 // each function needs to have its own set of labels … … 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 }
Note: See TracChangeset
for help on using the changeset viewer.