Implement a FIXME for conversion sequence distinction. Should fix PR12092.

llvm-svn: 151577
This commit is contained in:
Sebastian Redl 2012-02-27 22:38:26 +00:00
parent 7b4646184b
commit aa6feaa7ea
3 changed files with 48 additions and 5 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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"});
}
}