Changeset 1f44196 for src/InitTweak
- Timestamp:
- Nov 29, 2016, 3:30:59 PM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, stuck-waitfor-destruct, with_gc
- Children:
- 8e5724e
- Parents:
- 3a2128f (diff), 9129a84 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/InitTweak
- Files:
-
- 4 edited
-
FixInit.cc (modified) (15 diffs)
-
GenInit.cc (modified) (10 diffs)
-
GenInit.h (modified) (2 diffs)
-
InitTweak.cc (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r3a2128f r1f44196 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 51 class InsertImplicitCalls final : public GenPoly::PolyMutator { 53 52 public: … … 67 66 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 68 67 69 using SymTab::Indexer::visit; 68 typedef SymTab::Indexer Parent; 69 using Parent::visit; 70 70 71 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 72 virtual void visit( UniqueExpr * unqExpr ); 71 73 72 74 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) 73 ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 75 Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 76 Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL ); 74 77 /// true if type does not need to be copy constructed to ensure correctness 75 bool skipCopyConstruct( Type * ); 78 bool skipCopyConstruct( Type * type ); 79 void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ); 80 void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ); 76 81 private: 77 82 TypeSubstitution * env; … … 183 188 using GenPoly::PolyMutator::mutate; 184 189 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 190 virtual Expression * mutate( UniqueExpr * unqExpr ) override; 185 191 }; 186 192 … … 368 374 } 369 375 370 ApplicationExpr* ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {376 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { 371 377 assert( var ); 378 return makeCtorDtor( fname, new AddressExpr( new VariableExpr( var ) ), cpArg ); 379 } 380 381 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) { 382 assert( thisArg ); 372 383 UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) ); 373 untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ));384 untyped->get_args().push_back( thisArg ); 374 385 if (cpArg) untyped->get_args().push_back( cpArg->clone() ); 375 386 … … 378 389 // (VariableExpr and already resolved expression) 379 390 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 380 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 391 Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this ); 392 assert( resolved ); 381 393 if ( resolved->get_env() ) { 382 394 env->add( *resolved->get_env() ); 383 395 } // if 384 396 385 assert( resolved );386 397 delete untyped; 387 398 return resolved; 388 399 } 389 400 401 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) { 402 static UniqueName tempNamer("_tmp_cp"); 403 CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; ) 404 assert( arg->has_result() ); 405 Type * result = arg->get_result(); 406 if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types 407 408 // type may involve type variables, so apply type substitution to get temporary variable's actual type 409 result = result->clone(); 410 impCpCtorExpr->get_env()->apply( result ); 411 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 ); 412 tmp->get_type()->set_isConst( false ); 413 414 // create and resolve copy constructor 415 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; ) 416 Expression * cpCtor = makeCtorDtor( "?{}", tmp, arg ); 417 418 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( cpCtor ) ) { 419 // if the chosen constructor is intrinsic, the copy is unnecessary, so 420 // don't create the temporary and don't call the copy constructor 421 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 422 assert( function ); 423 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 424 } 425 426 // replace argument to function call with temporary 427 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 428 impCpCtorExpr->get_tempDecls().push_back( tmp ); 429 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 430 } 431 432 void ResolveCopyCtors::destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) { 433 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( ret ) ) ); 434 } 435 390 436 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) { 391 static UniqueName tempNamer("_tmp_cp");392 static UniqueName retNamer("_tmp_cp_ret");393 394 437 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 395 Visitor::visit( impCpCtorExpr );438 Parent::visit( impCpCtorExpr ); 396 439 env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer... 397 440 … … 400 443 // take each argument and attempt to copy construct it. 401 444 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 445 copyConstructArg( arg, impCpCtorExpr ); 427 446 } // for 428 447 … … 434 453 // level. Trying to pass that environment along. 435 454 callExpr->set_env( impCpCtorExpr->get_env()->clone() ); 436 for ( Type * result : appExpr->get_results() ) { 455 Type * result = appExpr->get_result(); 456 if ( ! result->isVoid() ) { 457 static UniqueName retNamer("_tmp_cp_ret"); 437 458 result = result->clone(); 438 459 impCpCtorExpr->get_env()->apply( result ); … … 441 462 impCpCtorExpr->get_returnDecls().push_back( ret ); 442 463 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 443 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 464 if ( ! result->get_isLvalue() ) { 465 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 466 destructRet( new VariableExpr( ret ), impCpCtorExpr ); 467 } 444 468 } // for 445 469 CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; ) 470 } 471 472 void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) { 473 static std::unordered_set< int > vars; 474 if ( vars.count( unqExpr->get_id() ) ) { 475 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated 476 return; 477 } 478 479 Parent::visit( unqExpr ); 480 // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought 481 assert( unqExpr->get_result() ); 482 if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) { 483 // note the variable used as the result from the call 484 assert( impCpCtorExpr->get_result() && impCpCtorExpr->get_returnDecls().size() == 1 ); 485 unqExpr->set_var( new VariableExpr( impCpCtorExpr->get_returnDecls().front() ) ); 486 } else { 487 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 488 unqExpr->set_object( new ObjectDecl( toString("_unq_expr_", unqExpr->get_id()), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) ); 489 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 490 } 491 vars.insert( unqExpr->get_id() ); 446 492 } 447 493 … … 490 536 // know the result type of the assignment is the type of the LHS (minus the pointer), so 491 537 // add that onto the assignment expression so that later steps have the necessary information 492 assign-> add_result( returnDecl->get_type()->clone() );538 assign->set_result( returnDecl->get_type()->clone() ); 493 539 494 540 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 495 if ( callExpr->get_result s().front()->get_isLvalue() ) {541 if ( callExpr->get_result()->get_isLvalue() ) { 496 542 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning 497 543 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the … … 500 546 // an AddressExpr. Effectively, this turns 501 547 // lvalue T f(); 502 // &*f() 548 // &*f(); 503 549 // into 550 // T * f(); 504 551 // T * tmp_cp_retN; 505 // tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret);552 // &*(tmp_cp_retN = &*f(), tmp_cp_retN); // the first * and second & are generated here 506 553 // which work out in terms of types, but is pretty messy. It would be nice to find a better way. 507 554 assign->get_args().back() = new AddressExpr( assign->get_args().back() ); 508 555 509 Type * resultType = returnDecl->get_type()->clone();510 556 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; 557 retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) ); 558 retExpr = UntypedExpr::createDeref( retExpr ); 515 559 } // if 516 560 retExpr->set_env( env->clone() ); … … 519 563 return callExpr; 520 564 } // if 565 } 566 567 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) { 568 static std::unordered_map< int, UniqueExpr * > unqMap; 569 static std::unordered_set< int > addDeref; 570 // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes 571 unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) ); 572 if ( unqMap.count( unqExpr->get_id() ) ) { 573 // take data from other UniqueExpr to ensure consistency 574 delete unqExpr->get_expr(); 575 unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() ); 576 delete unqExpr->get_result(); 577 unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) ); 578 if ( addDeref.count( unqExpr->get_id() ) ) { 579 // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too 580 return UntypedExpr::createDeref( unqExpr ); 581 } 582 return unqExpr; 583 } 584 unqMap[unqExpr->get_id()] = unqExpr; 585 if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) { 586 // unique expression is now a dereference, because the inner expression is an lvalue returning function call. 587 // Normalize the expression by dereferencing the unique expression, rather than the inner expression 588 // (i.e. move the dereference out a level) 589 assert( getFunctionName( deref ) == "*?" ); 590 unqExpr->set_expr( getCallArg( deref, 0 ) ); 591 getCallArg( deref, 0 ) = unqExpr; 592 addDeref.insert( unqExpr->get_id() ); 593 return deref; 594 } 595 return unqExpr; 521 596 } 522 597 … … 950 1025 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) { 951 1026 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 ); 1027 // xxx - is the size check necessary? 1028 assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 ); 1029 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr ); 954 1030 addDeclaration( tmp ); 955 1031 … … 963 1039 assign->get_args().push_back( new VariableExpr( tmp ) ); 964 1040 assign->get_args().push_back( firstArg ); 965 cloneAll( ctorExpr->get_results(), assign->get_results() );1041 assign->set_result( ctorExpr->get_result()->clone() ); 966 1042 firstArg = assign; 967 1043 -
src/InitTweak/GenInit.cc
r3a2128f r1f44196 29 29 #include "GenPoly/DeclMutator.h" 30 30 #include "GenPoly/ScopedSet.h" 31 #include "ResolvExpr/typeops.h" 31 32 32 33 namespace InitTweak { … … 50 51 51 52 protected: 52 std::list<DeclarationWithType*> returnVals;53 FunctionType * ftype; 53 54 UniqueName tempNamer; 54 55 std::string funcName; … … 86 87 87 88 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed 89 bool isManaged( Type * type ) const; // determine if type is managed 88 90 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor 89 91 GenPoly::ScopedSet< std::string > managedTypes; … … 136 138 137 139 Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) { 138 // update for multiple return values140 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals(); 139 141 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 140 142 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address … … 158 160 159 161 DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) { 160 ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals ); 162 // xxx - need to handle named return values - this pass may need to happen 163 // after resolution? the ordering is tricky because return statements must be 164 // constructed - the simplest way to do that (while also handling multiple 165 // returns) is to structure the returnVals into a tuple, as done here. 166 // however, if the tuple return value is structured before resolution, 167 // it's difficult to resolve named return values, since the name is lost 168 // in conversion to a tuple. this might be easiest to deal with 169 // after reference types are added, as it may then be possible to 170 // uniformly move named return values to the parameter list directly 171 ValueGuard< FunctionType * > oldFtype( ftype ); 161 172 ValueGuard< std::string > oldFuncName( funcName ); 162 173 163 FunctionType * type = functionDecl->get_functionType(); 164 returnVals = type->get_returnVals(); 174 ftype = functionDecl->get_functionType(); 175 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals(); 176 if ( retVals.size() > 1 ) { 177 TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) ); 178 ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) ); 179 retVals.clear(); 180 retVals.push_back( newRet ); 181 } 165 182 funcName = functionDecl->get_name(); 166 183 DeclarationWithType * decl = Mutator::mutate( functionDecl ); … … 222 239 } 223 240 241 bool CtorDtor::isManaged( Type * type ) const { 242 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 243 // tuple is also managed if any of its components are managed 244 if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) { 245 return true; 246 } 247 } 248 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end(); 249 } 250 224 251 bool CtorDtor::isManaged( ObjectDecl * objDecl ) const { 225 252 Type * type = objDecl->get_type(); … … 227 254 type = at->get_base(); 228 255 } 229 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();256 return isManaged( type ); 230 257 } 231 258 … … 238 265 managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) ); 239 266 } 267 } 268 269 ConstructorInit * genCtorInit( ObjectDecl * objDecl ) { 270 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 271 // for each constructable object 272 std::list< Statement * > ctor; 273 std::list< Statement * > dtor; 274 275 InitExpander srcParam( objDecl->get_init() ); 276 InitExpander nullParam( (Initializer *)NULL ); 277 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 278 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 279 280 // Currently genImplicitCall produces a single Statement - a CompoundStmt 281 // which wraps everything that needs to happen. As such, it's technically 282 // possible to use a Statement ** in the above calls, but this is inherently 283 // unsafe, so instead we take the slightly less efficient route, but will be 284 // immediately informed if somehow the above assumption is broken. In this case, 285 // we could always wrap the list of statements at this point with a CompoundStmt, 286 // but it seems reasonable at the moment for this to be done by genImplicitCall 287 // itself. It is possible that genImplicitCall produces no statements (e.g. if 288 // an array type does not have a dimension). In this case, it's fine to ignore 289 // the object for the purposes of construction. 290 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 291 if ( ctor.size() == 1 ) { 292 // need to remember init expression, in case no ctors exist 293 // if ctor does exist, want to use ctor expression instead of init 294 // push this decision to the resolver 295 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 296 return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ); 297 } 298 return nullptr; 240 299 } 241 300 … … 250 309 if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl ); 251 310 252 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor 253 // for each constructable object 254 std::list< Statement * > ctor; 255 std::list< Statement * > dtor; 256 257 InitExpander srcParam( objDecl->get_init() ); 258 InitExpander nullParam( (Initializer *)NULL ); 259 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 260 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 261 262 // Currently genImplicitCall produces a single Statement - a CompoundStmt 263 // which wraps everything that needs to happen. As such, it's technically 264 // possible to use a Statement ** in the above calls, but this is inherently 265 // unsafe, so instead we take the slightly less efficient route, but will be 266 // immediately informed if somehow the above assumption is broken. In this case, 267 // we could always wrap the list of statements at this point with a CompoundStmt, 268 // but it seems reasonable at the moment for this to be done by genImplicitCall 269 // itself. It is possible that genImplicitCall produces no statements (e.g. if 270 // an array type does not have a dimension). In this case, it's fine to ignore 271 // the object for the purposes of construction. 272 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 273 if ( ctor.size() == 1 ) { 274 // need to remember init expression, in case no ctors exist 275 // if ctor does exist, want to use ctor expression instead of init 276 // push this decision to the resolver 277 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 278 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 279 } 311 objDecl->set_init( genCtorInit( objDecl ) ); 280 312 } 281 313 return Parent::mutate( objDecl ); … … 290 322 managedTypes.beginScope(); 291 323 // go through assertions and recursively add seen ctor/dtors 292 for ( TypeDecl *tyDecl : functionDecl->get_functionType()->get_forall() ) {324 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) { 293 325 for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) { 294 326 assertion = assertion->acceptMutator( *this ); -
src/InitTweak/GenInit.h
r3a2128f r1f44196 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // RemoveInit.h --7 // GenInit.h -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 27 27 /// Adds return value temporaries and wraps Initializers in ConstructorInit nodes 28 28 void genInit( std::list< Declaration * > & translationUnit ); 29 30 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer 31 ConstructorInit * genCtorInit( ObjectDecl * objDecl ); 29 32 } // namespace 30 33 -
src/InitTweak/InitTweak.cc
r3a2128f r1f44196 340 340 return allofCtorDtor( stmt, []( Expression * callExpr ){ 341 341 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 342 assert( ! appExpr->get_function()->get_results().empty() ); 343 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() ); 342 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_result() ); 344 343 assert( funcType ); 345 344 return funcType->get_parameters().size() == 1; … … 388 387 return memberExpr->get_member()->get_name(); 389 388 } else if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * > ( func ) ) { 390 return memberExpr->get_member();389 return funcName( memberExpr->get_member() ); 391 390 } else { 392 391 assertf( false, "Unexpected expression type being called as a function in call expression" ); … … 451 450 // virtual void visit( LogicalExpr *logicalExpr ); 452 451 // virtual void visit( ConditionalExpr *conditionalExpr ); 453 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }454 virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }455 452 virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; } 456 453 virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; } 457 454 virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; } 458 455 virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; } 456 virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; } 457 virtual void visit( TupleAssignExpr *tupleExpr ) { isConstExpr = false; } 459 458 460 459 bool isConstExpr;
Note:
See TracChangeset
for help on using the changeset viewer.