[cfe-commits] r159896 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp test/CodeGenCXX/cxx0x-initializer-constructors.cpp test/SemaCXX/constant-expression-cxx11.cpp test/SemaCXX/cxx0x-initializer-aggregates.cpp test/SemaCXX/dcl_init_aggr.cpp

Richard Smith richard-llvm at metafoo.co.uk
Sat Jul 7 01:35:57 PDT 2012


Author: rsmith
Date: Sat Jul  7 03:35:56 2012
New Revision: 159896

URL: http://llvm.org/viewvc/llvm-project?rev=159896&view=rev
Log:
PR12670: Support for initializing an array of non-aggregate class type from an
initializer list. Patch by Olivier Goffart, with extra testcases by Meador Inge
and Daniel Lunow.

Added:
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-constructors.cpp
Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
    cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=159896&r1=159895&r2=159896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Jul  7 03:35:56 2012
@@ -687,22 +687,21 @@
   } else if (DeclType->isVectorType()) {
     CheckVectorType(Entity, IList, DeclType, Index,
                     StructuredList, StructuredIndex);
-  } else if (DeclType->isAggregateType()) {
-    if (DeclType->isRecordType()) {
-      RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
-      CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
-                            SubobjectIsDesignatorContext, Index,
-                            StructuredList, StructuredIndex,
-                            TopLevelObject);
-    } else if (DeclType->isArrayType()) {
-      llvm::APSInt Zero(
-                      SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
-                      false);
-      CheckArrayType(Entity, IList, DeclType, Zero,
-                     SubobjectIsDesignatorContext, Index,
-                     StructuredList, StructuredIndex);
-    } else
-      llvm_unreachable("Aggregate that isn't a structure or array?!");
+  } else if (DeclType->isRecordType()) {
+    assert(DeclType->isAggregateType() &&
+           "non-aggregate records should be handed in CheckSubElementType");
+    RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+    CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
+                          SubobjectIsDesignatorContext, Index,
+                          StructuredList, StructuredIndex,
+                          TopLevelObject);
+  } else if (DeclType->isArrayType()) {
+    llvm::APSInt Zero(
+                    SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
+                    false);
+    CheckArrayType(Entity, IList, DeclType, Zero,
+                   SubobjectIsDesignatorContext, Index,
+                   StructuredList, StructuredIndex);
   } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
     // This type is invalid, issue a diagnostic.
     ++Index;
@@ -710,19 +709,6 @@
       SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
         << DeclType;
     hadError = true;
-  } else if (DeclType->isRecordType()) {
-    // C++ [dcl.init]p14:
-    //   [...] If the class is an aggregate (8.5.1), and the initializer
-    //   is a brace-enclosed list, see 8.5.1.
-    //
-    // Note: 8.5.1 is handled below; here, we diagnose the case where
-    // we have an initializer list and a destination type that is not
-    // an aggregate.
-    // FIXME: In C++0x, this is yet another form of initialization.
-    if (!VerifyOnly)
-      SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
-        << DeclType << IList->getSourceRange();
-    hadError = true;
   } else if (DeclType->isReferenceType()) {
     CheckReferenceType(Entity, IList, DeclType, Index,
                        StructuredList, StructuredIndex);
@@ -747,18 +733,25 @@
                                           unsigned &StructuredIndex) {
   Expr *expr = IList->getInit(Index);
   if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
-    unsigned newIndex = 0;
-    unsigned newStructuredIndex = 0;
-    InitListExpr *newStructuredList
-      = getStructuredSubobjectInit(IList, Index, ElemType,
-                                   StructuredList, StructuredIndex,
-                                   SubInitList->getSourceRange());
-    CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
-                          newStructuredList, newStructuredIndex);
-    ++StructuredIndex;
-    ++Index;
-    return;
-  } else if (ElemType->isScalarType()) {
+    if (!ElemType->isRecordType() || ElemType->isAggregateType()) {
+      unsigned newIndex = 0;
+      unsigned newStructuredIndex = 0;
+      InitListExpr *newStructuredList
+        = getStructuredSubobjectInit(IList, Index, ElemType,
+                                     StructuredList, StructuredIndex,
+                                     SubInitList->getSourceRange());
+      CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
+                            newStructuredList, newStructuredIndex);
+      ++StructuredIndex;
+      ++Index;
+      return;
+    }
+    assert(SemaRef.getLangOpts().CPlusPlus &&
+           "non-aggregate records are only possible in C++");
+    // C++ initialization is handled later.
+  }
+
+  if (ElemType->isScalarType()) {
     return CheckScalarType(Entity, IList, ElemType, Index,
                            StructuredList, StructuredIndex);
   } else if (ElemType->isReferenceType()) {

Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp?rev=159896&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp Sat Jul  7 03:35:56 2012
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+namespace std {
+  typedef decltype(sizeof(int)) size_t;
+
+  template <typename E>
+  struct initializer_list
+  {
+    const E *p;
+    size_t n;
+    initializer_list(const E *p, size_t n) : p(p), n(n) {}
+  };
+
+  struct string {
+    string(const char *);
+  };
+
+  template<typename A, typename B>
+  struct pair {
+    pair(const A&, const B&);
+  };
+}
+
+namespace bullet2 {
+  double ad[] = { 1, 2.0 };
+  int ai[] = { 1, 2.0 };  // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}}
+
+  struct S2 {
+    int m1;
+    double m2, m3;
+  };
+
+  S2 s21 = { 1, 2, 3.0 };
+  S2 s22 { 1.0, 2, 3 };  // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}}
+  S2 s23 { };
+}
+
+namespace bullet4_example1 {
+  struct S {
+    S(std::initializer_list<double> d) {}
+    S(std::initializer_list<int> i) {}
+    S() {}
+  };
+
+  S s1 = { 1.0, 2.0, 3.0 };
+  S s2 = { 1, 2, 3 };
+  S s3 = { };
+}
+
+namespace bullet4_example2 {
+  struct Map {
+    Map(std::initializer_list<std::pair<std::string,int>>) {}
+  };
+
+  Map ship = {{"Sophie",14}, {"Surprise",28}};
+}
+
+namespace bullet4_example3 {
+  struct S {
+    S(int, double, double) {}
+    S() {}
+  };
+
+  S s1 = { 1, 2, 3.0 };
+  // FIXME: This is an ill-formed narrowing initialization.
+  S s2 { 1.0, 2, 3 };
+  S s3 {};
+}
+
+namespace bullet5 {
+  struct S {
+    S(std::initializer_list<double>) {}
+    S(const std::string &) {}
+  };
+
+  const S& r1 = { 1, 2, 3.0 };
+  const S& r2 = { "Spinach" };
+  S& r3 = { 1, 2, 3 };  // expected-error {{non-const lvalue reference to type 'bullet5::S' cannot bind to an initializer list temporary}}
+  const int& i1 = { 1 };
+  const int& i2 = { 1.1 };  // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} expected-warning {{implicit conversion}}
+  const int (&iar)[2] = { 1, 2 };
+}
+
+namespace bullet6 {
+  int x1 {2};
+  int x2 {2.0};  // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}}
+}
+
+namespace bullet7 {
+  int** pp {};
+}
+
+namespace bullet8 {
+  struct A { int i; int j; };
+  A a1 { 1, 2 };
+  A a2 { 1.2 };  // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} expected-warning {{implicit conversion}}
+
+  struct B {
+    B(std::initializer_list<int> i) {}
+  };
+  B b1 { 1, 2 };
+  B b2 { 1, 2.0 };
+
+  struct C {
+    C(int i, double j) {}
+  };
+  C c1 = { 1, 2.2 };
+  // FIXME: This is an ill-formed narrowing initialization.
+  C c2 = { 1.1, 2 };  // expected-warning {{implicit conversion}}
+
+  int j { 1 };
+  int k { };
+}

Added: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-constructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-constructors.cpp?rev=159896&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-constructors.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-constructors.cpp Sat Jul  7 03:35:56 2012
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s | FileCheck %s
+
+struct S {
+  S(int x) { }
+  S(int x, double y, double z) { }
+};
+
+void fn1() {
+  // CHECK: define void @_Z3fn1v
+  S s { 1 };
+  // CHECK: alloca %struct.S, align 1
+  // CHECK: call void @_ZN1SC1Ei(%struct.S* %s, i32 1)
+}
+
+void fn2() {
+  // CHECK: define void @_Z3fn2v
+  S s { 1, 2.0, 3.0 };
+  // CHECK: alloca %struct.S, align 1
+  // CHECK: call void @_ZN1SC1Eidd(%struct.S* %s, i32 1, double 2.000000e+00, double 3.000000e+00)
+}
+
+void fn3() {
+  // CHECK: define void @_Z3fn3v
+  S sa[] { { 1 }, { 2 }, { 3 } };
+  // CHECK: alloca [3 x %struct.S], align 1
+  // CHECK: call void @_ZN1SC1Ei(%struct.S* %arrayinit.begin, i32 1)
+  // CHECK: call void @_ZN1SC1Ei(%struct.S* %arrayinit.element, i32 2)
+  // CHECK: call void @_ZN1SC1Ei(%struct.S* %arrayinit.element1, i32 3)
+}
+
+void fn4() {
+  // CHECK: define void @_Z3fn4v
+  S sa[] { { 1, 2.0, 3.0 }, { 4, 5.0, 6.0 } };
+  // CHECK: alloca [2 x %struct.S], align 1
+  // CHECK: call void @_ZN1SC1Eidd(%struct.S* %arrayinit.begin, i32 1, double 2.000000e+00, double 3.000000e+00)
+  // CHECK: call void @_ZN1SC1Eidd(%struct.S* %arrayinit.element, i32 4, double 5.000000e+00, double 6.000000e+00)
+}

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=159896&r1=159895&r2=159896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Sat Jul  7 03:35:56 2012
@@ -1318,3 +1318,15 @@
   // actually call it.
   static_assert(S{}.t == 0, "");
 }
+
+namespace PR12670 {
+  struct S {
+    constexpr S(int a0) : m(a0) {}
+    constexpr S() : m(6) {}
+    int m;
+  };
+  constexpr S x[3] = { {4}, 5 };
+  static_assert(x[0].m == 4, "");
+  static_assert(x[1].m == 5, "");
+  static_assert(x[2].m == 6, "");
+}

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp?rev=159896&r1=159895&r2=159896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp Sat Jul  7 03:35:56 2012
@@ -87,3 +87,32 @@
     (void)test4{{{1}}}; // expected-note {{in instantiation of template class 'array_explicit_conversion::A<-1>' requested here}}
   }
 }
+
+namespace sub_constructor {
+  struct DefaultConstructor { // expected-note 2 {{not viable}}
+    DefaultConstructor(); // expected-note  {{not viable}}
+    int x;
+  };
+  struct NoDefaultConstructor1 { // expected-note 2 {{not viable}}
+    NoDefaultConstructor1(int); // expected-note {{not viable}}
+    int x;
+  };
+  struct NoDefaultConstructor2 {  // expected-note 4 {{not viable}}
+    NoDefaultConstructor2(int,int); // expected-note 2 {{not viable}}
+    int x;
+  };
+
+  struct Aggr {
+    DefaultConstructor a;
+    NoDefaultConstructor1 b;
+    NoDefaultConstructor2 c;
+  };
+
+  Aggr ok1 { {}, {0} , {0,0} };
+  Aggr ok2 = { {}, {0} , {0,0} };
+  Aggr too_many { {0} , {0} , {0,0} }; // expected-error {{no matching constructor for initialization}}
+  Aggr too_few { {} , {0} , {0} }; // expected-error {{no matching constructor for initialization}}
+  Aggr invalid { {} , {&ok1} , {0,0} }; // expected-error {{no matching constructor for initialization}}
+  NoDefaultConstructor2 array_ok[] = { {0,0} , {0,1} };
+  NoDefaultConstructor2 array_error[] = { {0,0} , {0} }; // expected-error {{no matching constructor for initialization}}
+}
\ No newline at end of file

Modified: cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp?rev=159896&r1=159895&r2=159896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp (original)
+++ cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp Sat Jul  7 03:35:56 2012
@@ -15,7 +15,7 @@
 };
 NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{non-aggregate type 'NonAggregate' cannot be initialized with an initializer list}}
 
-NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'NonAggregate' with an initializer list}}
+NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{non-aggregate type 'NonAggregate' cannot be initialized with an initializer list}}
 
 
 // C++ [dcl.init.aggr]p3





More information about the cfe-commits mailing list