Changeset 3f7e12cb for src/InitTweak
- Timestamp:
- Nov 8, 2017, 5:43:33 PM (8 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:
- 954908d
- Parents:
- 78315272 (diff), e35f30a (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:
-
- 5 edited
-
FixInit.cc (modified) (38 diffs)
-
GenInit.cc (modified) (19 diffs)
-
GenInit.h (modified) (2 diffs)
-
InitTweak.cc (modified) (14 diffs)
-
InitTweak.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r78315272 r3f7e12cb 36 36 #include "FixGlobalInit.h" // for fixGlobalInit 37 37 #include "GenInit.h" // for genCtorDtor 38 #include "GenPoly/DeclMutator.h" // for DeclMutator39 38 #include "GenPoly/GenPoly.h" // for getFunctionType 40 #include "GenPoly/PolyMutator.h" // for PolyMutator41 39 #include "InitTweak.h" // for getFunctionName, getCallArg 42 40 #include "Parser/LinkageSpec.h" // for C, Spec, Cforall, isBuiltin … … 46 44 #include "SymTab/Indexer.h" // for Indexer 47 45 #include "SymTab/Mangler.h" // for Mangler 48 #include "SynTree/AddStmtVisitor.h" // for AddStmtVisitor49 46 #include "SynTree/Attribute.h" // for Attribute 50 47 #include "SynTree/Constant.h" // for Constant … … 58 55 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution, operator<< 59 56 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 60 #include "Tuples/Tuples.h" // for isTtype61 57 62 58 bool ctordtorp = false; // print all debug … … 97 93 /// true if type does not need to be copy constructed to ensure correctness 98 94 bool skipCopyConstruct( Type * type ); 99 void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );95 void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ); 100 96 void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr ); 101 97 … … 187 183 }; 188 184 189 class FixCopyCtors final : public GenPoly::PolyMutator{185 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> { 190 186 public: 191 187 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} … … 194 190 static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount ); 195 191 196 typedef GenPoly::PolyMutator Parent; 197 using Parent::mutate; 198 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 199 virtual Expression * mutate( UniqueExpr * unqExpr ) override; 200 virtual Expression * mutate( StmtExpr * stmtExpr ) override; 192 Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 193 void premutate( StmtExpr * stmtExpr ); 194 void premutate( UniqueExpr * unqExpr ); 201 195 202 196 UnqCount & unqCount; … … 220 214 void emit( CodeLocation, const Params &... params ); 221 215 222 FunctionDecl * function = 0;216 FunctionDecl * function = nullptr; 223 217 std::set< DeclarationWithType * > unhandled; 224 218 std::map< DeclarationWithType *, CodeLocation > usedUninit; 225 ObjectDecl * thisParam = 0;219 ObjectDecl * thisParam = nullptr; 226 220 bool isCtor = false; // true if current function is a constructor 227 StructDecl * structDecl = 0;221 StructDecl * structDecl = nullptr; 228 222 }; 229 223 … … 243 237 }; 244 238 245 class FixCtorExprs final : public GenPoly::DeclMutator { 246 public: 239 struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer { 247 240 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 248 241 static void fix( std::list< Declaration * > & translationUnit ); 249 242 250 using GenPoly::DeclMutator::mutate; 251 virtual Expression * mutate( ConstructorExpr * ctorExpr ) override; 243 Expression * postmutate( ConstructorExpr * ctorExpr ); 252 244 }; 253 245 } // namespace … … 268 260 269 261 GenStructMemberCalls::generate( translationUnit ); 262 270 263 // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a 271 264 // hack in the way untyped assignments are generated, where the first argument cannot have … … 297 290 for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 298 291 try { 299 *i =maybeMutate( *i, fixer );292 maybeMutate( *i, fixer ); 300 293 translationUnit.splice( i, fixer.pass.staticDtorDecls ); 301 294 } catch( SemanticError &e ) { … … 316 309 317 310 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) { 318 FixCopyCtorsfixer( unqCount );311 PassVisitor<FixCopyCtors> fixer( unqCount ); 319 312 mutateAll( translationUnit, fixer ); 320 313 } … … 326 319 327 320 void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) { 328 FixCtorExprsfixer;329 fixer.mutateDeclarationList( translationUnit);321 PassVisitor<FixCtorExprs> fixer; 322 mutateAll( translationUnit, fixer ); 330 323 } 331 324 332 325 Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) { 333 assert( appExpr );334 335 326 if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) { 336 if ( LinkageSpec::isBuiltin( function->get_var()->get_linkage() )) {327 if ( function->var->linkage.is_builtin ) { 337 328 // optimization: don't need to copy construct in order to call intrinsic functions 338 329 return appExpr; 339 330 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 340 331 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 341 assert ( ftype);342 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype-> get_parameters().size() == 2 ) {343 Type * t1 = getPointerBase( ftype-> get_parameters().front()->get_type() );344 Type * t2 = ftype-> get_parameters().back()->get_type();332 assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() ); 333 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->parameters.size() == 2 ) { 334 Type * t1 = getPointerBase( ftype->parameters.front()->get_type() ); 335 Type * t2 = ftype->parameters.back()->get_type(); 345 336 assert( t1 ); 346 337 … … 368 359 } 369 360 370 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 371 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type ); 372 } 361 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); } 373 362 374 363 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { … … 377 366 ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg ); 378 367 ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() ); 379 Expression * untyped = exprStmt->get_expr(); 368 Expression * resolved = exprStmt->expr; 369 exprStmt->expr = nullptr; // take ownership of expr 380 370 381 371 // resolve copy constructor 382 372 // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed 383 373 // (VariableExpr and already resolved expression) 384 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )385 Expression * resolved = ResolvExpr::findVoidExpression( untyped, indexer );374 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << resolved << std::endl; ) 375 ResolvExpr::findVoidExpression( resolved, indexer ); 386 376 assert( resolved ); 387 377 if ( resolved->get_env() ) { … … 391 381 resolved->set_env( nullptr ); 392 382 } // if 393 394 383 delete stmt; 395 384 return resolved; 396 385 } 397 386 398 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {387 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) { 399 388 static UniqueName tempNamer("_tmp_cp"); 400 389 assert( env ); 401 390 CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; ) 402 assert( arg-> has_result());403 Type * result = arg-> get_result();391 assert( arg->result ); 392 Type * result = arg->result; 404 393 if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types 405 394 406 // type may involve type variables, so apply type substitution to get temporary variable's actual type 395 // type may involve type variables, so apply type substitution to get temporary variable's actual type. 396 // Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T). 407 397 result = result->clone(); 408 env->apply ( result );409 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);398 env->applyFree( result ); 399 ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr ); 410 400 tmp->get_type()->set_const( false ); 411 401 … … 417 407 // if the chosen constructor is intrinsic, the copy is unnecessary, so 418 408 // don't create the temporary and don't call the copy constructor 419 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 420 assert( function ); 421 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 422 } 409 VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function ); 410 if ( function->var->linkage == LinkageSpec::Intrinsic ) { 411 // arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic, 412 // so that the object isn't changed inside of the polymorphic function 413 if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return; 414 } 415 } 416 417 // set a unique name for the temporary once it's certain the call is necessary 418 tmp->name = tempNamer.newName(); 423 419 424 420 // replace argument to function call with temporary 425 421 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 426 impCpCtorExpr-> get_tempDecls().push_back( tmp );427 impCpCtorExpr-> get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );422 impCpCtorExpr->tempDecls.push_back( tmp ); 423 impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) ); 428 424 } 429 425 … … 435 431 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 436 432 437 ApplicationExpr * appExpr = impCpCtorExpr-> get_callExpr();433 ApplicationExpr * appExpr = impCpCtorExpr->callExpr; 438 434 439 435 // take each argument and attempt to copy construct it. 440 for ( Expression * & arg : appExpr->get_args() ) { 441 copyConstructArg( arg, impCpCtorExpr ); 436 FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result ); 437 assert( ftype ); 438 auto & params = ftype->parameters; 439 auto iter = params.begin(); 440 for ( Expression * & arg : appExpr->args ) { 441 Type * formal = nullptr; 442 if ( iter != params.end() ) { 443 DeclarationWithType * param = *iter++; 444 formal = param->get_type(); 445 } 446 447 copyConstructArg( arg, impCpCtorExpr, formal ); 442 448 } // for 443 449 … … 445 451 // initialized with the return value and is destructed later 446 452 // xxx - handle named return values? 447 Type * result = appExpr-> get_result();453 Type * result = appExpr->result; 448 454 if ( ! result->isVoid() ) { 449 455 static UniqueName retNamer("_tmp_cp_ret"); 450 456 result = result->clone(); 451 457 env->apply( result ); 452 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);453 ret-> get_type()->set_const( false );454 impCpCtorExpr-> get_returnDecls().push_back( ret );458 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 459 ret->type->set_const( false ); 460 impCpCtorExpr->returnDecls.push_back( ret ); 455 461 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 456 462 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 457 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary463 // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 458 464 destructRet( ret, impCpCtorExpr ); 459 465 } … … 472 478 result = result->clone(); 473 479 env->apply( result ); 474 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);480 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 475 481 ret->get_type()->set_const( false ); 476 482 stmtExpr->get_returnDecls().push_front( ret ); … … 493 499 visit_children = false; 494 500 } 501 } 502 503 // to prevent warnings (‘_unq0’ may be used uninitialized in this function), 504 // insert an appropriate zero initializer for UniqueExpr temporaries. 505 Initializer * makeInit( Type * t ) { 506 if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) { 507 // initizer for empty struct must be empty 508 if ( inst->baseStruct->members.empty() ) return new ListInit({}); 509 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) { 510 // initizer for empty union must be empty 511 if ( inst->baseUnion->members.empty() ) return new ListInit({}); 512 } 513 514 return new ListInit( { new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) } ); 495 515 } 496 516 … … 509 529 } else { 510 530 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 511 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr) );531 unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), makeInit( unqExpr->get_result() ) ) ); 512 532 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 513 533 } … … 515 535 } 516 536 517 Expression * FixCopyCtors:: mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {537 Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) { 518 538 CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 519 539 520 impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );521 540 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls(); 522 541 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls(); … … 525 544 // add all temporary declarations and their constructors 526 545 for ( ObjectDecl * obj : tempDecls ) { 527 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );546 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 528 547 } // for 529 548 for ( ObjectDecl * obj : returnDecls ) { 530 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );549 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 531 550 } // for 532 551 … … 536 555 } // for 537 556 538 // xxx - update to work with multiple return values539 557 ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front(); 540 558 Expression * callExpr = impCpCtorExpr->get_callExpr(); … … 561 579 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 562 580 // move env from callExpr to retExpr 563 retExpr->set_env( callExpr->get_env() ); 564 callExpr->set_env( nullptr ); 581 std::swap( retExpr->env, callExpr->env ); 565 582 return retExpr; 566 583 } else { … … 569 586 } 570 587 571 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {588 void FixCopyCtors::premutate( StmtExpr * stmtExpr ) { 572 589 // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression, 573 590 // since temporaries can be shared across sub-expressions, e.g. 574 591 // [A, A] f(); 575 592 // g([A] x, [A] y); 576 // f(g());593 // g(f()); 577 594 // f is executed once, so the return temporary is shared across the tuple constructors for x and y. 595 // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added 596 // to the outer context, rather than inside of the statement expression. 597 visit_children = false; 578 598 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids(); 579 599 for ( Statement *& stmt : stmts ) { 580 stmt = stmt->acceptMutator( * this);600 stmt = stmt->acceptMutator( *visitor ); 581 601 } // for 582 // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );583 602 assert( stmtExpr->get_result() ); 584 603 Type * result = stmtExpr->get_result(); 585 604 if ( ! result->isVoid() ) { 586 605 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) { 587 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );606 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 588 607 } // for 589 608 // add destructors after current statement … … 592 611 } // for 593 612 // must have a non-empty body, otherwise it wouldn't have a result 594 CompoundStmt * body = stmtExpr->get_statements(); 595 assert( ! body->get_kids().empty() ); 613 assert( ! stmts.empty() ); 596 614 assert( ! stmtExpr->get_returnDecls().empty() ); 597 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );615 stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) ); 598 616 stmtExpr->get_returnDecls().clear(); 599 617 stmtExpr->get_dtors().clear(); … … 601 619 assert( stmtExpr->get_returnDecls().empty() ); 602 620 assert( stmtExpr->get_dtors().empty() ); 603 return stmtExpr;604 } 605 606 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {621 } 622 623 void FixCopyCtors::premutate( UniqueExpr * unqExpr ) { 624 visit_children = false; 607 625 unqCount[ unqExpr->get_id() ]--; 608 626 static std::unordered_map< int, std::list< Statement * > > dtors; 609 627 static std::unordered_map< int, UniqueExpr * > unqMap; 610 static std::unordered_set< int > addDeref;611 628 // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes 612 629 if ( unqMap.count( unqExpr->get_id() ) ) { … … 619 636 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 620 637 } 621 if ( addDeref.count( unqExpr->get_id() ) ) { 622 // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too 623 return UntypedExpr::createDeref( unqExpr ); 624 } 625 return unqExpr; 626 } 627 FixCopyCtors fixer( unqCount ); 638 return; 639 } 640 PassVisitor<FixCopyCtors> fixer( unqCount ); 628 641 unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup 629 stmtsToAdd .splice( stmtsToAdd.end(), fixer.stmtsToAdd);642 stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore ); 630 643 unqMap[unqExpr->get_id()] = unqExpr; 631 644 if ( unqCount[ unqExpr->get_id() ] == 0 ) { // insert destructor after the last use of the unique expression 632 645 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 633 646 } else { // remember dtors for last instance of unique expr 634 dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter; 635 } 636 if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) { 637 // unique expression is now a dereference, because the inner expression is an lvalue returning function call. 638 // Normalize the expression by dereferencing the unique expression, rather than the inner expression 639 // (i.e. move the dereference out a level) 640 assert( getFunctionName( deref ) == "*?" ); 641 unqExpr->set_expr( getCallArg( deref, 0 ) ); 642 getCallArg( deref, 0 ) = unqExpr; 643 addDeref.insert( unqExpr->get_id() ); 644 return deref; 645 } 646 return unqExpr; 647 } 648 649 DeclarationWithType *FixInit::postmutate( ObjectDecl *objDecl ) { 647 dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter; 648 } 649 return; 650 } 651 652 DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) { 650 653 // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate) 651 654 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { … … 745 748 } else { 746 749 ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * > ( ctor ); 747 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit-> get_callStmt());750 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->callStmt ); 748 751 ApplicationExpr * ctorCall = nullptr; 749 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt-> get_expr())) && ctorCall->get_args().size() == 2 ) {752 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->get_args().size() == 2 ) { 750 753 // clean up intrinsic copy constructor calls by making them into SingleInits 751 objDecl->set_init( new SingleInit( ctorCall->get_args().back() ) ); 752 ctorCall->get_args().pop_back(); 754 Expression * ctorArg = ctorCall->args.back(); 755 std::swap( ctorArg->env, ctorCall->env ); 756 objDecl->init = new SingleInit( ctorArg ); 757 758 ctorCall->args.pop_back(); 753 759 } else { 754 760 stmtsToAddAfter.push_back( ctor ); 755 objDecl-> set_init( nullptr );756 ctorInit-> set_ctor( nullptr );761 objDecl->init = nullptr; 762 ctorInit->ctor = nullptr; 757 763 } 758 764 } // if 759 } else if ( Initializer * init = ctorInit-> get_init()) {760 objDecl-> set_init( init );761 ctorInit-> set_init( nullptr );765 } else if ( Initializer * init = ctorInit->init ) { 766 objDecl->init = init; 767 ctorInit->init = nullptr; 762 768 } else { 763 769 // no constructor and no initializer, which is okay 764 objDecl-> set_init( nullptr );770 objDecl->init = nullptr; 765 771 } // if 766 772 delete ctorInit; … … 819 825 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 820 826 Statement * dtor = ctorInit->get_dtor(); 827 // don't need to call intrinsic dtor, because it does nothing, but 828 // non-intrinsic dtors must be called 821 829 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 822 // don't need to call intrinsic dtor, because it does nothing, but823 // non-intrinsic dtors must be called830 // set dtor location to the object's location for error messages 831 ctorInit->dtor->location = objDecl->location; 824 832 reverseDeclOrder.front().push_front( objDecl ); 825 833 } // if … … 832 840 GuardValue( labelVars ); 833 841 labelVars.clear(); 842 // LabelFinder does not recurse into FunctionDecl, so need to visit 843 // its children manually. 834 844 maybeAccept( funcDecl->type, finder ); 835 845 maybeAccept( funcDecl->statements, finder ); … … 933 943 } 934 944 945 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) { 946 for ( auto d : decls ) { 947 indexer.addId( d ); 948 } 949 } 950 951 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) { 952 for ( auto td : tds ) { 953 indexer.addType( td ); 954 addIds( indexer, td->assertions ); 955 } 956 } 957 935 958 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) { 936 GuardValue( func Decl);959 GuardValue( function ); 937 960 GuardValue( unhandled ); 938 961 GuardValue( usedUninit ); … … 967 990 } 968 991 969 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {970 for ( auto d : decls ) {971 indexer.addId( d );972 }973 }974 975 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {976 for ( auto td : tds ) {977 indexer.addType( td );978 addIds( indexer, td->assertions );979 }980 }981 982 992 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) { 983 993 // remove the unhandled objects from usedUninit, because a call is inserted … … 1012 1022 // skip non-DWT members 1013 1023 if ( ! field ) continue; 1024 // skip non-constructable members 1025 if ( ! tryConstruct( field ) ) continue; 1014 1026 // skip handled members 1015 1027 if ( ! unhandled.count( field ) ) continue; … … 1130 1142 } 1131 1143 1132 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {1144 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) { 1133 1145 // add object to the indexer assumes that there will be no name collisions 1134 1146 // in generated code. If this changes, add mutate methods for entities with … … 1138 1150 } 1139 1151 1140 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) { 1141 return strict_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) ); 1142 } 1143 1144 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) { 1152 Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) { 1153 Expression * newExpr = untypedExpr; 1154 ResolvExpr::findVoidExpression( newExpr, indexer ); 1155 return newExpr; 1156 } 1157 1158 Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) { 1145 1159 static UniqueName tempNamer( "_tmp_ctor_expr" ); 1146 1160 // xxx - is the size check necessary? 1147 assert( ctorExpr-> has_result()&& ctorExpr->get_result()->size() == 1 );1161 assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 ); 1148 1162 1149 1163 // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary. 1150 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );1151 addDeclaration( tmp );1164 ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr ); 1165 declsToAddBefore.push_back( tmp ); 1152 1166 1153 1167 // xxx - this can be TupleAssignExpr now. Need to properly handle this case. … … 1158 1172 delete ctorExpr; 1159 1173 1174 // build assignment and replace constructor's first argument with new temporary 1160 1175 Expression *& firstArg = callExpr->get_args().front(); 1161 1162 // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away. 1163 1164 // generate the type of assignment operator using the type of tmp minus any reference types 1165 Type * type = tmp->get_type()->stripReferences(); 1166 FunctionType * ftype = SymTab::genAssignType( type ); 1167 1168 // generate fake assignment decl and call it using &tmp and &firstArg 1169 // since tmp is guaranteed to be a reference and we want to assign pointers 1170 FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr ); 1171 ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) ); 1172 assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) ); 1173 Expression * addrArg = new AddressExpr( firstArg ); 1174 // if firstArg has type T&&, then &firstArg has type T*&. 1175 // Cast away the reference to a value type so that the argument 1176 // matches the assignment's parameter types 1177 if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) { 1178 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() ); 1179 } 1180 assign->get_args().push_back( addrArg ); 1176 Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } ); 1181 1177 firstArg = new VariableExpr( tmp ); 1178 1179 // resolve assignment and dispose of new env 1180 ResolvExpr::findVoidExpression( assign, indexer ); 1181 delete assign->env; 1182 assign->env = nullptr; 1182 1183 1183 1184 // for constructor expr: -
src/InitTweak/GenInit.cc
r78315272 r3f7e12cb 26 26 #include "Common/UniqueName.h" // for UniqueName 27 27 #include "Common/utility.h" // for ValueGuard, maybeClone 28 #include "GenPoly/DeclMutator.h" // for DeclMutator29 28 #include "GenPoly/GenPoly.h" // for getFunctionType, isPolyType 30 29 #include "GenPoly/ScopedSet.h" // for ScopedSet, ScopedSet<>::const_iter... … … 62 61 }; 63 62 64 struct CtorDtor : public WithGuards, public WithShortCircuiting {63 struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor> { 65 64 /// create constructor and destructor statements for object declarations. 66 65 /// the actual call statements will be added in after the resolver has run … … 75 74 // that need to be constructed or destructed 76 75 void previsit( StructDecl *aggregateDecl ); 77 void previsit( __attribute__((unused)) UnionDecl * aggregateDecl ) { visit_children = false; } 78 void previsit( __attribute__((unused)) EnumDecl * aggregateDecl ) { visit_children = false; } 79 void previsit( __attribute__((unused)) TraitDecl * aggregateDecl ) { visit_children = false; } 80 void previsit( __attribute__((unused)) TypeDecl * typeDecl ) { visit_children = false; } 81 void previsit( __attribute__((unused)) TypedefDecl * typeDecl ) { visit_children = false; } 82 void previsit( __attribute__((unused)) FunctionType * funcType ) { visit_children = false; } 76 void previsit( AggregateDecl * ) { visit_children = false; } 77 void previsit( NamedTypeDecl * ) { visit_children = false; } 78 void previsit( FunctionType * ) { visit_children = false; } 83 79 84 80 void previsit( CompoundStmt * compoundStmt ); … … 89 85 // should not have a ConstructorInit generated. 90 86 91 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed 92 bool isManaged( Type * type ) const; // determine if type is managed 93 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor 94 GenPoly::ScopedSet< std::string > managedTypes; 87 ManagedTypes managedTypes; 95 88 bool inFunction = false; 96 89 }; 97 90 98 class HoistArrayDimension final : public GenPoly::DeclMutator { 99 public: 100 typedef GenPoly::DeclMutator Parent; 101 91 struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards { 102 92 /// hoist dimension from array types in object declaration so that it uses a single 103 93 /// const variable of type size_t, so that side effecting array dimensions are only … … 105 95 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 106 96 107 private: 108 using Parent::mutate; 109 110 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override; 111 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override; 97 void premutate( ObjectDecl * objectDecl ); 98 DeclarationWithType * postmutate( ObjectDecl * objectDecl ); 99 void premutate( FunctionDecl *functionDecl ); 112 100 // should not traverse into any of these declarations to find objects 113 101 // that need to be constructed or destructed 114 virtual Declaration* mutate( StructDecl *aggregateDecl ) override { return aggregateDecl; } 115 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; } 116 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; } 117 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; } 118 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; } 119 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; } 120 121 virtual Type* mutate( FunctionType *funcType ) override { return funcType; } 102 void premutate( AggregateDecl * ) { visit_children = false; } 103 void premutate( NamedTypeDecl * ) { visit_children = false; } 104 void premutate( FunctionType * ) { visit_children = false; } 122 105 123 106 void hoist( Type * type ); … … 128 111 129 112 void genInit( std::list< Declaration * > & translationUnit ) { 130 ReturnFixer::makeReturnTemp( translationUnit );113 fixReturnStatements( translationUnit ); 131 114 HoistArrayDimension::hoistArrayDimension( translationUnit ); 132 115 CtorDtor::generateCtorDtor( translationUnit ); 133 116 } 134 117 135 void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {118 void fixReturnStatements( std::list< Declaration * > & translationUnit ) { 136 119 PassVisitor<ReturnFixer> fixer; 137 120 mutateAll( translationUnit, fixer ); … … 143 126 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address 144 127 // is being returned 145 if ( returnStmt-> get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {128 if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) { 146 129 // explicitly construct the return value using the return expression and the retVal object 147 assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() ); 148 149 stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) ); 130 assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() ); 131 132 ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() ); 133 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) { 134 // return statement has already been mutated - don't need to do it again 135 if ( varExpr->var == retVal ) return; 136 } 137 stmtsToAddBefore.push_back( genCtorDtor( "?{}", retVal, returnStmt->get_expr() ) ); 150 138 151 139 // return the retVal object 152 returnStmt-> set_expr( new VariableExpr( returnVals.front()) );140 returnStmt->expr = new VariableExpr( returnVals.front() ); 153 141 } // if 154 142 } … … 158 146 GuardValue( funcName ); 159 147 160 ftype = functionDecl-> get_functionType();161 funcName = functionDecl-> get_name();148 ftype = functionDecl->type; 149 funcName = functionDecl->name; 162 150 } 163 151 … … 165 153 // which would be incorrect if it is a side-effecting computation. 166 154 void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 167 HoistArrayDimension hoister; 168 hoister.mutateDeclarationList( translationUnit ); 169 } 170 171 DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) { 155 PassVisitor<HoistArrayDimension> hoister; 156 mutateAll( translationUnit, hoister ); 157 } 158 159 void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) { 160 GuardValue( storageClasses ); 172 161 storageClasses = objectDecl->get_storageClasses(); 173 DeclarationWithType * temp = Parent::mutate( objectDecl ); 162 } 163 164 DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) { 174 165 hoist( objectDecl->get_type() ); 175 return temp;166 return objectDecl; 176 167 } 177 168 … … 194 185 195 186 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 196 addDeclaration( arrayDimension );187 declsToAddBefore.push_back( arrayDimension ); 197 188 198 189 hoist( arrayType->get_base() ); … … 201 192 } 202 193 203 DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) { 204 ValueGuard< bool > oldInFunc( inFunction ); 205 inFunction = true; 206 DeclarationWithType * decl = Parent::mutate( functionDecl ); 207 return decl; 194 void HoistArrayDimension::premutate( FunctionDecl * ) { 195 GuardValue( inFunction ); 208 196 } 209 197 … … 213 201 } 214 202 215 bool CtorDtor::isManaged( Type * type ) const {216 // at least for now,references are never constructed203 bool ManagedTypes::isManaged( Type * type ) const { 204 // references are never constructed 217 205 if ( dynamic_cast< ReferenceType * >( type ) ) return false; 218 206 // need to clear and reset qualifiers when determining if a type is managed … … 221 209 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 222 210 // tuple is also managed if any of its components are managed 223 if ( std::any_of( tupleType-> get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {211 if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) { 224 212 return true; 225 213 } 226 214 } 227 215 // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable) 228 return managedTypes.find( SymTab::Mangler::mangle ( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );229 } 230 231 bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {216 return managedTypes.find( SymTab::Mangler::mangleConcrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type ); 217 } 218 219 bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const { 232 220 Type * type = objDecl->get_type(); 233 221 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { … … 237 225 } 238 226 239 void CtorDtor::handleDWT( DeclarationWithType * dwt ) {227 void ManagedTypes::handleDWT( DeclarationWithType * dwt ) { 240 228 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 241 229 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) { … … 244 232 Type * type = InitTweak::getPointerBase( params.front()->get_type() ); 245 233 assert( type ); 246 managedTypes.insert( SymTab::Mangler::mangle( type ) ); 247 } 248 } 234 managedTypes.insert( SymTab::Mangler::mangleConcrete( type ) ); 235 } 236 } 237 238 void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) { 239 // don't construct members, but need to take note if there is a managed member, 240 // because that means that this type is also managed 241 for ( Declaration * member : aggregateDecl->get_members() ) { 242 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 243 if ( isManaged( field ) ) { 244 // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that 245 // polymorphic constructors make generic types managed types 246 StructInstType inst( Type::Qualifiers(), aggregateDecl ); 247 managedTypes.insert( SymTab::Mangler::mangleConcrete( &inst ) ); 248 break; 249 } 250 } 251 } 252 } 253 254 void ManagedTypes::beginScope() { managedTypes.beginScope(); } 255 void ManagedTypes::endScope() { managedTypes.endScope(); } 249 256 250 257 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) { … … 291 298 292 299 void CtorDtor::previsit( ObjectDecl * objDecl ) { 293 handleDWT( objDecl );300 managedTypes.handleDWT( objDecl ); 294 301 // hands off if @=, extern, builtin, etc. 295 302 // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C 296 if ( tryConstruct( objDecl ) && ( isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {303 if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) { 297 304 // constructed objects cannot be designated 298 305 if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl ); … … 305 312 306 313 void CtorDtor::previsit( FunctionDecl *functionDecl ) { 314 visit_children = false; // do not try and construct parameters or forall parameters 307 315 GuardValue( inFunction ); 308 316 inFunction = true; 309 317 310 handleDWT( functionDecl );318 managedTypes.handleDWT( functionDecl ); 311 319 312 320 GuardScope( managedTypes ); … … 314 322 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) { 315 323 for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) { 316 handleDWT( assertion );324 managedTypes.handleDWT( assertion ); 317 325 } 318 326 } 319 327 320 PassVisitor<CtorDtor> newCtorDtor; 321 newCtorDtor.pass = *this; 322 maybeAccept( functionDecl->get_statements(), newCtorDtor ); 323 visit_children = false; // do not try and construct parameters or forall parameters - must happen after maybeAccept 328 maybeAccept( functionDecl->get_statements(), *visitor ); 324 329 } 325 330 … … 327 332 visit_children = false; // do not try to construct and destruct aggregate members 328 333 329 // don't construct members, but need to take note if there is a managed member, 330 // because that means that this type is also managed 331 for ( Declaration * member : aggregateDecl->get_members() ) { 332 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 333 if ( isManaged( field ) ) { 334 StructInstType inst( Type::Qualifiers(), aggregateDecl ); 335 managedTypes.insert( SymTab::Mangler::mangle( &inst ) ); 336 break; 337 } 338 } 339 } 340 } 341 342 void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt ) { 334 managedTypes.handleStruct( aggregateDecl ); 335 } 336 337 void CtorDtor::previsit( CompoundStmt * ) { 343 338 GuardScope( managedTypes ); 344 339 } -
src/InitTweak/GenInit.h
r78315272 r3f7e12cb 16 16 #pragma once 17 17 18 #include <list> // for list19 #include <string> // for string18 #include <list> // for list 19 #include <string> // for string 20 20 21 #include "SynTree/SynTree.h" // for Visitor Nodes 21 #include "SynTree/SynTree.h" // for Visitor Nodes 22 23 #include "GenPoly/ScopedSet.h" // for ScopedSet 22 24 23 25 namespace InitTweak { … … 25 27 void genInit( std::list< Declaration * > & translationUnit ); 26 28 27 /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument 28 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr ); 29 /// Converts return statements into copy constructor calls on the hidden return variable 30 void fixReturnStatements( std::list< Declaration * > & translationUnit ); 31 32 /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument 33 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr ); 29 34 30 35 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer 31 36 ConstructorInit * genCtorInit( ObjectDecl * objDecl ); 37 38 class ManagedTypes { 39 public: 40 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed 41 bool isManaged( Type * type ) const; // determine if type is managed 42 43 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor 44 void handleStruct( StructDecl * aggregateDecl ); // add type to managed if child is managed 45 46 void beginScope(); 47 void endScope(); 48 private: 49 GenPoly::ScopedSet< std::string > managedTypes; 50 }; 32 51 } // namespace 33 52 -
src/InitTweak/InitTweak.cc
r78315272 r3f7e12cb 1 #include <stddef.h> // for NULL2 1 #include <algorithm> // for find, all_of 3 2 #include <cassert> // for assertf, assert, strict_dynamic_cast … … 23 22 #include "SynTree/Type.h" // for FunctionType, ArrayType, PointerType 24 23 #include "SynTree/Visitor.h" // for Visitor, maybeAccept 24 #include "Tuples/Tuples.h" // for Tuples::isTtype 25 25 26 26 class UntypedValofExpr; … … 170 170 } 171 171 172 bool InitExpander::addReference() { 173 bool added = false; 174 for ( Expression *& expr : cur ) { 175 expr = new AddressExpr( expr ); 176 added = true; 177 } 178 return added; 179 } 180 172 181 namespace { 173 182 /// given index i, dimension d, initializer init, and callExpr f, generates … … 184 193 callExpr->get_args().splice( callExpr->get_args().end(), args ); 185 194 186 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL);195 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr ); 187 196 188 197 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); … … 250 259 // To accomplish this, generate switch statement, consuming all of expander's elements 251 260 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 252 if ( ! init ) return NULL;261 if ( ! init ) return nullptr; 253 262 CompoundStmt * block = new CompoundStmt( noLabels ); 254 263 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) ); 255 264 if ( block->get_kids().empty() ) { 256 265 delete block; 257 return NULL;266 return nullptr; 258 267 } else { 259 init = NULL; // init was consumed in creating the list init268 init = nullptr; // init was consumed in creating the list init 260 269 return block; 261 270 } 262 271 } 263 272 264 Statement * ExprImpl::buildListInit( __attribute((unused)) UntypedExpr * dst, __attribute((unused)) std::list< Expression * > & indices) {265 return NULL;273 Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) { 274 return nullptr; 266 275 } 267 276 … … 270 279 } 271 280 272 bool tryConstruct( ObjectDecl * objDecl ) { 281 Type * getTypeofThis( FunctionType * ftype ) { 282 assertf( ftype, "getTypeofThis: nullptr ftype" ); 283 ObjectDecl * thisParam = getParamThis( ftype ); 284 ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( thisParam->type ); 285 return refType->base; 286 } 287 288 ObjectDecl * getParamThis( FunctionType * ftype ) { 289 assertf( ftype, "getParamThis: nullptr ftype" ); 290 auto & params = ftype->parameters; 291 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( ftype ).c_str() ); 292 return strict_dynamic_cast< ObjectDecl * >( params.front() ); 293 } 294 295 bool tryConstruct( DeclarationWithType * dwt ) { 296 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); 297 if ( ! objDecl ) return false; 273 298 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) && 274 (objDecl->get_init() == NULL || 275 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) 276 && ! objDecl->get_storageClasses().is_extern; 299 (objDecl->get_init() == nullptr || 300 ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() )) 301 && ! objDecl->get_storageClasses().is_extern 302 && isConstructable( objDecl->type ); 303 } 304 305 bool isConstructable( Type * type ) { 306 return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type ); 277 307 } 278 308 … … 314 344 collectCtorDtorCalls( stmt, matches ); 315 345 assert( matches.size() <= 1 ); 316 return matches.size() == 1 ? matches.front() : NULL;346 return matches.size() == 1 ? matches.front() : nullptr; 317 347 } 318 348 … … 332 362 assert( expr ); 333 363 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 334 return varExpr-> get_var();364 return varExpr->var; 335 365 } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) { 336 return memberExpr-> get_member();366 return memberExpr->member; 337 367 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 338 return getCalledFunction( castExpr-> get_arg());368 return getCalledFunction( castExpr->arg ); 339 369 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) { 340 370 return handleDerefCalledFunction( untypedExpr ); … … 342 372 return handleDerefCalledFunction( appExpr ); 343 373 } else if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) { 344 return getCalledFunction( addrExpr->get_arg() ); 374 return getCalledFunction( addrExpr->arg ); 375 } else if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( expr ) ) { 376 return getCalledFunction( commaExpr->arg2 ); 345 377 } 346 378 return nullptr; … … 359 391 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) { 360 392 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ); 361 if ( ! appExpr ) return NULL;393 if ( ! appExpr ) return nullptr; 362 394 DeclarationWithType * function = getCalledFunction( appExpr->get_function() ); 363 395 assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() ); 364 396 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 365 397 // will call all member dtors, and some members may have a user defined dtor. 366 return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;398 return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr; 367 399 } 368 400 … … 482 514 return refType->get_base(); 483 515 } else { 484 return NULL;516 return nullptr; 485 517 } 486 518 } … … 488 520 Type * isPointerType( Type * type ) { 489 521 if ( getPointerBase( type ) ) return type; 490 else return NULL;522 else return nullptr; 491 523 } 492 524 … … 557 589 FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) { 558 590 FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl ); 559 if ( ! function ) return 0;560 if ( function-> get_name() != fname ) return 0;561 FunctionType * ftype = function-> get_functionType();562 if ( ftype-> get_parameters().size() != 2 ) return 0;591 if ( ! function ) return nullptr; 592 if ( function->name != fname ) return nullptr; 593 FunctionType * ftype = function->type; 594 if ( ftype->parameters.size() != 2 ) return nullptr; 563 595 564 596 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 565 Type * t2 = ftype-> get_parameters().back()->get_type();597 Type * t2 = ftype->parameters.back()->get_type(); 566 598 assert( t1 ); 567 599 … … 583 615 } 584 616 FunctionDecl * isDefaultConstructor( Declaration * decl ) { 585 if ( isConstructor( decl-> get_name()) ) {617 if ( isConstructor( decl->name ) ) { 586 618 if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) { 587 if ( func-> get_functionType()->get_parameters().size() == 1 ) {619 if ( func->type->parameters.size() == 1 ) { 588 620 return func; 589 621 } -
src/InitTweak/InitTweak.h
r78315272 r3f7e12cb 30 30 FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ); 31 31 32 /// returns the base type of the first parameter to a constructor/destructor/assignment function 33 Type * getTypeofThis( FunctionType * ftype ); 34 35 /// returns the first parameter of a constructor/destructor/assignment function 36 ObjectDecl * getParamThis( FunctionType * ftype ); 37 32 38 /// transform Initializer into an argument list that can be passed to a call expression 33 39 std::list< Expression * > makeInitList( Initializer * init ); 34 40 35 /// True if the resolver should try to construct objDecl 36 bool tryConstruct( ObjectDecl * objDecl ); 41 /// True if the resolver should try to construct dwt 42 bool tryConstruct( DeclarationWithType * dwt ); 43 44 /// True if the type can have a user-defined constructor 45 bool isConstructable( Type * t ); 37 46 38 47 /// True if the Initializer contains designations … … 96 105 void addArrayIndex( Expression * index, Expression * dimension ); 97 106 void clearArrayIndices(); 107 bool addReference(); 98 108 99 109 class ExpanderImpl;
Note:
See TracChangeset
for help on using the changeset viewer.