diff options
-rw-r--r-- | clang/include/clang/Sema/Overload.h | 23 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 12 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx0x-initializer-constructor.cpp | 18 |
3 files changed, 48 insertions, 5 deletions
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 751d6053429..1d53faaa2d8 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -401,11 +401,15 @@ namespace clang { }; /// ConversionKind - The kind of implicit conversion sequence. - unsigned ConversionKind : 31; + unsigned ConversionKind : 30; /// \brief Whether the argument is an initializer list. bool ListInitializationSequence : 1; + /// \brief Whether the target is really a std::initializer_list, and the + /// sequence only represents the worst element conversion. + bool StdInitializerListElement : 1; + void setKind(Kind K) { destruct(); ConversionKind = K; @@ -435,13 +439,16 @@ namespace clang { }; ImplicitConversionSequence() - : ConversionKind(Uninitialized), ListInitializationSequence(false) {} + : ConversionKind(Uninitialized), ListInitializationSequence(false), + StdInitializerListElement(false) + {} ~ImplicitConversionSequence() { destruct(); } ImplicitConversionSequence(const ImplicitConversionSequence &Other) : ConversionKind(Other.ConversionKind), - ListInitializationSequence(Other.ListInitializationSequence) + ListInitializationSequence(Other.ListInitializationSequence), + StdInitializerListElement(Other.StdInitializerListElement) { switch (ConversionKind) { case Uninitialized: break; @@ -536,6 +543,16 @@ namespace clang { ListInitializationSequence = true; } + /// \brief Whether the target is really a std::initializer_list, and the + /// sequence only represents the worst element conversion. + bool isStdInitializerListElement() const { + return StdInitializerListElement; + } + + void setStdInitializerListElement(bool V = true) { + StdInitializerListElement = V; + } + // The result of a comparison between implicit conversion // sequences. Use Sema::CompareImplicitConversionSequences to // actually perform the comparison. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 12d4e48352e..dd781a86031 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3163,9 +3163,15 @@ CompareImplicitConversionSequences(Sema &S, // 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() && ICS1.isListInitializationSequence() && ICS2.isListInitializationSequence()) { - // FIXME: Find out if ICS1 converts to initializer_list and ICS2 doesn't. + if (ICS1.isStdInitializerListElement() && + !ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Better; + if (!ICS1.isStdInitializerListElement() && + ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Worse; } return Result; @@ -4241,11 +4247,12 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // 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. + bool toStdInitializerList = false; QualType X; if (ToType->isArrayType()) X = S.Context.getBaseElementType(ToType); else - (void)S.isStdInitializerList(ToType, &X); + toStdInitializerList = S.isStdInitializerList(ToType, &X); if (!X.isNull()) { for (unsigned i = 0, e = From->getNumInits(); i < e; ++i) { Expr *Init = From->getInit(i); @@ -4265,6 +4272,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, Result = ICS; } Result.setListInitializationSequence(); + Result.setStdInitializerListElement(toStdInitializerList); return Result; } diff --git a/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp index 2fd30614d14..5e686d7152d 100644 --- a/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -194,3 +194,21 @@ namespace objects { H h4 = {1, 1}; // expected-error {{no matching constructor}} }; } + +namespace PR12092 { + + struct S { + S(const char*); + }; + struct V { + template<typename T> V(T, T); + void f(std::initializer_list<S>); + void f(const V &); + }; + + void g() { + extern V s; + s.f({"foo", "bar"}); + } + +} |