Changes in / [a15b72c:6840e7c]
- Location:
- src
- Files:
-
- 2 edited
-
InitTweak/FixInit.cc (modified) (8 diffs)
-
SynTree/Mutator.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
ra15b72c r6840e7c 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; … … 636 635 } 637 636 637 DeclarationWithType * FixInit::getDtorFunc( ObjectDecl * objDecl, Statement * dtor ) { 638 if ( dynamic_cast< ExprStmt * >( dtor ) ) { 639 if ( DeclarationWithType * func = getFunction( getCtorDtorCall( dtor ) ) ) { 640 // cleanup argument must be a function, not an object (including function pointer) 641 if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) { 642 if ( dtorFunc->type->forall.empty() ) { 643 // simple case where the destructor is a monomorphic function call - can simply 644 // use that function as the cleanup function. 645 delete dtor; 646 return func; 647 } 648 } 649 } 650 } 651 652 // otherwise the cleanup is more complicated - need to build a single argument cleanup function that 653 // wraps the more complicated code. 654 static UniqueName dtorNamer( "__cleanup_dtor" ); 655 FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type ), new CompoundStmt( noLabels ) ); 656 stmtsToAddBefore.push_back( new DeclStmt( noLabels, dtorFunc ) ); 657 658 // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter. 659 ObjectDecl * thisParam = getThisParam( dtorFunc->type ); 660 VarExprReplacer::replace( dtor, { std::make_pair( objDecl, thisParam ) } ); 661 dtorFunc->statements->push_back( dtor ); 662 663 return dtorFunc; 664 } 665 638 666 DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) { 639 667 // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate) … … 748 776 ctorInit->ctor = nullptr; 749 777 } 778 779 Statement * dtor = ctorInit->dtor; 780 if ( dtor ) { 781 ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor ); 782 Statement * dtorStmt = implicit->callStmt; 783 // don't need to call intrinsic dtor, because it does nothing, but 784 // non-intrinsic dtors must be called 785 if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) { 786 // set dtor location to the object's location for error messages 787 DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt ); 788 objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) ); 789 // objDecl->attributes.push_back( new Attribute( "cleanup", { new NameExpr( dtorFunc->name ) } ) ); 790 ctorInit->dtor = nullptr; 791 } // if 792 } 750 793 } // if 751 794 } else if ( Initializer * init = ctorInit->init ) { … … 790 833 791 834 792 template<typename Iterator, typename OutputIterator>793 void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {794 for ( Iterator it = begin ; it != end ; ++it ) {795 // extract destructor statement from the object decl and insert it into the output. Note that this is796 // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually797 // calls an intrinsic dtor then the call must (and will) still be generated since the argument may798 // contain side effects.799 ObjectDecl * objDecl = *it;800 ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() );801 assert( ctorInit && ctorInit->get_dtor() );802 *out++ = ctorInit->get_dtor()->clone();803 } // for804 }805 806 void InsertDtors::previsit( ObjectDecl * objDecl ) {807 // remember non-static destructed objects so that their destructors can be inserted later808 if ( ! objDecl->get_storageClasses().is_static ) {809 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {810 // a decision should have been made by the resolver, so ctor and init are not both non-NULL811 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );812 Statement * dtor = ctorInit->get_dtor();813 // don't need to call intrinsic dtor, because it does nothing, but814 // non-intrinsic dtors must be called815 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {816 // set dtor location to the object's location for error messages817 ctorInit->dtor->location = objDecl->location;818 reverseDeclOrder.front().push_front( objDecl );819 } // if820 } // if821 } // if822 }823 824 835 void InsertDtors::previsit( FunctionDecl * funcDecl ) { 825 836 // each function needs to have its own set of labels … … 834 845 } 835 846 836 void InsertDtors::previsit( CompoundStmt * compoundStmt ) {837 // visit statements - this will also populate reverseDeclOrder list. don't want to dump all destructors838 // when block is left, just the destructors associated with variables defined in this block, so push a new839 // list to the top of the stack so that we can differentiate scopes840 reverseDeclOrder.push_front( OrderedDecls() );841 Parent::previsit( compoundStmt );842 }843 844 void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {845 // add destructors for the current scope that we're exiting, unless the last statement is a return, which846 // causes unreachable code warnings847 std::list< Statement * > & statements = compoundStmt->get_kids();848 if ( ! statements.empty() && ! dynamic_cast< ReturnStmt * >( statements.back() ) ) {849 insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( statements ) );850 }851 reverseDeclOrder.pop_front();852 }853 854 void InsertDtors::previsit( ReturnStmt * ) {855 // return exits all scopes, so dump destructors for all scopes856 for ( OrderedDecls & od : reverseDeclOrder ) {857 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );858 } // for859 }860 861 847 // Handle break/continue/goto in the same manner as C++. Basic idea: any objects that are in scope at the 862 848 // BranchStmt but not at the labelled (target) statement must be destructed. If there are any objects in scope … … 886 872 if ( ! diff.empty() ) { 887 873 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt ); 888 } // if889 // S_G-S_L results in set of objects that must be destructed890 diff.clear();891 std::set_difference( curVars.begin(), curVars.end(), lvars.begin(), lvars.end(), std::inserter( diff, diff.end() ) );892 DTOR_PRINT(893 std::cerr << "S_G-S_L = " << printSet( diff ) << std::endl;894 )895 if ( ! diff.empty() ) {896 // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages.897 std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() );898 899 // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor900 OrderedDecls ordered;901 for ( OrderedDecls & rdo : reverseDeclOrder ) {902 // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.903 copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );904 } // for905 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );906 874 } // if 907 875 } -
src/SynTree/Mutator.h
ra15b72c r6840e7c 119 119 120 120 virtual TypeSubstitution * mutate( TypeSubstitution * sub ); 121 121 122 private: 122 123 virtual Declaration * handleAggregateDecl(AggregateDecl * aggregateDecl );
Note:
See TracChangeset
for help on using the changeset viewer.