Changeset adcc065 for src/InitTweak
- Timestamp:
- Jul 6, 2016, 6:06:27 PM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 3f869f0
- Parents:
- e04c5ff
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
re04c5ff radcc065 9 9 // Author : Rob Schluntz 10 10 // Created On : Wed Jan 13 16:29:30 2016 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Fri May 13 11:44:26 201613 // Update Count : 3 011 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 6 17:34:46 2016 13 // Update Count : 33 14 14 // 15 15 … … 47 47 class InsertImplicitCalls : public GenPoly::PolyMutator { 48 48 public: 49 /// wrap function application expressions as ImplicitCopyCtorExpr nodes 50 /// so that it is easy to identify which function calls need their parameters 51 /// to be copy constructed 49 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which 50 /// function calls need their parameters to be copy constructed 52 51 static void insert( std::list< Declaration * > & translationUnit ); 53 52 … … 57 56 class ResolveCopyCtors : public SymTab::Indexer { 58 57 public: 59 /// generate temporary ObjectDecls for each argument and return value of each 60 /// ImplicitCopyCtorExpr, generate/resolve copy construction expressions for each,61 /// a nd generate/resolve destructors for both arguments and return value temporaries58 /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr, 59 /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both 60 /// arguments and return value temporaries 62 61 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 63 62 … … 93 92 for ( ObjectDecl * obj : set.objs ) { 94 93 out << obj->get_name() << ", " ; 95 } 94 } // for 96 95 out << " }"; 97 96 return out; … … 108 107 109 108 // xxx - This needs to be done better. 110 // allow some generalization among different kinds of nodes with 111 // with similar parentage (e.g. all expressions, all statements, etc.) 112 // important to have this to provide a single entry point so that as 113 // new subclasses are added, there is only one place that the code has 114 // to be updated, rather than ensure that every specialized class knows 115 // about every new kind of statement that might be added. 109 // allow some generalization among different kinds of nodes with with similar parentage (e.g. all 110 // expressions, all statements, etc.) important to have this to provide a single entry point so that as new 111 // subclasses are added, there is only one place that the code has to be updated, rather than ensure that 112 // every specialized class knows about every new kind of statement that might be added. 116 113 virtual void visit( CompoundStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 117 114 virtual void visit( ExprStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } … … 136 133 class InsertDtors : public ObjDeclCollector { 137 134 public: 138 /// insert destructor calls at the appropriate places. 139 /// must happen before CtorInit nodes are removed(currently by FixInit)135 /// insert destructor calls at the appropriate places. must happen before CtorInit nodes are removed 136 /// (currently by FixInit) 140 137 static void insert( std::list< Declaration * > & translationUnit ); 141 138 … … 168 165 class FixCopyCtors : public GenPoly::PolyMutator { 169 166 public: 170 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, 171 /// call expression,and destructors167 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression, 168 /// and destructors 172 169 static void fixCopyCtors( std::list< Declaration * > &translationUnit ); 173 170 … … 235 232 // assignment operator 236 233 return appExpr; 237 } 234 } // if 238 235 } else if ( funcDecl->get_name() == "^?{}" ) { 239 236 // correctness: never copy construct arguments to a destructor 240 237 return appExpr; 241 } 242 } 243 } 238 } // if 239 } // if 240 } // if 244 241 CP_CTOR_PRINT( std::cerr << "InsertImplicitCalls: adding a wrapper " << appExpr << std::endl; ) 245 242 … … 270 267 271 268 // resolve copy constructor 272 // should only be one alternative for copy ctor and dtor expressions, since 273 // all arguments are fixed(VariableExpr and already resolved expression)269 // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed 270 // (VariableExpr and already resolved expression) 274 271 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 275 272 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 276 273 if ( resolved->get_env() ) { 277 274 env->add( *resolved->get_env() ); 278 } 275 } // if 279 276 280 277 assert( resolved ); … … 319 316 impCpCtorExpr->get_tempDecls().push_back( tmp ); 320 317 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 321 } 322 } 323 324 // each return value from the call needs to be connected with an ObjectDecl 325 // at the call site, which is initialized with the return value and is destructed 326 // later 318 } // if 319 } // for 320 321 // each return value from the call needs to be connected with an ObjectDecl at the call site, which is 322 // initialized with the return value and is destructed later 327 323 // xxx - handle multiple return values 328 324 ApplicationExpr * callExpr = impCpCtorExpr->get_callExpr(); 329 // xxx - is this right? callExpr may not have the right environment, because it was attached 330 // at a higherlevel. Trying to pass that environment along.325 // xxx - is this right? callExpr may not have the right environment, because it was attached at a higher 326 // level. Trying to pass that environment along. 331 327 callExpr->set_env( impCpCtorExpr->get_env()->clone() ); 332 328 for ( Type * result : appExpr->get_results() ) { … … 338 334 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 339 335 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 340 } 336 } // for 341 337 CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; ) 342 338 } … … 356 352 for ( ObjectDecl * obj : tempDecls ) { 357 353 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 358 } 354 } // for 359 355 for ( ObjectDecl * obj : returnDecls ) { 360 356 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 361 } 357 } // for 362 358 363 359 // add destructors after current statement 364 360 for ( Expression * dtor : dtors ) { 365 361 stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) ); 366 } 362 } // for 367 363 368 364 // xxx - update to work with multiple return values … … 390 386 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 391 387 if ( callExpr->get_results().front()->get_isLvalue() ) { 392 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any 393 // lvalue returning non-intrinsic function. Add an AddressExpr to the call to negate 394 // the derefence and change the type of the return temporary from T to T* to properly 395 // capture the return value. Then dereference the result of the comma expression, since 396 // the lvalue returning call was originally wrapped with an AddressExpr. 397 // Effectively, this turns 388 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning 389 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the 390 // type of the return temporary from T to T* to properly capture the return value. Then dereference 391 // the result of the comma expression, since the lvalue returning call was originally wrapped with 392 // an AddressExpr. Effectively, this turns 398 393 // lvalue T f(); 399 394 // &*f() … … 410 405 deref->add_result( resultType ); 411 406 retExpr = deref; 412 } 407 } // if 413 408 // xxx - might need to set env on retExpr... 414 409 // retExpr->set_env( env->clone() ); … … 416 411 } else { 417 412 return callExpr; 418 } 413 } // if 419 414 } 420 415 421 416 DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) { 422 // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors 423 // when the initis removed from the ObjectDecl417 // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors when the init 418 // is removed from the ObjectDecl 424 419 objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) ); 425 420 … … 474 469 } else { 475 470 stmtsToAddAfter.push_back( ctor ); 476 } 471 } // if 477 472 objDecl->set_init( NULL ); 478 473 ctorInit->set_ctor( NULL ); … … 483 478 // no constructor and no initializer, which is okay 484 479 objDecl->set_init( NULL ); 485 } 480 } // if 486 481 delete ctorInit; 487 } 482 } // if 488 483 return objDecl; 489 484 } … … 499 494 if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) { 500 495 curVars.insert( objDecl ); 501 } 496 } // if 502 497 Parent::visit( stmt ); 503 498 } … … 507 502 for ( Label l : stmt->get_labels() ) { 508 503 vars[l] = curVars; 509 } 504 } // for 510 505 } 511 506 … … 513 508 void insertDtors( Iterator begin, Iterator end, OutputIterator out ) { 514 509 for ( Iterator it = begin ; it != end ; ++it ) { 515 // extract destructor statement from the object decl and 516 // insert it into the output. Note that this is only called 517 // on lists of non-static objects with implicit non-intrinsic 518 // dtors, so if the user manually calls an intrinsic dtor 519 // then the call must (and will) still be generated since 520 // the argument may contain side effects. 510 // extract destructor statement from the object decl and insert it into the output. Note that this is 511 // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually 512 // calls an intrinsic dtor then the call must (and will) still be generated since the argument may 513 // contain side effects. 521 514 ObjectDecl * objDecl = *it; 522 515 ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ); 523 516 assert( ctorInit && ctorInit->get_dtor() ); 524 517 *out++ = ctorInit->get_dtor()->clone(); 525 } 518 } // for 526 519 } 527 520 … … 537 530 // non-intrinsic dtors must be called 538 531 reverseDeclOrder.front().push_front( objDecl ); 539 } 540 } 541 } 532 } // if 533 } // if 534 } // if 542 535 Parent::visit( objDecl ); 543 536 } 544 537 545 538 void InsertDtors::visit( CompoundStmt * compoundStmt ) { 546 // visit statements - this will also populate reverseDeclOrder list. 547 // don't want to dump all destructors when block is left, 548 // just the destructors associated with variables defined in this block, 549 // so push a new list to the top of the stack so that we can differentiate scopes 539 // visit statements - this will also populate reverseDeclOrder list. don't want to dump all destructors 540 // when block is left, just the destructors associated with variables defined in this block, so push a new 541 // list to the top of the stack so that we can differentiate scopes 550 542 reverseDeclOrder.push_front( OrderedDecls() ); 551 543 Parent::visit( compoundStmt ); … … 561 553 for ( OrderedDecls & od : reverseDeclOrder ) { 562 554 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAdd ) ); 563 } 564 } 565 566 // Handle break/continue/goto in the same manner as C++. 567 // Basic idea: any objects that are in scope at the BranchStmt 568 // but not at the labelled (target) statement must be destructed. 569 // If there are any objects in scope at the target location but 570 // not at the BranchStmt then those objects would be uninitialized 571 // so notify the user of the error. 572 // See C++ Reference 6.6 Jump Statements for details. 555 } // for 556 } 557 558 // Handle break/continue/goto in the same manner as C++. Basic idea: any objects that are in scope at the 559 // BranchStmt but not at the labelled (target) statement must be destructed. If there are any objects in scope 560 // at the target location but not at the BranchStmt then those objects would be uninitialized so notify the user 561 // of the error. See C++ Reference 6.6 Jump Statements for details. 573 562 void InsertDtors::handleGoto( BranchStmt * stmt ) { 574 563 assert( stmt->get_target() != "" && "BranchStmt missing a label" ); … … 591 580 if ( ! diff.empty() ) { 592 581 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt ); 593 } 582 } // if 594 583 // S_G-S_L results in set of objects that must be destructed 595 584 diff.clear(); … … 604 593 // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order. 605 594 copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return diff.count( objDecl ); } ); 606 } 595 } // for 607 596 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) ); 608 } 597 } // if 609 598 } 610 599 611 600 void InsertDtors::visit( BranchStmt * stmt ) { 612 601 switch( stmt->get_type() ) { 613 case BranchStmt::Continue: 614 case BranchStmt::Break: 615 // could optimize the break/continue case, because the S_L-S_G check 616 // is unnecessary (this set should always be empty), but it serves 617 // as a small sanity check. 618 case BranchStmt::Goto: 619 handleGoto( stmt ); 620 break; 621 default: 622 assert( false ); 623 } 602 case BranchStmt::Continue: 603 case BranchStmt::Break: 604 // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should 605 // always be empty), but it serves as a small sanity check. 606 case BranchStmt::Goto: 607 handleGoto( stmt ); 608 break; 609 default: 610 assert( false ); 611 } // switch 624 612 } 625 613 } // namespace
Note:
See TracChangeset
for help on using the changeset viewer.