@@ -1568,19 +1568,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
15681568 // called for those cases.
15691569 if (CXXConstructorDecl *Constructor
15701570 = 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());
15731591 QualType ToCanon
15741592 = S.Context.getCanonicalType(ToType).getUnqualifiedType();
15751593 if (Constructor->isCopyConstructor() &&
15761594 (FromCanon == ToCanon ||
1577- S.IsDerivedFrom(From->getBeginLoc() , FromCanon, ToCanon))) {
1595+ S.IsDerivedFrom(FromLoc , FromCanon, ToCanon))) {
15781596 // Turn this into a "standard" conversion sequence, so that it
15791597 // gets ranked with standard conversion sequences.
15801598 DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
15811599 ICS.setStandard();
15821600 ICS.Standard.setAsIdentityConversion();
1583- ICS.Standard.setFromType(From->getType() );
1601+ ICS.Standard.setFromType(FromType );
15841602 ICS.Standard.setAllToTypes(ToType);
15851603 ICS.Standard.CopyConstructor = Constructor;
15861604 ICS.Standard.FoundCopyConstructor = Found;
@@ -5306,18 +5324,18 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
53065324 IsDesignatedInit)
53075325 return Result;
53085326
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.
53145332 //
53155333 // Otherwise, if the parameter type is a character array [... ]
53165334 // and the initializer list has a single element that is an
53175335 // appropriately-typed string literal (8.5.2 [dcl.init.string]), the
53185336 // implicit conversion sequence is the identity conversion.
53195337 if (From->getNumInits() == 1 && !IsDesignatedInit) {
5320- if (ToType->isRecordType()) {
5338+ if (ToType->isRecordType() && ToType->isAggregateType() ) {
53215339 QualType InitType = From->getInit(0)->getType();
53225340 if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
53235341 S.IsDerivedFrom(From->getBeginLoc(), InitType, ToType))
0 commit comments