diff options
| author | Larisse Voufo <lvoufo@google.com> | 2015-01-27 18:47:05 +0000 |
|---|---|---|
| committer | Larisse Voufo <lvoufo@google.com> | 2015-01-27 18:47:05 +0000 |
| commit | 19d08672844ee7558910d9880555b111fc3c90b3 (patch) | |
| tree | 2a0eb5add4adbe1b8b7eb8090c51e675c2b8a5f9 /clang/lib | |
| parent | ba1b6a16c444690ac2ba9513536a3fc2f1822406 (diff) | |
| download | bcm5719-llvm-19d08672844ee7558910d9880555b111fc3c90b3.tar.gz bcm5719-llvm-19d08672844ee7558910d9880555b111fc3c90b3.zip | |
Implement the remaining portion of DR1467 from r227022. I may have overlooked a few things, but this implementation comes straight from the DR resolution itself.
llvm-svn: 227224
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 47 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 87 |
2 files changed, 84 insertions, 50 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index c9d8e5312ad..c6d9a544c4b 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3110,7 +3110,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, ArrayRef<NamedDecl *> Ctors, OverloadCandidateSet::iterator &Best, bool CopyInitializing, bool AllowExplicit, - bool OnlyListConstructors, bool InitListSyntax) { + bool OnlyListConstructors) { CandidateSet.clear(); for (ArrayRef<NamedDecl *>::iterator @@ -3129,20 +3129,13 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, Constructor = cast<CXXConstructorDecl>(D); // C++11 [over.best.ics]p4: - // However, when considering the argument of a constructor or - // user-defined conversion function that is a candidate: - // -- by 13.3.1.3 when invoked for the copying/moving of a temporary - // in the second step of a class copy-initialization, - // -- by 13.3.1.7 when passing the initializer list as a single - // argument or when the initializer list has exactly one elementand - // a conversion to some class X or reference to (possibly - // cv-qualified) X is considered for the first parameter of a - // constructor of X, or - // -- by 13.3.1.4, 13.3.1.5, or 13.3.1.6 in all cases, - // only standard conversion sequences and ellipsis conversion sequences - // are considered. - if ((CopyInitializing || (InitListSyntax && Args.size() == 1)) && - Constructor->isCopyOrMoveConstructor()) + // ... and the constructor or user-defined conversion function is a + // candidate by + // — 13.3.1.3, when the argument is the temporary in the second step + // of a class copy-initialization, or + // — 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), + // user-defined conversion sequences are not considered. + if (CopyInitializing && Constructor->isCopyOrMoveConstructor()) SuppressUserConversions = true; } @@ -3222,16 +3215,12 @@ static void TryConstructorInitialization(Sema &S, OverloadCandidateSet::iterator Best; bool AsInitializerList = false; - // C++14 DR 1467 [over.match.list]p1: + // C++11 [over.match.list]p1, per DR1467: // When objects of non-aggregate type T are list-initialized, such that // 8.5.4 [dcl.init.list] specifies that overload resolution is performed // according to the rules in this section, overload resolution selects // the constructor in two phases: // - // C++11 [over.match.list]p1: - // When objects of non-aggregate type T are list-initialized, overload - // resolution selects the constructor in two phases: - // // - Initially, the candidate functions are the initializer-list // constructors of the class T and the argument list consists of the // initializer list as a single argument. @@ -3245,8 +3234,7 @@ static void TryConstructorInitialization(Sema &S, Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, - /*OnlyListConstructor=*/true, - InitListSyntax); + /*OnlyListConstructor=*/true); // Time to unwrap the init list. Args = MultiExprArg(ILE->getInits(), ILE->getNumInits()); @@ -3262,8 +3250,7 @@ static void TryConstructorInitialization(Sema &S, Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, - /*OnlyListConstructors=*/false, - InitListSyntax); + /*OnlyListConstructors=*/false); } if (Result) { Sequence.SetOverloadFailure(InitListSyntax ? @@ -3439,7 +3426,7 @@ static void TryListInitialization(Sema &S, return; } - // C++14 DR1467 [dcl.init.list]p3: + // C++11 [dcl.init.list]p3, per DR1467: // - If T is a class type and the initializer list has a single element of // type cv U, where U is T or a class derived from T, the object is // initialized from that element (by copy-initialization for @@ -3449,8 +3436,8 @@ static void TryListInitialization(Sema &S, // single element that is an appropriately-typed string literal // (8.5.2 [dcl.init.string]), initialization is performed as described // in that section. - // - Otherwise, If T is an aggregate, [...] (continue below). - if (S.getLangOpts().CPlusPlus14 && InitList->getNumInits() == 1) { + // - Otherwise, if T is an aggregate, [...] (continue below). + if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1) { if (DestType->isRecordType()) { QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || @@ -3519,12 +3506,6 @@ static void TryListInitialization(Sema &S, InitList->getInit(0)->getType()->isRecordType()) { // - Otherwise, if the initializer list has a single element of type E // [...references are handled above...], the object or reference is - // initialized from that element; if a narrowing conversion is required - // to convert the element to T, the program is ill-formed. - // - // C++14 DR1467: - // - Otherwise, if the initializer list has a single element of type E - // [...references are handled above...], the object or reference is // initialized from that element (by copy-initialization for // copy-list-initialization, or by direct-initialization for // direct-list-initialization); if a narrowing conversion is required diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7c34f43d270..28f1231bd57 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3336,7 +3336,26 @@ CompareImplicitConversionSequences(Sema &S, // Two implicit conversion sequences of the same form are // indistinguishable conversion sequences unless one of the // following rules apply: (C++ 13.3.3.2p3): + + // List-initialization sequence L1 is a better conversion sequence than + // list-initialization sequence L2 if: + // - L1 converts to std::initializer_list<X> for some X and L2 does not, or, + // if not that, + // - L1 converts to type “array of N1 T”, L2 converts to type “array of N2 T”, + // and N1 is smaller than N2., + // even if one of the other rules in this paragraph would otherwise apply. + if (!ICS1.isBad()) { + if (ICS1.isStdInitializerListElement() && + !ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Better; + if (!ICS1.isStdInitializerListElement() && + ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Worse; + } + if (ICS1.isStandard()) + // Standard conversion sequence S1 is a better conversion sequence than + // standard conversion sequence S2 if [...] Result = CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard); else if (ICS1.isUserDefined()) { @@ -3357,19 +3376,6 @@ CompareImplicitConversionSequences(Sema &S, ICS2.UserDefined.ConversionFunction); } - // List-initialization sequence L1 is a better conversion sequence than - // list-initialization sequence L2 if L1 converts to std::initializer_list<X> - // for some X and L2 does not. - if (Result == ImplicitConversionSequence::Indistinguishable && - !ICS1.isBad()) { - if (ICS1.isStdInitializerListElement() && - !ICS2.isStdInitializerListElement()) - return ImplicitConversionSequence::Better; - if (!ICS1.isStdInitializerListElement() && - ICS2.isStdInitializerListElement()) - return ImplicitConversionSequence::Worse; - } - return Result; } @@ -4453,11 +4459,53 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, if (S.RequireCompleteType(From->getLocStart(), ToType, 0)) return Result; + // Per DR1467: + // If the parameter type is a class X and the initializer list has a single + // element of type cv U, where U is X or a class derived from X, the + // implicit conversion sequence is the one required to convert the element + // to the parameter type. + // + // Otherwise, if the parameter type is a character array [... ] + // and the initializer list has a single element that is an + // appropriately-typed string literal (8.5.2 [dcl.init.string]), the + // implicit conversion sequence is the identity conversion. + if (From->getNumInits() == 1) { + if (ToType->isRecordType()) { + QualType InitType = From->getInit(0)->getType(); + if (S.Context.hasSameUnqualifiedType(InitType, ToType) || + S.IsDerivedFrom(InitType, ToType)) + return TryCopyInitialization(S, From->getInit(0), ToType, + SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + } + if (S.Context.getAsArrayType(ToType)) { + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, ToType, + /*Consumed=*/false); + if (S.CanPerformCopyInitialization(Entity, From)) { + Result.setStandard(); + Result.Standard.setAsIdentityConversion(); + Result.Standard.setFromType(ToType); + Result.Standard.setAllToTypes(ToType); + return Result; + } + } + } + + // C++14 [over.ics.list]p2: Otherwise, if the parameter type [...] (below). // C++11 [over.ics.list]p2: // If the parameter type is std::initializer_list<X> or "array of X" and // all the elements can be implicitly converted to X, the implicit // conversion sequence is the worst conversion necessary to convert an // element of the list to X. + // + // C++14 [over.ics.list]p3: + // Otherwise, if the parameter type is “array of N X”, if the initializer + // list has exactly N elements or if it has fewer than N elements and X is + // default-constructible, and if all the elements of the initializer list + // can be implicitly converted to X, the implicit conversion sequence is + // the worst conversion necessary to convert an element of the list to X. bool toStdInitializerList = false; QualType X; if (ToType->isArrayType()) @@ -4496,6 +4544,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p4: // C++11 [over.ics.list]p3: // Otherwise, if the parameter is a non-aggregate class X and overload // resolution chooses a single best constructor [...] the implicit @@ -4511,6 +4560,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, /*AllowObjCConversionOnExplicit=*/false); } + // C++14 [over.ics.list]p5: // C++11 [over.ics.list]p4: // Otherwise, if the parameter has an aggregate type which can be // initialized from the initializer list [...] the implicit conversion @@ -4537,6 +4587,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p6: // C++11 [over.ics.list]p5: // Otherwise, if the parameter is a reference, see 13.3.3.1.4. if (ToType->isReferenceType()) { @@ -4605,14 +4656,15 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p7: // C++11 [over.ics.list]p6: // Otherwise, if the parameter type is not a class: if (!ToType->isRecordType()) { - // - if the initializer list has one element, the implicit conversion - // sequence is the one required to convert the element to the - // parameter type. + // - if the initializer list has one element that is not itself an + // initializer list, the implicit conversion sequence is the one + // required to convert the element to the parameter type. unsigned NumInits = From->getNumInits(); - if (NumInits == 1) + if (NumInits == 1 && !dyn_cast<InitListExpr>(From->getInit(0))) Result = TryCopyInitialization(S, From->getInit(0), ToType, SuppressUserConversions, InOverloadResolution, @@ -4628,6 +4680,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p8: // C++11 [over.ics.list]p7: // In all cases other than those enumerated above, no conversion is possible return Result; |

