From adfb535905a7ca4226d06a29ebc665085503afd5 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Mon, 27 Feb 2012 22:38:26 +0000 Subject: [PATCH] Implement a FIXME for conversion sequence distinction. Should fix PR12092. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151577 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Overload.h | 23 ++++++++++++++++--- lib/Sema/SemaOverload.cpp | 12 ++++++++-- .../SemaCXX/cxx0x-initializer-constructor.cpp | 18 +++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 751d605342..1d53faaa2d 100644 --- a/include/clang/Sema/Overload.h +++ b/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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 12d4e48352..dd781a8603 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3163,9 +3163,15 @@ CompareImplicitConversionSequences(Sema &S, // list-initialization sequence L2 if L1 converts to std::initializer_list // 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/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp index 2fd30614d1..5e686d7152 100644 --- a/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/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 V(T, T); + void f(std::initializer_list); + void f(const V &); + }; + + void g() { + extern V s; + s.f({"foo", "bar"}); + } + +} -- 2.40.0