summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-07-15 15:16:29 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-07-15 15:16:29 -0400
commit0090cacae6e9f0d3649dff9e428ea92a10d69cfa (patch)
tree4d907344ad2b91570c02586a01550c3cf0448eb6
parente27989c4f4ff56ea84f94135cfc8f574d66459bb (diff)
downloadgcc-0090cacae6e9f0d3649dff9e428ea92a10d69cfa.tar.gz
re PR c++/60848 (Crash while experimenting with c++-0x initializer lists)
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
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c1
-rw-r--r--gcc/cp/class.c22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist85.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist87.C35
5 files changed, 69 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 697ba793c73..1d5b7d6423c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6da1218042f..ea8cb5f78c8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);
}
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index dbd8d3d3aa5..e4523c7b1f6 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist85.C b/gcc/testsuite/g++.dg/cpp0x/initlist85.C
index 0eb8e26b8cf..fa4fb617b33 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist85.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist85.C
@@ -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
index 00000000000..fd7586d27d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist87.C
@@ -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" }