@@ -3546,15 +3546,50 @@ static void TryConstructorInitialization(Sema &S,
3546
3546
InitializationSequence &Sequence,
3547
3547
bool IsListInit = false,
3548
3548
bool IsInitListCopy = false) {
3549
- assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
3550
- "IsListInit must come with a single initializer list argument.");
3549
+ assert(((!IsListInit && !IsInitListCopy) ||
3550
+ (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
3551
+ "IsListInit/IsInitListCopy must come with a single initializer list "
3552
+ "argument.");
3553
+ InitListExpr *ILE =
3554
+ (IsListInit || IsInitListCopy) ? cast<InitListExpr>(Args[0]) : nullptr;
3555
+ MultiExprArg UnwrappedArgs =
3556
+ ILE ? MultiExprArg(ILE->getInits(), ILE->getNumInits()) : Args;
3551
3557
3552
3558
// The type we're constructing needs to be complete.
3553
3559
if (!S.isCompleteType(Kind.getLocation(), DestType)) {
3554
3560
Sequence.setIncompleteTypeFailure(DestType);
3555
3561
return;
3556
3562
}
3557
3563
3564
+ // C++1z [dcl.init]p17:
3565
+ // - If the initializer expression is a prvalue and the cv-unqualified
3566
+ // version of the source type is the same class as the class of the
3567
+ // destination, the initializer expression is used to initialize the
3568
+ // destination object.
3569
+ // Per DR (no number yet), this does not apply when initializing a base
3570
+ // class or delegating to another constructor from a mem-initializer.
3571
+ if (S.getLangOpts().CPlusPlus1z &&
3572
+ Entity.getKind() != InitializedEntity::EK_Base &&
3573
+ Entity.getKind() != InitializedEntity::EK_Delegating &&
3574
+ UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() &&
3575
+ S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) {
3576
+ // Convert qualifications if necessary.
3577
+ QualType InitType = UnwrappedArgs[0]->getType();
3578
+ ImplicitConversionSequence ICS;
3579
+ ICS.setStandard();
3580
+ ICS.Standard.setAsIdentityConversion();
3581
+ ICS.Standard.setFromType(InitType);
3582
+ ICS.Standard.setAllToTypes(InitType);
3583
+ if (!S.Context.hasSameType(InitType, DestType)) {
3584
+ ICS.Standard.Third = ICK_Qualification;
3585
+ ICS.Standard.setToType(2, DestType);
3586
+ }
3587
+ Sequence.AddConversionSequenceStep(ICS, DestType);
3588
+ if (ILE)
3589
+ Sequence.RewrapReferenceInitList(DestType, ILE);
3590
+ return;
3591
+ }
3592
+
3558
3593
const RecordType *DestRecordType = DestType->getAs<RecordType>();
3559
3594
assert(DestRecordType && "Constructor initialization requires record type");
3560
3595
CXXRecordDecl *DestRecordDecl
@@ -3588,20 +3623,16 @@ static void TryConstructorInitialization(Sema &S,
3588
3623
// constructors of the class T and the argument list consists of the
3589
3624
// initializer list as a single argument.
3590
3625
if (IsListInit) {
3591
- InitListExpr *ILE = cast<InitListExpr>(Args[0]);
3592
3626
AsInitializerList = true;
3593
3627
3594
3628
// If the initializer list has no elements and T has a default constructor,
3595
3629
// the first phase is omitted.
3596
- if (ILE->getNumInits() != 0 || ! DestRecordDecl->hasDefaultConstructor())
3630
+ if (!(UnwrappedArgs.empty() && DestRecordDecl->hasDefaultConstructor() ))
3597
3631
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,
3598
3632
CandidateSet, Ctors, Best,
3599
3633
CopyInitialization, AllowExplicit,
3600
3634
/*OnlyListConstructor=*/true,
3601
3635
IsListInit);
3602
-
3603
- // Time to unwrap the init list.
3604
- Args = MultiExprArg(ILE->getInits(), ILE->getNumInits());
3605
3636
}
3606
3637
3607
3638
// C++11 [over.match.list]p1:
@@ -3611,7 +3642,7 @@ static void TryConstructorInitialization(Sema &S,
3611
3642
// elements of the initializer list.
3612
3643
if (Result == OR_No_Viable_Function) {
3613
3644
AsInitializerList = false;
3614
- Result = ResolveConstructorOverload(S, Kind.getLocation(), Args ,
3645
+ Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs ,
3615
3646
CandidateSet, Ctors, Best,
3616
3647
CopyInitialization, AllowExplicit,
3617
3648
/*OnlyListConstructors=*/false,
@@ -3821,8 +3852,8 @@ static void TryListInitialization(Sema &S,
3821
3852
QualType InitType = InitList->getInit(0)->getType();
3822
3853
if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
3823
3854
S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) {
3824
- Expr *InitAsExpr = InitList->getInit(0) ;
3825
- TryConstructorInitialization(S, Entity, Kind, InitAsExpr , DestType,
3855
+ Expr *InitListAsExpr = InitList;
3856
+ TryConstructorInitialization(S, Entity, Kind, InitListAsExpr , DestType,
3826
3857
Sequence, /*InitListSyntax*/ false,
3827
3858
/*IsInitListCopy*/ true);
3828
3859
return;
@@ -4332,16 +4363,21 @@ static void TryReferenceInitializationCore(Sema &S,
4332
4363
}
4333
4364
4334
4365
// - If the initializer expression
4366
+ // C++14-and-before:
4335
4367
// - is an xvalue, class prvalue, array prvalue, or function lvalue and
4336
4368
// "cv1 T1" is reference-compatible with "cv2 T2"
4369
+ // C++1z:
4370
+ // - is an rvalue or function lvalue and "cv1 T1" is reference-compatible
4371
+ // with "cv2 T2"
4337
4372
// Note: functions are handled below.
4338
4373
if (!T1Function &&
4339
4374
(RefRelationship == Sema::Ref_Compatible ||
4340
4375
(Kind.isCStyleOrFunctionalCast() &&
4341
4376
RefRelationship == Sema::Ref_Related)) &&
4342
4377
(InitCategory.isXValue() ||
4343
- (InitCategory.isPRValue() && T2->isRecordType()) ||
4344
- (InitCategory.isPRValue() && T2->isArrayType()))) {
4378
+ (InitCategory.isPRValue() &&
4379
+ (S.getLangOpts().CPlusPlus1z || T2->isRecordType() ||
4380
+ T2->isArrayType())))) {
4345
4381
ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;
4346
4382
if (InitCategory.isPRValue() && T2->isRecordType()) {
4347
4383
// The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
@@ -6604,7 +6640,26 @@ InitializationSequence::Perform(Sema &S,
6604
6640
CreatedObject = Conversion->getReturnType()->isRecordType();
6605
6641
}
6606
6642
6643
+ // C++14 and before:
6644
+ // - if the function is a constructor, the call initializes a temporary
6645
+ // of the cv-unqualified version of the destination type [...]
6646
+ // C++1z:
6647
+ // - if the function is a constructor, the call is a prvalue of the
6648
+ // cv-unqualified version of the destination type whose return object
6649
+ // is initialized by the constructor [...]
6650
+ // Both:
6651
+ // The [..] call is used to direct-initialize, according to the rules
6652
+ // above, the object that is the destination of the
6653
+ // copy-initialization.
6654
+ // In C++14 and before, that always means the "constructors are
6655
+ // considered" bullet, because we have arrived at a reference-related
6656
+ // type. In C++1z, it only means that if the types are different or we
6657
+ // didn't produce a prvalue, so just check for that case here.
6607
6658
bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back());
6659
+ if (S.getLangOpts().CPlusPlus1z && CurInit.get()->isRValue() &&
6660
+ S.Context.hasSameUnqualifiedType(
6661
+ Entity.getType().getNonReferenceType(), CurInit.get()->getType()))
6662
+ RequiresCopy = false;
6608
6663
bool MaybeBindToTemp = RequiresCopy || shouldBindAsTemporary(Entity);
6609
6664
6610
6665
if (!MaybeBindToTemp && CreatedObject && shouldDestroyTemporary(Entity)) {
0 commit comments