@@ -1568,19 +1568,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
1568
1568
// called for those cases.
1569
1569
if (CXXConstructorDecl *Constructor
1570
1570
= dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
1571
- QualType FromCanon
1572
- = S.Context.getCanonicalType(From->getType().getUnqualifiedType());
1571
+ QualType FromType;
1572
+ SourceLocation FromLoc;
1573
+ // C++11 [over.ics.list]p6, per DR2137:
1574
+ // C++17 [over.ics.list]p6:
1575
+ // If C is not an initializer-list constructor and the initializer list
1576
+ // has a single element of type cv U, where U is X or a class derived
1577
+ // from X, the implicit conversion sequence has Exact Match rank if U is
1578
+ // X, or Conversion rank if U is derived from X.
1579
+ if (const auto *InitList = dyn_cast<InitListExpr>(From);
1580
+ InitList && InitList->getNumInits() == 1 &&
1581
+ !S.isInitListConstructor(Constructor)) {
1582
+ const Expr *SingleInit = InitList->getInit(0);
1583
+ FromType = SingleInit->getType();
1584
+ FromLoc = SingleInit->getBeginLoc();
1585
+ } else {
1586
+ FromType = From->getType();
1587
+ FromLoc = From->getBeginLoc();
1588
+ }
1589
+ QualType FromCanon =
1590
+ S.Context.getCanonicalType(FromType.getUnqualifiedType());
1573
1591
QualType ToCanon
1574
1592
= S.Context.getCanonicalType(ToType).getUnqualifiedType();
1575
1593
if (Constructor->isCopyConstructor() &&
1576
1594
(FromCanon == ToCanon ||
1577
- S.IsDerivedFrom(From->getBeginLoc() , FromCanon, ToCanon))) {
1595
+ S.IsDerivedFrom(FromLoc , FromCanon, ToCanon))) {
1578
1596
// Turn this into a "standard" conversion sequence, so that it
1579
1597
// gets ranked with standard conversion sequences.
1580
1598
DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
1581
1599
ICS.setStandard();
1582
1600
ICS.Standard.setAsIdentityConversion();
1583
- ICS.Standard.setFromType(From->getType() );
1601
+ ICS.Standard.setFromType(FromType );
1584
1602
ICS.Standard.setAllToTypes(ToType);
1585
1603
ICS.Standard.CopyConstructor = Constructor;
1586
1604
ICS.Standard.FoundCopyConstructor = Found;
@@ -5306,18 +5324,18 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
5306
5324
IsDesignatedInit)
5307
5325
return Result;
5308
5326
5309
- // Per DR1467:
5310
- // If the parameter type is a class X and the initializer list has a single
5311
- // element of type cv U, where U is X or a class derived from X, the
5312
- // implicit conversion sequence is the one required to convert the element
5313
- // to the parameter type.
5327
+ // Per DR1467 and DR2137 :
5328
+ // If the parameter type is an aggregate class X and the initializer list
5329
+ // has a single element of type cv U, where U is X or a class derived from
5330
+ // X, the implicit conversion sequence is the one required to convert the
5331
+ // element to the parameter type.
5314
5332
//
5315
5333
// Otherwise, if the parameter type is a character array [... ]
5316
5334
// and the initializer list has a single element that is an
5317
5335
// appropriately-typed string literal (8.5.2 [dcl.init.string]), the
5318
5336
// implicit conversion sequence is the identity conversion.
5319
5337
if (From->getNumInits() == 1 && !IsDesignatedInit) {
5320
- if (ToType->isRecordType()) {
5338
+ if (ToType->isRecordType() && ToType->isAggregateType() ) {
5321
5339
QualType InitType = From->getInit(0)->getType();
5322
5340
if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
5323
5341
S.IsDerivedFrom(From->getBeginLoc(), InitType, ToType))
0 commit comments