re PR c++/60848 (Crash while experimenting with c++-0x initializer lists)
authorJason Merrill <jason@redhat.com>
Tue, 15 Jul 2014 19:16:29 +0000 (15:16 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 15 Jul 2014 19:16:29 +0000 (15:16 -0400)
PR c++/60848
PR c++/61723
* call.c (is_std_init_list): Don't check CLASSTYPE_TEMPLATE_INFO.
* class.c (finish_struct): Reject invalid definition of
std::initializer_list.

From-SVN: r212574

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/testsuite/g++.dg/cpp0x/initlist85.C
gcc/testsuite/g++.dg/cpp0x/initlist87.C [new file with mode: 0644]

index 697ba793c73d274dc5085b8164fdd15d4a858507..1d5b7d6423c40dc86aa8d22481de746fb79b5b7e 100644 (file)
@@ -1,3 +1,11 @@
+2014-07-15  Jason Merrill  <jason@redhat.com>
+
+       PR c++/60848
+       PR c++/61723
+       * call.c (is_std_init_list): Don't check CLASSTYPE_TEMPLATE_INFO.
+       * class.c (finish_struct): Reject invalid definition of
+       std::initializer_list.
+
 2014-07-15  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * call.c (convert_like_real): Call print_z_candidate and inform only
index 6da1218042f53bf838992642a52d460f2f347019..ea8cb5f78c896787af3fc0a620800b2a628116d4 100644 (file)
@@ -9701,7 +9701,6 @@ is_std_init_list (tree type)
   type = TYPE_MAIN_VARIANT (type);
   return (CLASS_TYPE_P (type)
          && CP_TYPE_CONTEXT (type) == std_node
-         && CLASSTYPE_TEMPLATE_INFO (type)
          && strcmp (TYPE_NAME_STRING (type), "initializer_list") == 0);
 }
 
index dbd8d3d3aa58c28e5751dc63cda37b5ee8360df7..e4523c7b1f686fa4b4286a0b83433ea2fc755338 100644 (file)
@@ -6695,6 +6695,28 @@ finish_struct (tree t, tree attributes)
   else
     finish_struct_1 (t);
 
+  if (is_std_init_list (t))
+    {
+      /* People keep complaining that the compiler crashes on an invalid
+        definition of initializer_list, so I guess we should explicitly
+        reject it.  What the compiler internals care about is that it's a
+        template and has a pointer field followed by an integer field.  */
+      bool ok = false;
+      if (processing_template_decl)
+       {
+         tree f = next_initializable_field (TYPE_FIELDS (t));
+         if (f && TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE)
+           {
+             f = next_initializable_field (DECL_CHAIN (f));
+             if (f && TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
+               ok = true;
+           }
+       }
+      if (!ok)
+       fatal_error ("definition of std::initializer_list does not match "
+                    "#include <initializer_list>");
+    }
+
   input_location = saved_loc;
 
   TYPE_BEING_DEFINED (t) = 0;
index 0eb8e26b8cfd0f351cfda64e303d2e637b41edf3..fa4fb617b33e59fb33ea71ab8fca7ec68449f137 100644 (file)
@@ -3,12 +3,14 @@
 
 namespace std
 {
-  struct initializer_list {};
+  struct initializer_list {};  // { dg-message "initializer_list" }
 }
 
 void foo(std::initializer_list &);
 
 void f()
 {
-  foo({1, 2});                 // { dg-error "" }
+  foo({1, 2});
 }
+
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist87.C b/gcc/testsuite/g++.dg/cpp0x/initlist87.C
new file mode 100644 (file)
index 0000000..fd7586d
--- /dev/null
@@ -0,0 +1,35 @@
+// PR c++/61723
+// { dg-do compile { target c++11 } }
+
+namespace std {
+  template < class > struct initializer_list // { dg-message "initializer_list" }
+  {
+#if BUG1
+    int _M_len;
+#endif
+    const int *begin ();
+    const int *end ();
+  };
+}
+
+struct J
+{
+    J (const int &);
+    template < typename InputIterator > J (InputIterator, InputIterator);
+    J (std::initializer_list < int >p1):J (p1.begin (), p1.end ()) { }
+};
+
+struct L
+{
+    L ():dim (0) { }
+    J dim;
+};
+
+void
+fn1 ()
+{
+    L spec;
+    spec.dim = { };
+}
+
+// { dg-prune-output "compilation terminated" }