Changes in src/InitTweak/FixInit.cc [33a25f9:e3e16bc]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r33a25f9 re3e16bc 70 70 namespace InitTweak { 71 71 namespace { 72 typedef std::unordered_map< Expression *, TypeSubstitution * > EnvMap; 72 73 typedef std::unordered_map< int, int > UnqCount; 73 74 74 struct InsertImplicitCalls : public WithTypeSubstitution { 75 class InsertImplicitCalls : public WithTypeSubstitution { 76 public: 75 77 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which 76 78 /// function calls need their parameters to be copy constructed 77 static void insert( std::list< Declaration * > & translationUnit ); 79 static void insert( std::list< Declaration * > & translationUnit, EnvMap & envMap ); 80 81 InsertImplicitCalls( EnvMap & envMap ) : envMap( envMap ) {} 78 82 79 83 Expression * postmutate( ApplicationExpr * appExpr ); 84 void premutate( StmtExpr * stmtExpr ); 85 86 // collects environments for relevant nodes 87 EnvMap & envMap; 80 88 }; 81 89 82 struct ResolveCopyCtors final : public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution { 90 class ResolveCopyCtors final : public SymTab::Indexer { 91 public: 83 92 /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr, 84 93 /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both 85 94 /// arguments and return value temporaries 86 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount ); 87 88 ResolveCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ) {} 89 90 void postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ); 91 void postvisit( StmtExpr * stmtExpr ); 92 void previsit( UniqueExpr * unqExpr ); 93 void postvisit( UniqueExpr * unqExpr ); 95 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap, UnqCount & unqCount ); 96 97 typedef SymTab::Indexer Parent; 98 using Parent::visit; 99 100 ResolveCopyCtors( const EnvMap & envMap, UnqCount & unqCount ) : envMap( envMap ), unqCount( unqCount ) {} 101 102 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 103 virtual void visit( UniqueExpr * unqExpr ) override; 104 virtual void visit( StmtExpr * stmtExpr ) override; 94 105 95 106 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) … … 100 111 void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr ); 101 112 113 TypeSubstitution * env; 114 const EnvMap & envMap; 102 115 UnqCount & unqCount; // count the number of times each unique expr ID appears 103 std::unordered_set< int > vars;104 116 }; 105 117 … … 226 238 }; 227 239 228 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer { 240 class GenStructMemberCalls final : public SymTab::Indexer { 241 public: 242 typedef Indexer Parent; 229 243 /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors 230 244 /// for any member that is missing a corresponding ctor/dtor call. … … 232 246 static void generate( std::list< Declaration * > & translationUnit ); 233 247 234 void previsit( FunctionDecl * funcDecl ); 235 void postvisit( FunctionDecl * funcDecl ); 236 237 void previsit( MemberExpr * memberExpr ); 238 void previsit( ApplicationExpr * appExpr ); 248 using Parent::visit; 249 250 virtual void visit( FunctionDecl * funcDecl ) override; 251 252 virtual void visit( MemberExpr * memberExpr ) override; 253 virtual void visit( ApplicationExpr * appExpr ) override; 239 254 240 255 SemanticError errors; … … 280 295 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary ); 281 296 297 EnvMap envMap; 282 298 UnqCount unqCount; 283 299 284 InsertImplicitCalls::insert( translationUnit );285 ResolveCopyCtors::resolveImplicitCalls( translationUnit, unqCount );300 InsertImplicitCalls::insert( translationUnit, envMap ); 301 ResolveCopyCtors::resolveImplicitCalls( translationUnit, envMap, unqCount ); 286 302 InsertDtors::insert( translationUnit ); 287 303 FixInit::fixInitializers( translationUnit ); … … 302 318 303 319 namespace { 304 void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {305 PassVisitor<InsertImplicitCalls> inserter ;320 void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit, EnvMap & envMap ) { 321 PassVisitor<InsertImplicitCalls> inserter( envMap ); 306 322 mutateAll( translationUnit, inserter ); 307 323 } 308 324 309 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {310 PassVisitor<ResolveCopyCtors> resolver(unqCount );325 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap, UnqCount & unqCount ) { 326 ResolveCopyCtors resolver( envMap, unqCount ); 311 327 acceptAll( translationUnit, resolver ); 312 328 } … … 344 360 345 361 void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) { 346 PassVisitor<GenStructMemberCalls>warner;362 GenStructMemberCalls warner; 347 363 acceptAll( translationUnit, warner ); 348 364 } … … 382 398 // wrap each function call so that it is easy to identify nodes that have to be copy constructed 383 399 ImplicitCopyCtorExpr * expr = new ImplicitCopyCtorExpr( appExpr ); 384 // Move the type substitution to the new top-level, if it is attached to the appExpr.400 // save the type substitution into the envMap so that it is easy to find. 385 401 // Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion. 386 402 // The substitution is needed to obtain the type of temporary variables so that copy constructor 387 // calls can be resolved. 403 // calls can be resolved. Normally this is what PolyMutator is for, but the pass that resolves 404 // copy constructor calls must be an Indexer. We could alternatively make a PolyIndexer which 405 // saves the environment, or compute the types of temporaries here, but it's much simpler to 406 // save the environment here, and more cohesive to compute temporary variables and resolve copy 407 // constructor calls together. 388 408 assert( env ); 389 std::swap( expr->env, appExpr->env );409 envMap[expr] = env; 390 410 return expr; 411 } 412 413 void InsertImplicitCalls::premutate( StmtExpr * stmtExpr ) { 414 assert( env ); 415 envMap[stmtExpr] = env; 391 416 } 392 417 … … 406 431 // (VariableExpr and already resolved expression) 407 432 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 408 Expression * resolved = ResolvExpr::findVoidExpression( untyped, indexer);433 Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this ); 409 434 assert( resolved ); 410 435 if ( resolved->get_env() ) { … … 455 480 } 456 481 457 void ResolveCopyCtors:: postvisit( ImplicitCopyCtorExpr *impCpCtorExpr ) {482 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) { 458 483 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 484 Parent::visit( impCpCtorExpr ); 485 env = envMap.at(impCpCtorExpr); 486 assert( env ); 459 487 460 488 ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr(); … … 485 513 } 486 514 487 void ResolveCopyCtors::postvisit( StmtExpr * stmtExpr ) { 488 assert( env ); 515 void ResolveCopyCtors::visit( StmtExpr * stmtExpr ) { 516 Parent::visit( stmtExpr ); 517 env = envMap.at(stmtExpr); 489 518 assert( stmtExpr->get_result() ); 490 519 Type * result = stmtExpr->get_result(); … … 508 537 stmtExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 509 538 } // if 510 } 511 512 void ResolveCopyCtors::previsit( UniqueExpr * unqExpr ) { 539 540 } 541 542 void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) { 543 static std::unordered_set< int > vars; 513 544 unqCount[ unqExpr->get_id() ]++; // count the number of unique expressions for each ID 514 545 if ( vars.count( unqExpr->get_id() ) ) { 515 546 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated 516 visit_children = false;517 }518 }519 520 void ResolveCopyCtors::postvisit( UniqueExpr * unqExpr ) {521 if ( vars.count( unqExpr->get_id() ) ) {522 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated523 547 return; 524 548 } 525 549 550 Parent::visit( unqExpr ); 526 551 // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought 527 552 assert( unqExpr->get_result() ); … … 560 585 561 586 // xxx - update to work with multiple return values 562 ObjectDecl * returnDecl = returnDecls.empty() ? nullptr: returnDecls.front();587 ObjectDecl * returnDecl = returnDecls.empty() ? NULL : returnDecls.front(); 563 588 Expression * callExpr = impCpCtorExpr->get_callExpr(); 564 589 … … 569 594 tempDecls.clear(); 570 595 returnDecls.clear(); 571 impCpCtorExpr->set_callExpr( nullptr ); 572 std::swap( impCpCtorExpr->env, callExpr->env ); 573 assert( impCpCtorExpr->env == nullptr ); 596 impCpCtorExpr->set_callExpr( NULL ); 597 impCpCtorExpr->set_env( NULL ); 574 598 delete impCpCtorExpr; 575 599 … … 954 978 } 955 979 956 void GenStructMemberCalls:: previsit( FunctionDecl * funcDecl ) {957 GuardValue( funcDecl );958 GuardValue( unhandled );959 GuardValue( usedUninit );960 GuardValue( thisParam );961 GuardValue( isCtor );962 GuardValue( structDecl );980 void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) { 981 ValueGuard< FunctionDecl * > oldFunction( funcDecl ); 982 ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled ); 983 ValueGuard< std::map< DeclarationWithType *, CodeLocation > > oldUsedUninit( usedUninit ); 984 ValueGuard< ObjectDecl * > oldThisParam( thisParam ); 985 ValueGuard< bool > oldIsCtor( isCtor ); 986 ValueGuard< StructDecl * > oldStructDecl( structDecl ); 963 987 errors = SemanticError(); // clear previous errors 964 988 … … 986 1010 } 987 1011 } 988 } 989 990 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) { 991 for ( auto d : decls ) { 992 indexer.addId( d ); 993 } 994 } 995 996 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) { 997 for ( auto td : tds ) { 998 indexer.addType( td ); 999 addIds( indexer, td->assertions ); 1000 } 1001 } 1002 1003 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) { 1012 Parent::visit( function ); 1013 1004 1014 // remove the unhandled objects from usedUninit, because a call is inserted 1005 1015 // to handle them - only objects that are later constructed are used uninitialized. … … 1022 1032 if ( ! unhandled.empty() ) { 1023 1033 // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors 1024 auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this]() { indexer.leaveScope(); } ); 1025 addTypes( indexer, function->type->forall ); 1026 addIds( indexer, function->type->returnVals ); 1027 addIds( indexer, function->type->parameters ); 1034 enterScope(); 1035 maybeAccept( function->get_functionType(), *this ); 1028 1036 1029 1037 // need to iterate through members in reverse in order for … … 1055 1063 Statement * callStmt = stmt.front(); 1056 1064 1057 MutatingResolver resolver( indexer);1065 MutatingResolver resolver( *this ); 1058 1066 try { 1059 1067 callStmt->acceptMutator( resolver ); … … 1069 1077 } 1070 1078 } 1079 leaveScope(); 1071 1080 } 1072 1081 if (! errors.isEmpty()) { … … 1098 1107 } 1099 1108 1100 void GenStructMemberCalls::previsit( ApplicationExpr * appExpr ) { 1101 if ( ! checkWarnings( function ) ) { 1102 visit_children = false; 1103 return; 1104 } 1109 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 1110 if ( ! checkWarnings( function ) ) return; 1105 1111 1106 1112 std::string fname = getFunctionName( appExpr ); … … 1121 1127 } 1122 1128 } 1123 } 1124 1125 void GenStructMemberCalls::previsit( MemberExpr * memberExpr ) { 1126 if ( ! checkWarnings( function ) || ! isCtor ) { 1127 visit_children = false; 1128 return; 1129 } 1129 Parent::visit( appExpr ); 1130 } 1131 1132 void GenStructMemberCalls::visit( MemberExpr * memberExpr ) { 1133 if ( ! checkWarnings( function ) ) return; 1134 if ( ! isCtor ) return; 1130 1135 1131 1136 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { … … 1135 1140 } 1136 1141 } 1142 Parent::visit( memberExpr ); 1137 1143 } 1138 1144 … … 1155 1161 // in generated code. If this changes, add mutate methods for entities with 1156 1162 // scope and call {enter,leave}Scope explicitly. 1157 indexer.addId( objectDecl);1163 objectDecl->accept( indexer ); 1158 1164 return objectDecl; 1159 1165 }
Note:
See TracChangeset
for help on using the changeset viewer.