[cfe-commits] r148349 - in /cfe/trunk: include/clang/Sema/Initialization.h lib/Sema/SemaInit.cpp test/SemaCXX/cxx0x-initializer-scalars.cpp test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp test/SemaCXX/generalized-initializers.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Tue Jan 17 14:49:42 PST 2012
Author: cornedbee
Date: Tue Jan 17 16:49:42 2012
New Revision: 148349
URL: http://llvm.org/viewvc/llvm-project?rev=148349&view=rev
Log:
Sema support for initialization of std::initializer_list from initializer lists.
This does not yet support CodeGen.
Added:
cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
Modified:
cfe/trunk/include/clang/Sema/Initialization.h
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
cfe/trunk/test/SemaCXX/generalized-initializers.cpp
Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=148349&r1=148348&r2=148349&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Tue Jan 17 16:49:42 2012
@@ -553,7 +553,9 @@
/// \brief Pass an object by indirect restore.
SK_PassByIndirectRestore,
/// \brief Produce an Objective-C object pointer.
- SK_ProduceObjCObject
+ SK_ProduceObjCObject,
+ /// \brief Construct a std::initializer_list from an initializer list.
+ SK_StdInitializerList
};
/// \brief A single step in the initialization sequence.
@@ -657,7 +659,10 @@
FK_ListInitializationFailed,
/// \brief Initializer has a placeholder type which cannot be
/// resolved by initialization.
- FK_PlaceholderType
+ FK_PlaceholderType,
+ /// \brief Failed to initialize a std::initializer_list because copy
+ /// construction of some element failed.
+ FK_InitListElementCopyFailure
};
private:
@@ -866,6 +871,10 @@
/// retaining it).
void AddProduceObjCObjectStep(QualType T);
+ /// \brief Add a step to construct a std::initializer_list object from an
+ /// initializer list.
+ void AddStdInitializerListConstructionStep(QualType T);
+
/// \brief Add steps to unwrap a initializer list for a reference around a
/// single element and rewrap it at the end.
void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);
@@ -886,7 +895,7 @@
return FailedCandidateSet;
}
- /// brief Get the overloading result, for when the initialization
+ /// \brief Get the overloading result, for when the initialization
/// sequence failed due to a bad overload.
OverloadingResult getFailedOverloadResult() const {
return FailedOverloadResult;
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=148349&r1=148348&r2=148349&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jan 17 16:49:42 2012
@@ -21,6 +21,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
@@ -2408,6 +2409,7 @@
case SK_PassByIndirectCopyRestore:
case SK_PassByIndirectRestore:
case SK_ProduceObjCObject:
+ case SK_StdInitializerList:
break;
case SK_ConversionSequence:
@@ -2445,6 +2447,7 @@
case FK_ListInitializationFailed:
case FK_VariableLengthArrayHasInitializer:
case FK_PlaceholderType:
+ case FK_InitListElementCopyFailure:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -2777,6 +2780,13 @@
Steps.push_back(S);
}
+void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) {
+ Step S;
+ S.Kind = SK_StdInitializerList;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::RewrapReferenceInitList(QualType T,
InitListExpr *Syntactic) {
assert(Syntactic->getNumInits() == 1 &&
@@ -2839,7 +2849,7 @@
CXXRecordDecl *DestRecordDecl,
QualType DestType,
InitializationSequence &Sequence) {
- // C++0x [dcl.init.list]p3:
+ // C++11 [dcl.init.list]p3:
// List-initialization of an object of type T is defined as follows:
// - If the initializer list has no elements and T is a class type with
// a default constructor, the object is value-initialized.
@@ -2876,7 +2886,28 @@
}
// - Otherwise, if T is a specialization of std::initializer_list, [...]
- // FIXME: Implement.
+ QualType E;
+ if (S.isStdInitializerList(DestType, &E)) {
+ // Check that each individual element can be copy-constructed. But since we
+ // have no place to store further information, we'll recalculate everything
+ // later.
+ InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+ S.Context.getConstantArrayType(E,
+ llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),NumArgs),
+ ArrayType::Normal, 0));
+ InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
+ 0, HiddenArray);
+ for (unsigned i = 0; i < NumArgs; ++i) {
+ Element.setElementIndex(i);
+ if (!S.CanPerformCopyInitialization(Element, Args[i])) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_InitListElementCopyFailure);
+ return true;
+ }
+ }
+ Sequence.AddStdInitializerListConstructionStep(DestType);
+ return true;
+ }
// Not a special case.
return false;
@@ -4819,7 +4850,8 @@
case SK_ArrayInit:
case SK_PassByIndirectCopyRestore:
case SK_PassByIndirectRestore:
- case SK_ProduceObjCObject: {
+ case SK_ProduceObjCObject:
+ case SK_StdInitializerList: {
assert(Args.size() == 1);
CurInit = Args.get()[0];
if (!CurInit.get()) return ExprError();
@@ -5246,6 +5278,40 @@
CK_ARCProduceObject,
CurInit.take(), 0, VK_RValue));
break;
+
+ case SK_StdInitializerList: {
+ QualType Dest = Step->Type;
+ QualType E;
+ bool Success = S.isStdInitializerList(Dest, &E);
+ (void)Success;
+ assert(Success && "Destination type changed?");
+ InitListExpr *ILE = cast<InitListExpr>(CurInit.take());
+ unsigned NumInits = ILE->getNumInits();
+ SmallVector<Expr*, 16> Converted(NumInits);
+ InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+ S.Context.getConstantArrayType(E,
+ llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+ NumInits),
+ ArrayType::Normal, 0));
+ InitializedEntity Element =InitializedEntity::InitializeElement(S.Context,
+ 0, HiddenArray);
+ for (unsigned i = 0; i < NumInits; ++i) {
+ Element.setElementIndex(i);
+ ExprResult Init = S.Owned(ILE->getInit(i));
+ ExprResult Res = S.PerformCopyInitialization(Element,
+ Init.get()->getExprLoc(),
+ Init);
+ assert(!Res.isInvalid() && "Result changed since try phase.");
+ Converted[i] = Res.take();
+ }
+ InitListExpr *Semantic = new (S.Context)
+ InitListExpr(S.Context, ILE->getLBraceLoc(),
+ Converted.data(), NumInits, ILE->getRBraceLoc());
+ Semantic->setSyntacticForm(ILE);
+ Semantic->setType(Dest);
+ CurInit = S.Owned(Semantic);
+ break;
+ }
}
}
@@ -5584,6 +5650,37 @@
// FIXME: Already diagnosed!
break;
}
+
+ case FK_InitListElementCopyFailure: {
+ // Try to perform all copies again.
+ InitListExpr* InitList = cast<InitListExpr>(Args[0]);
+ unsigned NumInits = InitList->getNumInits();
+ QualType DestType = Entity.getType();
+ QualType E;
+ bool Success = S.isStdInitializerList(DestType, &E);
+ (void)Success;
+ assert(Success && "Where did the std::initializer_list go?");
+ InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+ S.Context.getConstantArrayType(E,
+ llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+ NumInits),
+ ArrayType::Normal, 0));
+ InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
+ 0, HiddenArray);
+ // Show at most 3 errors. Otherwise, you'd get a lot of errors for errors
+ // where the init list type is wrong, e.g.
+ // std::initializer_list<void*> list = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ // FIXME: Emit a note if we hit the limit?
+ int ErrorCount = 0;
+ for (unsigned i = 0; i < NumInits && ErrorCount < 3; ++i) {
+ Element.setElementIndex(i);
+ ExprResult Init = S.Owned(InitList->getInit(i));
+ if (S.PerformCopyInitialization(Element, Init.get()->getExprLoc(), Init)
+ .isInvalid())
+ ++ErrorCount;
+ }
+ break;
+ }
}
PrintInitLocationNote(S, Entity);
@@ -5694,6 +5791,10 @@
case FK_ListConstructorOverloadFailed:
OS << "list constructor overloading failed";
break;
+
+ case FK_InitListElementCopyFailure:
+ OS << "copy construction of initializer list element failed";
+ break;
}
OS << '\n';
return;
@@ -5815,6 +5916,10 @@
case SK_ProduceObjCObject:
OS << "Objective-C object retension";
break;
+
+ case SK_StdInitializerList:
+ OS << "std::initializer_list from initializer list";
+ break;
}
}
}
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp?rev=148349&r1=148348&r2=148349&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Tue Jan 17 16:49:42 2012
@@ -55,5 +55,4 @@
emptylist({});
emptylist({}, {}, {});
}
-
}
Added: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=148349&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Tue Jan 17 16:49:42 2012
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ // libc++'s implementation
+ template <class _E>
+ class initializer_list
+ {
+ const _E* __begin_;
+ size_t __size_;
+
+ initializer_list(const _E* __b, size_t __s)
+ : __begin_(__b),
+ __size_(__s)
+ {}
+
+ public:
+ typedef _E value_type;
+ typedef const _E& reference;
+ typedef const _E& const_reference;
+ typedef size_t size_type;
+
+ typedef const _E* iterator;
+ typedef const _E* const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const {return __size_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __begin_ + __size_;}
+ };
+}
+
+struct one { char c[1]; };
+struct two { char c[2]; };
+
+struct A {
+ int a, b;
+};
+
+struct B {
+ B();
+ B(int, int);
+};
+
+void simple_list() {
+ std::initializer_list<int> il = { 1, 2, 3 };
+ std::initializer_list<double> dl = { 1.0, 2.0, 3 };
+ std::initializer_list<A> al = { {1, 2}, {2, 3}, {3, 4} };
+ std::initializer_list<B> bl = { {1, 2}, {2, 3}, {} };
+}
+
+void function_call() {
+ void f(std::initializer_list<int>);
+ f({1, 2, 3});
+
+ void g(std::initializer_list<B>);
+ g({ {1, 2}, {2, 3}, {} });
+}
Modified: cfe/trunk/test/SemaCXX/generalized-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/generalized-initializers.cpp?rev=148349&r1=148348&r2=148349&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/generalized-initializers.cpp (original)
+++ cfe/trunk/test/SemaCXX/generalized-initializers.cpp Tue Jan 17 16:49:42 2012
@@ -41,8 +41,6 @@
namespace integral {
void initializer_list() {
- std::initializer_list<int> il = { 1, 2, 3 };
- std::initializer_list<double> dl = { 1.0, 2.0, 3 };
auto l = {1, 2, 3, 4};
static_assert(same_type<decltype(l), std::initializer_list<int>>::value, "");
auto bl = {1, 2.0}; // expected-error {{cannot deduce}}
@@ -152,7 +150,7 @@
C c({1, 2}); // expected-error {{}}
// valid (by copy constructor).
- C d({1, 2L}); // expected-error {{}}
+ C d({1, 2L});
// valid
C e{1, 2};
More information about the cfe-commits
mailing list