Changes in src/InitTweak/FixInit.cc [141b786:62e5546]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r141b786 r62e5546 18 18 #include <iterator> 19 19 #include <algorithm> 20 #include <unordered_map>21 #include <unordered_set>22 20 #include "InitTweak.h" 23 21 #include "FixInit.h" … … 37 35 #include "GenPoly/DeclMutator.h" 38 36 #include "SynTree/AddStmtVisitor.h" 39 #include "CodeGen/GenType.h" // for warning /error messages40 41 bool ctordtorp = false; // print all debug42 bool ctorp = false; // print ctor debug43 bool cpctorp = false; // print copy ctor debug44 bool dtorp = false; // print dtor debug37 #include "CodeGen/GenType.h" // for warnings 38 39 bool ctordtorp = false; 40 bool ctorp = false; 41 bool cpctorp = false; 42 bool dtorp = false; 45 43 #define PRINT( text ) if ( ctordtorp ) { text } 46 44 #define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text } … … 49 47 namespace InitTweak { 50 48 namespace { 51 class InsertImplicitCalls : public GenPoly::PolyMutator { 49 const std::list<Label> noLabels; 50 const std::list<Expression*> noDesignators; 51 52 class InsertImplicitCalls final : public GenPoly::PolyMutator { 52 53 public: 53 54 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which … … 55 56 static void insert( std::list< Declaration * > & translationUnit ); 56 57 57 virtual Expression * mutate( ApplicationExpr * appExpr ); 58 }; 59 60 class ResolveCopyCtors : public SymTab::Indexer { 58 using GenPoly::PolyMutator::mutate; 59 virtual Expression * mutate( ApplicationExpr * appExpr ) override; 60 }; 61 62 class ResolveCopyCtors final : public SymTab::Indexer { 61 63 public: 62 64 /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr, … … 65 67 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 66 68 67 typedef SymTab::Indexer Parent; 68 using Parent::visit; 69 70 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 71 virtual void visit( UniqueExpr * unqExpr ); 69 using SymTab::Indexer::visit; 70 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 72 71 73 72 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) 74 Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 75 Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL ); 73 ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 76 74 /// true if type does not need to be copy constructed to ensure correctness 77 bool skipCopyConstruct( Type * type ); 78 void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ); 79 void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ); 75 bool skipCopyConstruct( Type * ); 80 76 private: 81 77 TypeSubstitution * env; … … 88 84 using Parent::visit; 89 85 typedef std::set< ObjectDecl * > ObjectSet; 90 virtual void visit( CompoundStmt *compoundStmt ) ;91 virtual void visit( DeclStmt *stmt ) ;86 virtual void visit( CompoundStmt *compoundStmt ) override; 87 virtual void visit( DeclStmt *stmt ) override; 92 88 protected: 93 89 ObjectSet curVars; … … 109 105 } 110 106 111 class LabelFinder : public ObjDeclCollector {107 class LabelFinder final : public ObjDeclCollector { 112 108 public: 113 109 typedef ObjDeclCollector Parent; … … 123 119 // subclasses are added, there is only one place that the code has to be updated, rather than ensure that 124 120 // every specialized class knows about every new kind of statement that might be added. 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 ); } 141 }; 142 143 class InsertDtors : public ObjDeclCollector { 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 ); } 138 }; 139 140 class InsertDtors final : public ObjDeclCollector { 144 141 public: 145 142 /// insert destructor calls at the appropriate places. must happen before CtorInit nodes are removed … … 153 150 InsertDtors( LabelFinder & finder ) : labelVars( finder.vars ) {} 154 151 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 ); 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; 160 159 private: 161 160 void handleGoto( BranchStmt * stmt ); … … 165 164 }; 166 165 167 class FixInit : public GenPoly::PolyMutator {166 class FixInit final : public GenPoly::PolyMutator { 168 167 public: 169 168 /// expand each object declaration to use its constructor after it is declared. 170 169 static void fixInitializers( std::list< Declaration * > &translationUnit ); 171 170 172 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 171 using GenPoly::PolyMutator::mutate; 172 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ) override; 173 173 174 174 std::list< Declaration * > staticDtorDecls; 175 175 }; 176 176 177 class FixCopyCtors : public GenPoly::PolyMutator {177 class FixCopyCtors final : 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 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );184 virtual Expression * mutate( UniqueExpr * unqExpr );185 }; 186 187 class GenStructMemberCalls : public SymTab::Indexer {183 using GenPoly::PolyMutator::mutate; 184 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 185 }; 186 187 class GenStructMemberCalls final : public SymTab::Indexer { 188 188 public: 189 189 typedef Indexer Parent; … … 193 193 static void generate( std::list< Declaration * > & translationUnit ); 194 194 195 virtual void visit( FunctionDecl * funcDecl ); 196 197 virtual void visit( MemberExpr * memberExpr ); 198 virtual void visit( ApplicationExpr * appExpr ); 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; 199 201 200 202 SemanticError errors; … … 214 216 // resolve UntypedExprs that are found within newly 215 217 // generated constructor/destructor calls 216 class MutatingResolver : public Mutator {218 class MutatingResolver final : public Mutator { 217 219 public: 218 220 MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {} 219 221 220 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ); 221 222 virtual Expression* mutate( UntypedExpr *untypedExpr ); 223 private: 222 using Mutator::mutate; 223 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override; 224 virtual Expression* mutate( UntypedExpr *untypedExpr ) override; 225 226 private: 224 227 SymTab::Indexer & indexer; 225 228 }; 226 229 227 class FixCtorExprs : public GenPoly::DeclMutator {230 class FixCtorExprs final : public GenPoly::DeclMutator { 228 231 public: 229 232 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 230 233 static void fix( std::list< Declaration * > & translationUnit ); 231 234 232 virtual Expression * mutate( ConstructorExpr * ctorExpr ); 235 using GenPoly::DeclMutator::mutate; 236 virtual Expression * mutate( ConstructorExpr * ctorExpr ) override; 233 237 }; 234 238 } // namespace … … 364 368 } 365 369 366 Expression* ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {370 ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { 367 371 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 );373 372 UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) ); 374 untyped->get_args().push_back( thisArg);373 untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) ); 375 374 if (cpArg) untyped->get_args().push_back( cpArg->clone() ); 376 375 … … 379 378 // (VariableExpr and already resolved expression) 380 379 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 381 Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this ); 382 assert( resolved ); 380 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 383 381 if ( resolved->get_env() ) { 384 382 env->add( *resolved->get_env() ); 385 383 } // if 386 384 385 assert( resolved ); 387 386 delete untyped; 388 387 return resolved; 389 388 } 390 389 391 void ResolveCopyCtors:: copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr *impCpCtorExpr ) {390 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) { 392 391 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 ) ) { 392 static UniqueName retNamer("_tmp_cp_ret"); 393 394 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 395 Visitor::visit( impCpCtorExpr ); 396 env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer... 397 398 ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr(); 399 400 // take each argument and attempt to copy construct it. 401 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 409 417 // if the chosen constructor is intrinsic, the copy is unnecessary, so 410 418 // don't create the temporary and don't call the copy constructor 411 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );419 VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() ); 412 420 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 426 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) { 427 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 428 Parent::visit( impCpCtorExpr ); 429 env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer... 430 431 ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr(); 432 433 // take each argument and attempt to copy construct it. 434 for ( Expression * & arg : appExpr->get_args() ) { 435 copyConstructArg( arg, impCpCtorExpr ); 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 436 427 } // for 437 428 … … 443 434 // level. Trying to pass that environment along. 444 435 callExpr->set_env( impCpCtorExpr->get_env()->clone() ); 445 Type * result = appExpr->get_result(); 446 if ( ! result->isVoid() ) { 447 static UniqueName retNamer("_tmp_cp_ret"); 436 for ( Type * result : appExpr->get_results() ) { 448 437 result = result->clone(); 449 438 impCpCtorExpr->get_env()->apply( result ); … … 452 441 impCpCtorExpr->get_returnDecls().push_back( ret ); 453 442 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 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 } 443 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 458 444 } // for 459 445 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 generated466 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 rethought471 assert( unqExpr->get_result() );472 if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) {473 // note the variable used as the result from the call474 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 expression478 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() );482 446 } 483 447 … … 526 490 // know the result type of the assignment is the type of the LHS (minus the pointer), so 527 491 // add that onto the assignment expression so that later steps have the necessary information 528 assign-> set_result( returnDecl->get_type()->clone() );492 assign->add_result( returnDecl->get_type()->clone() ); 529 493 530 494 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 531 if ( callExpr->get_result ()->get_isLvalue() ) {495 if ( callExpr->get_results().front()->get_isLvalue() ) { 532 496 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning 533 497 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the … … 536 500 // an AddressExpr. Effectively, this turns 537 501 // lvalue T f(); 538 // &*f() ;502 // &*f() 539 503 // into 540 // T * f();541 504 // T * tmp_cp_retN; 542 // &*(tmp_cp_retN = &*f(), tmp_cp_retN); // the first * and second & are generated here505 // tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret); 543 506 // which work out in terms of types, but is pretty messy. It would be nice to find a better way. 544 507 assign->get_args().back() = new AddressExpr( assign->get_args().back() ); 545 508 509 Type * resultType = returnDecl->get_type()->clone(); 546 510 returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) ); 547 retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) ); 548 retExpr = UntypedExpr::createDeref( retExpr ); 511 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 512 deref->get_args().push_back( retExpr ); 513 deref->add_result( resultType ); 514 retExpr = deref; 549 515 } // if 550 516 retExpr->set_env( env->clone() ); … … 553 519 return callExpr; 554 520 } // 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 passes561 unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) );562 if ( unqMap.count( unqExpr->get_id() ) ) {563 // take data from other UniqueExpr to ensure consistency564 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 too570 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 expression578 // (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;586 521 } 587 522 … … 1015 950 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) { 1016 951 static UniqueName tempNamer( "_tmp_ctor_expr" ); 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 ); 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 ); 1020 954 addDeclaration( tmp ); 1021 955 … … 1029 963 assign->get_args().push_back( new VariableExpr( tmp ) ); 1030 964 assign->get_args().push_back( firstArg ); 1031 assign->set_result( ctorExpr->get_result()->clone() );965 cloneAll( ctorExpr->get_results(), assign->get_results() ); 1032 966 firstArg = assign; 1033 967
Note:
See TracChangeset
for help on using the changeset viewer.