summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2012-01-17 22:49:48 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2012-01-17 22:49:48 +0000
commit10f0fc04a8f509aabb06ef1cb196a62a2c20c995 (patch)
treefbcadb18f1ebad8392641c125bd8ed13cdc838fe /clang
parentc1839b1b098723756efdea72ca91da64a0e30880 (diff)
downloadbcm5719-llvm-10f0fc04a8f509aabb06ef1cb196a62a2c20c995.tar.gz
bcm5719-llvm-10f0fc04a8f509aabb06ef1cb196a62a2c20c995.zip
Basic overloading support for std::initializer_list.
llvm-svn: 148350
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp32
-rw-r--r--clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp29
2 files changed, 58 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d14bf904df0..e39735e256c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -3953,15 +3953,42 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
Result.setBad(BadConversionSequence::no_conversion, From, ToType);
Result.setListInitializationSequence();
+ // We need a complete type for what follows. Incomplete types can bever be
+ // initialized from init lists.
+ if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()))
+ return Result;
+
// 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.
- // FIXME: Recognize std::initializer_list.
- // FIXME: Implement arrays.
+ QualType X;
if (ToType->isArrayType())
+ X = S.Context.getBaseElementType(ToType);
+ else
+ (void)S.isStdInitializerList(ToType, &X);
+ if (!X.isNull()) {
+ for (unsigned i = 0, e = From->getNumInits(); i < e; ++i) {
+ Expr *Init = From->getInit(i);
+ ImplicitConversionSequence ICS =
+ TryCopyInitialization(S, Init, X, SuppressUserConversions,
+ InOverloadResolution,
+ AllowObjCWritebackConversion);
+ // If a single element isn't convertible, fail.
+ if (ICS.isBad()) {
+ Result = ICS;
+ break;
+ }
+ // Otherwise, look for the worst conversion.
+ if (Result.isBad() ||
+ CompareImplicitConversionSequences(S, ICS, Result) ==
+ ImplicitConversionSequence::Worse)
+ Result = ICS;
+ }
+ Result.setListInitializationSequence();
return Result;
+ }
// C++11 [over.ics.list]p3:
// Otherwise, if the parameter is a non-aggregate class X and overload
@@ -4078,7 +4105,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
// - if the initializer list has one element, the implicit conversion
// sequence is the one required to convert the element to the
// parameter type.
- // FIXME: Catch narrowing here?
unsigned NumInits = From->getNumInits();
if (NumInits == 1)
Result = TryCopyInitialization(S, From->getInit(0), ToType,
diff --git a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index fc0df68575b..87e7e8462ba 100644
--- a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -58,3 +58,32 @@ void function_call() {
void g(std::initializer_list<B>);
g({ {1, 2}, {2, 3}, {} });
}
+
+struct C {
+ C(int);
+};
+
+struct D {
+ D();
+ operator int();
+ operator C();
+};
+
+void overloaded_call() {
+ one overloaded(std::initializer_list<int>);
+ two overloaded(std::initializer_list<B>);
+
+ static_assert(sizeof(overloaded({1, 2, 3})) == sizeof(one), "bad overload");
+ static_assert(sizeof(overloaded({ {1, 2}, {2, 3}, {} })) == sizeof(two), "bad overload");
+
+ void ambiguous(std::initializer_list<A>); // expected-note {{candidate}}
+ void ambiguous(std::initializer_list<B>); // expected-note {{candidate}}
+ ambiguous({ {1, 2}, {2, 3}, {3, 4} }); // expected-error {{ambiguous}}
+
+ one ov2(std::initializer_list<int>); // expected-note {{candidate}}
+ two ov2(std::initializer_list<C>); // expected-note {{candidate}}
+ // Worst sequence to int is identity, whereas to C it's user-defined.
+ static_assert(sizeof(ov2({1, 2, 3})) == sizeof(one), "bad overload");
+ // But here, user-defined is worst in both cases.
+ ov2({1, 2, D()}); // expected-error {{ambiguous}}
+}
OpenPOWER on IntegriCloud