Changes in src/InitTweak/GenInit.cc [0bd3faf:f02f546]
- File:
-
- 1 edited
-
src/InitTweak/GenInit.cc (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/GenInit.cc
r0bd3faf rf02f546 29 29 #include "CompilationState.h" 30 30 #include "CodeGen/OperatorTable.h" 31 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... 31 32 #include "Common/SemanticError.h" // for SemanticError 32 33 #include "Common/ToString.hpp" // for toCString … … 37 38 #include "InitTweak.h" // for isConstExpr, InitExpander, checkIn... 38 39 #include "ResolvExpr/Resolver.h" 40 #include "SymTab/Autogen.h" // for genImplicitCall 39 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 40 42 #include "SymTab/Mangler.h" // for Mangler 43 #include "SynTree/LinkageSpec.h" // for isOverridable, C 44 #include "SynTree/Declaration.h" // for ObjectDecl, DeclarationWithType 45 #include "SynTree/Expression.h" // for VariableExpr, UntypedExpr, Address... 46 #include "SynTree/Initializer.h" // for ConstructorInit, SingleInit, Initi... 47 #include "SynTree/Label.h" // for Label 48 #include "SynTree/Mutator.h" // for mutateAll 49 #include "SynTree/Statement.h" // for CompoundStmt, ImplicitCtorDtorStmt 50 #include "SynTree/Type.h" // for Type, ArrayType, Type::Qualifiers 51 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 41 52 #include "Tuples/Tuples.h" // for maybeImpure 42 53 #include "Validate/FindSpecialDecls.h" // for SizeType 43 54 44 55 namespace InitTweak { 56 namespace { 57 const std::list<Label> noLabels; 58 const std::list<Expression *> noDesignators; 59 } 60 61 struct ReturnFixer : public WithStmtsToAdd, public WithGuards { 62 /// consistently allocates a temporary variable for the return value 63 /// of a function so that anything which the resolver decides can be constructed 64 /// into the return type of a function can be returned. 65 static void makeReturnTemp( std::list< Declaration * > &translationUnit ); 66 67 void premutate( FunctionDecl *functionDecl ); 68 void premutate( ReturnStmt * returnStmt ); 69 70 protected: 71 FunctionType * ftype = nullptr; 72 std::string funcName; 73 }; 74 75 struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor> { 76 /// create constructor and destructor statements for object declarations. 77 /// the actual call statements will be added in after the resolver has run 78 /// so that the initializer expression is only removed if a constructor is found 79 /// and the same destructor call is inserted in all of the appropriate locations. 80 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 81 82 void previsit( ObjectDecl * ); 83 void previsit( FunctionDecl *functionDecl ); 84 85 // should not traverse into any of these declarations to find objects 86 // that need to be constructed or destructed 87 void previsit( StructDecl *aggregateDecl ); 88 void previsit( AggregateDecl * ) { visit_children = false; } 89 void previsit( NamedTypeDecl * ) { visit_children = false; } 90 void previsit( FunctionType * ) { visit_children = false; } 91 92 void previsit( CompoundStmt * compoundStmt ); 93 94 private: 95 // set of mangled type names for which a constructor or destructor exists in the current scope. 96 // these types require a ConstructorInit node to be generated, anything else is a POD type and thus 97 // should not have a ConstructorInit generated. 98 99 ManagedTypes managedTypes; 100 bool inFunction = false; 101 }; 102 103 struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards, public WithIndexer { 104 /// hoist dimension from array types in object declaration so that it uses a single 105 /// const variable of type size_t, so that side effecting array dimensions are only 106 /// computed once. 107 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 108 109 void premutate( ObjectDecl * objectDecl ); 110 DeclarationWithType * postmutate( ObjectDecl * objectDecl ); 111 void premutate( FunctionDecl *functionDecl ); 112 // should not traverse into any of these declarations to find objects 113 // that need to be constructed or destructed 114 void premutate( AggregateDecl * ) { visit_children = false; } 115 void premutate( NamedTypeDecl * ) { visit_children = false; } 116 void premutate( FunctionType * ) { visit_children = false; } 117 118 // need this so that enumerators are added to the indexer, due to premutate(AggregateDecl *) 119 void premutate( EnumDecl * ) {} 120 121 void hoist( Type * type ); 122 123 Type::StorageClasses storageClasses; 124 bool inFunction = false; 125 }; 126 127 struct HoistArrayDimension_NoResolve final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards { 128 /// hoist dimension from array types in object declaration so that it uses a single 129 /// const variable of type size_t, so that side effecting array dimensions are only 130 /// computed once. 131 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 132 133 void premutate( ObjectDecl * objectDecl ); 134 DeclarationWithType * postmutate( ObjectDecl * objectDecl ); 135 void premutate( FunctionDecl *functionDecl ); 136 // should not traverse into any of these declarations to find objects 137 // that need to be constructed or destructed 138 void premutate( AggregateDecl * ) { visit_children = false; } 139 void premutate( NamedTypeDecl * ) { visit_children = false; } 140 void premutate( FunctionType * ) { visit_children = false; } 141 142 void hoist( Type * type ); 143 144 Type::StorageClasses storageClasses; 145 bool inFunction = false; 146 }; 147 148 void genInit( std::list< Declaration * > & translationUnit ) { 149 if (!useNewAST) { 150 HoistArrayDimension::hoistArrayDimension( translationUnit ); 151 } 152 else { 153 HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit ); 154 } 155 fixReturnStatements( translationUnit ); 156 157 if (!useNewAST) { 158 CtorDtor::generateCtorDtor( translationUnit ); 159 } 160 } 161 162 void fixReturnStatements( std::list< Declaration * > & translationUnit ) { 163 PassVisitor<ReturnFixer> fixer; 164 mutateAll( translationUnit, fixer ); 165 } 166 167 void ReturnFixer::premutate( ReturnStmt *returnStmt ) { 168 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals(); 169 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 170 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address 171 // is being returned 172 if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) { 173 // explicitly construct the return value using the return expression and the retVal object 174 assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() ); 175 176 ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() ); 177 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) { 178 // return statement has already been mutated - don't need to do it again 179 if ( varExpr->var == retVal ) return; 180 } 181 Statement * stmt = genCtorDtor( "?{}", retVal, returnStmt->expr ); 182 assertf( stmt, "ReturnFixer: genCtorDtor returned nullptr: %s / %s", toString( retVal ).c_str(), toString( returnStmt->expr ).c_str() ); 183 stmtsToAddBefore.push_back( stmt ); 184 185 // return the retVal object 186 returnStmt->expr = new VariableExpr( returnVals.front() ); 187 } // if 188 } 189 190 void ReturnFixer::premutate( FunctionDecl *functionDecl ) { 191 GuardValue( ftype ); 192 GuardValue( funcName ); 193 194 ftype = functionDecl->type; 195 funcName = functionDecl->name; 196 } 197 198 // precompute array dimension expression, because constructor generation may duplicate it, 199 // which would be incorrect if it is a side-effecting computation. 200 void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 201 PassVisitor<HoistArrayDimension> hoister; 202 mutateAll( translationUnit, hoister ); 203 } 204 205 void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) { 206 GuardValue( storageClasses ); 207 storageClasses = objectDecl->get_storageClasses(); 208 } 209 210 DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) { 211 hoist( objectDecl->get_type() ); 212 return objectDecl; 213 } 214 215 void HoistArrayDimension::hoist( Type * type ) { 216 // if in function, generate const size_t var 217 static UniqueName dimensionName( "_array_dim" ); 218 219 // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension. 220 if ( ! inFunction ) return; 221 if ( storageClasses.is_static ) return; 222 223 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 224 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 225 226 // need to resolve array dimensions in order to accurately determine if constexpr 227 ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer ); 228 // array is variable-length when the dimension is not constexpr 229 arrayType->isVarLen = ! isConstExpr( arrayType->dimension ); 230 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 231 // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve 232 // still try to detect constant expressions 233 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 234 235 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); 236 arrayDimension->get_type()->set_const( true ); 237 238 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 239 declsToAddBefore.push_back( arrayDimension ); 240 241 hoist( arrayType->get_base() ); 242 return; 243 } 244 } 245 246 void HoistArrayDimension::premutate( FunctionDecl * ) { 247 GuardValue( inFunction ); 248 inFunction = true; 249 } 250 251 // precompute array dimension expression, because constructor generation may duplicate it, 252 // which would be incorrect if it is a side-effecting computation. 253 void HoistArrayDimension_NoResolve::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 254 PassVisitor<HoistArrayDimension_NoResolve> hoister; 255 mutateAll( translationUnit, hoister ); 256 } 257 258 void HoistArrayDimension_NoResolve::premutate( ObjectDecl * objectDecl ) { 259 GuardValue( storageClasses ); 260 storageClasses = objectDecl->get_storageClasses(); 261 } 262 263 DeclarationWithType * HoistArrayDimension_NoResolve::postmutate( ObjectDecl * objectDecl ) { 264 hoist( objectDecl->get_type() ); 265 return objectDecl; 266 } 267 268 void HoistArrayDimension_NoResolve::hoist( Type * type ) { 269 // if in function, generate const size_t var 270 static UniqueName dimensionName( "_array_dim" ); 271 272 // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension. 273 if ( ! inFunction ) return; 274 if ( storageClasses.is_static ) return; 275 276 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 277 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 278 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 279 // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve 280 // still try to detect constant expressions 281 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 282 283 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); 284 arrayDimension->get_type()->set_const( true ); 285 286 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 287 declsToAddBefore.push_back( arrayDimension ); 288 289 hoist( arrayType->get_base() ); 290 return; 291 } 292 } 293 294 void HoistArrayDimension_NoResolve::premutate( FunctionDecl * ) { 295 GuardValue( inFunction ); 296 inFunction = true; 297 } 45 298 46 299 namespace { 47 300 301 # warning Remove the _New suffix after the conversion is complete. 302 48 303 // Outer pass finds declarations, for their type could wrap a type that needs hoisting 49 struct HoistArrayDimension_NoResolve final :304 struct HoistArrayDimension_NoResolve_New final : 50 305 public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting, 51 306 public ast::WithGuards, public ast::WithConstTranslationUnit, 52 public ast::WithVisitorRef<HoistArrayDimension_NoResolve >,307 public ast::WithVisitorRef<HoistArrayDimension_NoResolve_New>, 53 308 public ast::WithSymbolTableX<ast::SymbolTable::ErrorDetection::IgnoreErrors> { 54 309 … … 57 312 public ast::WithShortCircuiting, public ast::WithGuards { 58 313 59 HoistArrayDimension_NoResolve * outer;60 HoistDimsFromTypes( HoistArrayDimension_NoResolve * outer ) : outer(outer) {}314 HoistArrayDimension_NoResolve_New * outer; 315 HoistDimsFromTypes( HoistArrayDimension_NoResolve_New * outer ) : outer(outer) {} 61 316 62 317 // Only intended for visiting through types. … … 209 464 210 465 211 struct ReturnFixer final :466 struct ReturnFixer_New final : 212 467 public ast::WithStmtsToAdd<>, ast::WithGuards, ast::WithShortCircuiting { 213 468 void previsit( const ast::FunctionDecl * decl ); … … 217 472 }; 218 473 219 void ReturnFixer ::previsit( const ast::FunctionDecl * decl ) {474 void ReturnFixer_New::previsit( const ast::FunctionDecl * decl ) { 220 475 if (decl->linkage == ast::Linkage::Intrinsic) visit_children = false; 221 476 GuardValue( funcDecl ) = decl; 222 477 } 223 478 224 const ast::ReturnStmt * ReturnFixer ::previsit(479 const ast::ReturnStmt * ReturnFixer_New::previsit( 225 480 const ast::ReturnStmt * stmt ) { 226 481 auto & returns = funcDecl->returns; … … 263 518 264 519 void genInit( ast::TranslationUnit & transUnit ) { 265 ast::Pass<HoistArrayDimension_NoResolve >::run( transUnit );266 ast::Pass<ReturnFixer >::run( transUnit );520 ast::Pass<HoistArrayDimension_NoResolve_New>::run( transUnit ); 521 ast::Pass<ReturnFixer_New>::run( transUnit ); 267 522 } 268 523 269 524 void fixReturnStatements( ast::TranslationUnit & transUnit ) { 270 ast::Pass<ReturnFixer>::run( transUnit ); 271 } 272 273 bool ManagedTypes::isManaged( const ast::Type * type ) const { 525 ast::Pass<ReturnFixer_New>::run( transUnit ); 526 } 527 528 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { 529 PassVisitor<CtorDtor> ctordtor; 530 acceptAll( translationUnit, ctordtor ); 531 } 532 533 bool ManagedTypes::isManaged( Type * type ) const { 534 // references are never constructed 535 if ( dynamic_cast< ReferenceType * >( type ) ) return false; 536 // need to clear and reset qualifiers when determining if a type is managed 537 ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() ); 538 type->get_qualifiers() = Type::Qualifiers(); 539 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 540 // tuple is also managed if any of its components are managed 541 if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) { 542 return true; 543 } 544 } 545 // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable) 546 return managedTypes.find( SymTab::Mangler::mangleConcrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type ); 547 } 548 549 bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const { 550 Type * type = objDecl->get_type(); 551 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 552 // must always construct VLAs with an initializer, since this is an error in C 553 if ( at->isVarLen && objDecl->init ) return true; 554 type = at->get_base(); 555 } 556 return isManaged( type ); 557 } 558 559 // why is this not just on FunctionDecl? 560 void ManagedTypes::handleDWT( DeclarationWithType * dwt ) { 561 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 562 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) { 563 std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters(); 564 assert( ! params.empty() ); 565 Type * type = InitTweak::getPointerBase( params.front()->get_type() ); 566 assert( type ); 567 managedTypes.insert( SymTab::Mangler::mangleConcrete( type ) ); 568 } 569 } 570 571 void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) { 572 // don't construct members, but need to take note if there is a managed member, 573 // because that means that this type is also managed 574 for ( Declaration * member : aggregateDecl->get_members() ) { 575 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 576 if ( isManaged( field ) ) { 577 // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that 578 // polymorphic constructors make generic types managed types 579 StructInstType inst( Type::Qualifiers(), aggregateDecl ); 580 managedTypes.insert( SymTab::Mangler::mangleConcrete( &inst ) ); 581 break; 582 } 583 } 584 } 585 } 586 587 void ManagedTypes::beginScope() { managedTypes.beginScope(); } 588 void ManagedTypes::endScope() { managedTypes.endScope(); } 589 590 bool ManagedTypes_new::isManaged( const ast::Type * type ) const { 274 591 // references are never constructed 275 592 if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false; … … 290 607 } 291 608 292 bool ManagedTypes ::isManaged( const ast::ObjectDecl * objDecl ) const {609 bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const { 293 610 const ast::Type * type = objDecl->type; 294 611 while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) { … … 300 617 } 301 618 302 void ManagedTypes ::handleDWT( const ast::DeclWithType * dwt ) {619 void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) { 303 620 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 304 621 if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) { … … 311 628 } 312 629 313 void ManagedTypes ::handleStruct( const ast::StructDecl * aggregateDecl ) {630 void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) { 314 631 // don't construct members, but need to take note if there is a managed member, 315 632 // because that means that this type is also managed … … 327 644 } 328 645 329 void ManagedTypes::beginScope() { managedTypes.beginScope(); } 330 void ManagedTypes::endScope() { managedTypes.endScope(); } 646 void ManagedTypes_new::beginScope() { managedTypes.beginScope(); } 647 void ManagedTypes_new::endScope() { managedTypes.endScope(); } 648 649 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) { 650 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 651 assertf( objDecl, "genCtorDtor passed null objDecl" ); 652 std::list< Statement * > stmts; 653 InitExpander_old srcParam( maybeClone( arg ) ); 654 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), fname, back_inserter( stmts ), objDecl ); 655 assert( stmts.size() <= 1 ); 656 return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr; 657 658 } 331 659 332 660 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) { 333 661 assertf(objDecl, "genCtorDtor passed null objDecl"); 334 InitExpander srcParam(arg);662 InitExpander_new srcParam(arg); 335 663 return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl); 664 } 665 666 ConstructorInit * genCtorInit( ObjectDecl * objDecl ) { 667 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 668 // for each constructable object 669 std::list< Statement * > ctor; 670 std::list< Statement * > dtor; 671 672 InitExpander_old srcParam( objDecl->get_init() ); 673 InitExpander_old nullParam( (Initializer *)NULL ); 674 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 675 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 676 677 // Currently genImplicitCall produces a single Statement - a CompoundStmt 678 // which wraps everything that needs to happen. As such, it's technically 679 // possible to use a Statement ** in the above calls, but this is inherently 680 // unsafe, so instead we take the slightly less efficient route, but will be 681 // immediately informed if somehow the above assumption is broken. In this case, 682 // we could always wrap the list of statements at this point with a CompoundStmt, 683 // but it seems reasonable at the moment for this to be done by genImplicitCall 684 // itself. It is possible that genImplicitCall produces no statements (e.g. if 685 // an array type does not have a dimension). In this case, it's fine to ignore 686 // the object for the purposes of construction. 687 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 688 if ( ctor.size() == 1 ) { 689 // need to remember init expression, in case no ctors exist 690 // if ctor does exist, want to use ctor expression instead of init 691 // push this decision to the resolver 692 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 693 return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ); 694 } 695 return nullptr; 696 } 697 698 void CtorDtor::previsit( ObjectDecl * objDecl ) { 699 managedTypes.handleDWT( objDecl ); 700 // hands off if @=, extern, builtin, etc. 701 // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C 702 if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) { 703 // constructed objects cannot be designated 704 if ( isDesignated( objDecl->get_init() ) ) SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" ); 705 // constructed objects should not have initializers nested too deeply 706 if ( ! checkInitDepth( objDecl ) ) SemanticError( objDecl, "Managed object's initializer is too deep " ); 707 708 objDecl->set_init( genCtorInit( objDecl ) ); 709 } 710 } 711 712 void CtorDtor::previsit( FunctionDecl *functionDecl ) { 713 visit_children = false; // do not try and construct parameters or forall parameters 714 GuardValue( inFunction ); 715 inFunction = true; 716 717 managedTypes.handleDWT( functionDecl ); 718 719 GuardScope( managedTypes ); 720 // go through assertions and recursively add seen ctor/dtors 721 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) { 722 for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) { 723 managedTypes.handleDWT( assertion ); 724 } 725 } 726 727 maybeAccept( functionDecl->get_statements(), *visitor ); 728 } 729 730 void CtorDtor::previsit( StructDecl *aggregateDecl ) { 731 visit_children = false; // do not try to construct and destruct aggregate members 732 733 managedTypes.handleStruct( aggregateDecl ); 734 } 735 736 void CtorDtor::previsit( CompoundStmt * ) { 737 GuardScope( managedTypes ); 336 738 } 337 739 … … 339 741 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor for each 340 742 // constructable object 341 InitExpander srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };743 InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr }; 342 744 ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl); 343 745
Note:
See TracChangeset
for help on using the changeset viewer.