Changes in src/InitTweak/FixInit.cc [62e5546:141b786]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r62e5546 r141b786 18 18 #include <iterator> 19 19 #include <algorithm> 20 #include <unordered_map> 21 #include <unordered_set> 20 22 #include "InitTweak.h" 21 23 #include "FixInit.h" … … 35 37 #include "GenPoly/DeclMutator.h" 36 38 #include "SynTree/AddStmtVisitor.h" 37 #include "CodeGen/GenType.h" // for warning s38 39 bool ctordtorp = false; 40 bool ctorp = false; 41 bool cpctorp = false; 42 bool dtorp = false; 39 #include "CodeGen/GenType.h" // for warning/error messages 40 41 bool ctordtorp = false; // print all debug 42 bool ctorp = false; // print ctor debug 43 bool cpctorp = false; // print copy ctor debug 44 bool dtorp = false; // print dtor debug 43 45 #define PRINT( text ) if ( ctordtorp ) { text } 44 46 #define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text } … … 47 49 namespace InitTweak { 48 50 namespace { 49 const std::list<Label> noLabels; 50 const std::list<Expression*> noDesignators; 51 52 class InsertImplicitCalls final : public GenPoly::PolyMutator { 51 class InsertImplicitCalls : public GenPoly::PolyMutator { 53 52 public: 54 53 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which … … 56 55 static void insert( std::list< Declaration * > & translationUnit ); 57 56 58 using GenPoly::PolyMutator::mutate; 59 virtual Expression * mutate( ApplicationExpr * appExpr ) override; 57 virtual Expression * mutate( ApplicationExpr * appExpr ); 60 58 }; 61 59 62 class ResolveCopyCtors final: public SymTab::Indexer {60 class ResolveCopyCtors : public SymTab::Indexer { 63 61 public: 64 62 /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr, … … 67 65 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 68 66 69 using SymTab::Indexer::visit; 70 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 67 typedef SymTab::Indexer Parent; 68 using Parent::visit; 69 70 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 71 virtual void visit( UniqueExpr * unqExpr ); 71 72 72 73 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) 73 ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 74 Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 75 Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL ); 74 76 /// true if type does not need to be copy constructed to ensure correctness 75 bool skipCopyConstruct( Type * ); 77 bool skipCopyConstruct( Type * type ); 78 void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ); 79 void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ); 76 80 private: 77 81 TypeSubstitution * env; … … 84 88 using Parent::visit; 85 89 typedef std::set< ObjectDecl * > ObjectSet; 86 virtual void visit( CompoundStmt *compoundStmt ) override;87 virtual void visit( DeclStmt *stmt ) override;90 virtual void visit( CompoundStmt *compoundStmt ); 91 virtual void visit( DeclStmt *stmt ); 88 92 protected: 89 93 ObjectSet curVars; … … 105 109 } 106 110 107 class LabelFinder final: public ObjDeclCollector {111 class LabelFinder : public ObjDeclCollector { 108 112 public: 109 113 typedef ObjDeclCollector Parent; … … 119 123 // subclasses are added, there is only one place that the code has to be updated, rather than ensure that 120 124 // every specialized class knows about every new kind of statement that might be added. 121 using Parent::visit; 122 virtual void visit( CompoundStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 123 virtual void visit( ExprStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 124 virtual void visit( AsmStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 125 virtual void visit( IfStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 126 virtual void visit( WhileStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 127 virtual void visit( ForStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 128 virtual void visit( SwitchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 129 virtual void visit( CaseStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 130 virtual void visit( BranchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 131 virtual void visit( ReturnStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 132 virtual void visit( TryStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 133 virtual void visit( CatchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 134 virtual void visit( FinallyStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 135 virtual void visit( NullStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 136 virtual void visit( DeclStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 137 virtual void visit( ImplicitCtorDtorStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 125 virtual void visit( CompoundStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 126 virtual void visit( ExprStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 127 virtual void visit( AsmStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 128 virtual void visit( IfStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 129 virtual void visit( WhileStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 130 virtual void visit( ForStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 131 virtual void visit( SwitchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 132 virtual void visit( CaseStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 133 virtual void visit( BranchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 134 virtual void visit( ReturnStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 135 virtual void visit( TryStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 136 virtual void visit( CatchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 137 virtual void visit( FinallyStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 138 virtual void visit( NullStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 139 virtual void visit( DeclStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 140 virtual void visit( ImplicitCtorDtorStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 138 141 }; 139 142 140 class InsertDtors final: public ObjDeclCollector {143 class InsertDtors : public ObjDeclCollector { 141 144 public: 142 145 /// insert destructor calls at the appropriate places. must happen before CtorInit nodes are removed … … 150 153 InsertDtors( LabelFinder & finder ) : labelVars( finder.vars ) {} 151 154 152 using Parent::visit; 153 154 virtual void visit( ObjectDecl * objDecl ) override; 155 156 virtual void visit( CompoundStmt * compoundStmt ) override; 157 virtual void visit( ReturnStmt * returnStmt ) override; 158 virtual void visit( BranchStmt * stmt ) override; 155 virtual void visit( ObjectDecl * objDecl ); 156 157 virtual void visit( CompoundStmt * compoundStmt ); 158 virtual void visit( ReturnStmt * returnStmt ); 159 virtual void visit( BranchStmt * stmt ); 159 160 private: 160 161 void handleGoto( BranchStmt * stmt ); … … 164 165 }; 165 166 166 class FixInit final: public GenPoly::PolyMutator {167 class FixInit : public GenPoly::PolyMutator { 167 168 public: 168 169 /// expand each object declaration to use its constructor after it is declared. 169 170 static void fixInitializers( std::list< Declaration * > &translationUnit ); 170 171 171 using GenPoly::PolyMutator::mutate; 172 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ) override; 172 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 173 173 174 174 std::list< Declaration * > staticDtorDecls; 175 175 }; 176 176 177 class FixCopyCtors final: public GenPoly::PolyMutator {177 class FixCopyCtors : public GenPoly::PolyMutator { 178 178 public: 179 179 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression, … … 181 181 static void fixCopyCtors( std::list< Declaration * > &translationUnit ); 182 182 183 using GenPoly::PolyMutator::mutate;184 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;183 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 184 virtual Expression * mutate( UniqueExpr * unqExpr ); 185 185 }; 186 186 187 class GenStructMemberCalls final: public SymTab::Indexer {187 class GenStructMemberCalls : public SymTab::Indexer { 188 188 public: 189 189 typedef Indexer Parent; … … 193 193 static void generate( std::list< Declaration * > & translationUnit ); 194 194 195 using Parent::visit; 196 197 virtual void visit( FunctionDecl * funcDecl ) override; 198 199 virtual void visit( MemberExpr * memberExpr ) override; 200 virtual void visit( ApplicationExpr * appExpr ) override; 195 virtual void visit( FunctionDecl * funcDecl ); 196 197 virtual void visit( MemberExpr * memberExpr ); 198 virtual void visit( ApplicationExpr * appExpr ); 201 199 202 200 SemanticError errors; … … 216 214 // resolve UntypedExprs that are found within newly 217 215 // generated constructor/destructor calls 218 class MutatingResolver final: public Mutator {216 class MutatingResolver : public Mutator { 219 217 public: 220 218 MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {} 221 219 222 using Mutator::mutate; 223 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override; 224 virtual Expression* mutate( UntypedExpr *untypedExpr ) override; 225 226 private: 220 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ); 221 222 virtual Expression* mutate( UntypedExpr *untypedExpr ); 223 private: 227 224 SymTab::Indexer & indexer; 228 225 }; 229 226 230 class FixCtorExprs final: public GenPoly::DeclMutator {227 class FixCtorExprs : public GenPoly::DeclMutator { 231 228 public: 232 229 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 233 230 static void fix( std::list< Declaration * > & translationUnit ); 234 231 235 using GenPoly::DeclMutator::mutate; 236 virtual Expression * mutate( ConstructorExpr * ctorExpr ) override; 232 virtual Expression * mutate( ConstructorExpr * ctorExpr ); 237 233 }; 238 234 } // namespace … … 368 364 } 369 365 370 ApplicationExpr* ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {366 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { 371 367 assert( var ); 368 return makeCtorDtor( fname, new AddressExpr( new VariableExpr( var ) ), cpArg ); 369 } 370 371 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) { 372 assert( thisArg ); 372 373 UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) ); 373 untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ));374 untyped->get_args().push_back( thisArg ); 374 375 if (cpArg) untyped->get_args().push_back( cpArg->clone() ); 375 376 … … 378 379 // (VariableExpr and already resolved expression) 379 380 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 380 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 381 Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this ); 382 assert( resolved ); 381 383 if ( resolved->get_env() ) { 382 384 env->add( *resolved->get_env() ); 383 385 } // if 384 386 385 assert( resolved );386 387 delete untyped; 387 388 return resolved; 388 389 } 389 390 391 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) { 392 static UniqueName tempNamer("_tmp_cp"); 393 CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; ) 394 assert( arg->has_result() ); 395 Type * result = arg->get_result(); 396 if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types 397 398 // type may involve type variables, so apply type substitution to get temporary variable's actual type 399 result = result->clone(); 400 impCpCtorExpr->get_env()->apply( result ); 401 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 ); 402 tmp->get_type()->set_isConst( false ); 403 404 // create and resolve copy constructor 405 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; ) 406 Expression * cpCtor = makeCtorDtor( "?{}", tmp, arg ); 407 408 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( cpCtor ) ) { 409 // if the chosen constructor is intrinsic, the copy is unnecessary, so 410 // don't create the temporary and don't call the copy constructor 411 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 412 assert( function ); 413 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 414 } 415 416 // replace argument to function call with temporary 417 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 418 impCpCtorExpr->get_tempDecls().push_back( tmp ); 419 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 420 } 421 422 void ResolveCopyCtors::destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) { 423 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( ret ) ) ); 424 } 425 390 426 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) { 391 static UniqueName tempNamer("_tmp_cp");392 static UniqueName retNamer("_tmp_cp_ret");393 394 427 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 395 Visitor::visit( impCpCtorExpr );428 Parent::visit( impCpCtorExpr ); 396 429 env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer... 397 430 … … 400 433 // take each argument and attempt to copy construct it. 401 434 for ( Expression * & arg : appExpr->get_args() ) { 402 CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; ) 403 // xxx - need to handle tuple arguments 404 assert( ! arg->get_results().empty() ); 405 Type * result = arg->get_results().front(); 406 if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types 407 // type may involve type variables, so apply type substitution to get temporary variable's actual type 408 result = result->clone(); 409 impCpCtorExpr->get_env()->apply( result ); 410 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 ); 411 tmp->get_type()->set_isConst( false ); 412 413 // create and resolve copy constructor 414 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; ) 415 ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg ); 416 417 // if the chosen constructor is intrinsic, the copy is unnecessary, so 418 // don't create the temporary and don't call the copy constructor 419 VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() ); 420 assert( function ); 421 if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) { 422 // replace argument to function call with temporary 423 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 424 impCpCtorExpr->get_tempDecls().push_back( tmp ); 425 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 426 } // if 435 copyConstructArg( arg, impCpCtorExpr ); 427 436 } // for 428 437 … … 434 443 // level. Trying to pass that environment along. 435 444 callExpr->set_env( impCpCtorExpr->get_env()->clone() ); 436 for ( Type * result : appExpr->get_results() ) { 445 Type * result = appExpr->get_result(); 446 if ( ! result->isVoid() ) { 447 static UniqueName retNamer("_tmp_cp_ret"); 437 448 result = result->clone(); 438 449 impCpCtorExpr->get_env()->apply( result ); … … 441 452 impCpCtorExpr->get_returnDecls().push_back( ret ); 442 453 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 443 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 454 if ( ! result->get_isLvalue() ) { 455 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 456 destructRet( new VariableExpr( ret ), impCpCtorExpr ); 457 } 444 458 } // for 445 459 CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; ) 460 } 461 462 void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) { 463 static std::unordered_set< int > vars; 464 if ( vars.count( unqExpr->get_id() ) ) { 465 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated 466 return; 467 } 468 469 Parent::visit( unqExpr ); 470 // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought 471 assert( unqExpr->get_result() ); 472 if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) { 473 // note the variable used as the result from the call 474 assert( impCpCtorExpr->get_result() && impCpCtorExpr->get_returnDecls().size() == 1 ); 475 unqExpr->set_var( new VariableExpr( impCpCtorExpr->get_returnDecls().front() ) ); 476 } else { 477 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 478 unqExpr->set_object( new ObjectDecl( toString("_unq_expr_", unqExpr->get_id()), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) ); 479 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 480 } 481 vars.insert( unqExpr->get_id() ); 446 482 } 447 483 … … 490 526 // know the result type of the assignment is the type of the LHS (minus the pointer), so 491 527 // add that onto the assignment expression so that later steps have the necessary information 492 assign-> add_result( returnDecl->get_type()->clone() );528 assign->set_result( returnDecl->get_type()->clone() ); 493 529 494 530 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 495 if ( callExpr->get_result s().front()->get_isLvalue() ) {531 if ( callExpr->get_result()->get_isLvalue() ) { 496 532 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning 497 533 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the … … 500 536 // an AddressExpr. Effectively, this turns 501 537 // lvalue T f(); 502 // &*f() 538 // &*f(); 503 539 // into 540 // T * f(); 504 541 // T * tmp_cp_retN; 505 // tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret);542 // &*(tmp_cp_retN = &*f(), tmp_cp_retN); // the first * and second & are generated here 506 543 // which work out in terms of types, but is pretty messy. It would be nice to find a better way. 507 544 assign->get_args().back() = new AddressExpr( assign->get_args().back() ); 508 545 509 Type * resultType = returnDecl->get_type()->clone();510 546 returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) ); 511 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 512 deref->get_args().push_back( retExpr ); 513 deref->add_result( resultType ); 514 retExpr = deref; 547 retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) ); 548 retExpr = UntypedExpr::createDeref( retExpr ); 515 549 } // if 516 550 retExpr->set_env( env->clone() ); … … 519 553 return callExpr; 520 554 } // if 555 } 556 557 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) { 558 static std::unordered_map< int, UniqueExpr * > unqMap; 559 static std::unordered_set< int > addDeref; 560 // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes 561 unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) ); 562 if ( unqMap.count( unqExpr->get_id() ) ) { 563 // take data from other UniqueExpr to ensure consistency 564 delete unqExpr->get_expr(); 565 unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() ); 566 delete unqExpr->get_result(); 567 unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) ); 568 if ( addDeref.count( unqExpr->get_id() ) ) { 569 // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too 570 return UntypedExpr::createDeref( unqExpr ); 571 } 572 return unqExpr; 573 } 574 unqMap[unqExpr->get_id()] = unqExpr; 575 if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) { 576 // unique expression is now a dereference, because the inner expression is an lvalue returning function call. 577 // Normalize the expression by dereferencing the unique expression, rather than the inner expression 578 // (i.e. move the dereference out a level) 579 assert( getFunctionName( deref ) == "*?" ); 580 unqExpr->set_expr( getCallArg( deref, 0 ) ); 581 getCallArg( deref, 0 ) = unqExpr; 582 addDeref.insert( unqExpr->get_id() ); 583 return deref; 584 } 585 return unqExpr; 521 586 } 522 587 … … 950 1015 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) { 951 1016 static UniqueName tempNamer( "_tmp_ctor_expr" ); 952 assert( ctorExpr->get_results().size() == 1 ); 953 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_results().front()->clone(), nullptr ); 1017 // xxx - is the size check necessary? 1018 assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 ); 1019 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr ); 954 1020 addDeclaration( tmp ); 955 1021 … … 963 1029 assign->get_args().push_back( new VariableExpr( tmp ) ); 964 1030 assign->get_args().push_back( firstArg ); 965 cloneAll( ctorExpr->get_results(), assign->get_results() );1031 assign->set_result( ctorExpr->get_result()->clone() ); 966 1032 firstArg = assign; 967 1033
Note:
See TracChangeset
for help on using the changeset viewer.