[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