C++ PATCH for c++/78345, ICE with lambda as array initializer

Submitted by Jason Merrill on March 17, 2017, 6:55 p.m.

Details

Message ID CADzB+2kwEWOn-0D3SHcfbLDzZ8fpWt6tOskHM6_Bm4JUAo8EKg@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill March 17, 2017, 6:55 p.m.
build_aggr_init was blithely passing most any initializer on to
build_vec_init, which saw a CONSTRUCTOR and assumed that it would be
of the right type, leading to an ICE.  Fixed by not taking the
INIT_EXPR shortcut if the CONSTRUCTOR has the wrong type.

That returned us to the GCC 6 state, where we would sometimes silently
accept a single expression used as an array initializer.  I think
that's a remnant of an extension that predates my work on the
compiler, and several places already reject that pattern, so let's
reject it here with a permerror.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 5929f60b57733160099e1d34dde93d01ae2e0319
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 17 07:45:02 2017 -0400

            PR c++/78345 - ICE initializing array from lambda.
    
            * init.c (build_aggr_init): Check array initializer.
            (build_vec_init): Check the type of a CONSTRUCTOR.

Patch hide | download patch | download mbox

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 8bfcbde..ebb1245 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1617,6 +1617,10 @@  build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
   if (init == error_mark_node)
     return error_mark_node;
 
+  location_t init_loc = (init
+			 ? EXPR_LOC_OR_LOC (init, input_location)
+			 : location_of (exp));
+
   TREE_READONLY (exp) = 0;
   TREE_THIS_VOLATILE (exp) = 0;
 
@@ -1656,6 +1660,16 @@  build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
 	    TREE_TYPE (init) = cv_unqualified (itype);
 	  from_array = (itype && same_type_p (TREE_TYPE (init),
 					      TREE_TYPE (exp)));
+
+	  if (init && !from_array
+	      && !BRACE_ENCLOSED_INITIALIZER_P (init))
+	    {
+	      if (complain & tf_error)
+		permerror (init_loc, "array must be initialized "
+			   "with a brace-enclosed initializer");
+	      else
+		return error_mark_node;
+	    }
 	}
 
       stmt_expr = build_vec_init (exp, NULL_TREE, init,
@@ -3945,6 +3959,9 @@  build_vec_init (tree base, tree maxindex, tree init,
 	  ? vec_copy_assign_is_trivial (inner_elt_type, init)
 	  : !TYPE_NEEDS_CONSTRUCTING (type))
       && ((TREE_CODE (init) == CONSTRUCTOR
+	   && (BRACE_ENCLOSED_INITIALIZER_P (init)
+	       || (same_type_ignoring_top_level_qualifiers_p
+		   (atype, TREE_TYPE (init))))
 	   /* Don't do this if the CONSTRUCTOR might contain something
 	      that might throw and require us to clean up.  */
 	   && (vec_safe_is_empty (CONSTRUCTOR_ELTS (init))
diff --git a/gcc/testsuite/g++.dg/init/array48.C b/gcc/testsuite/g++.dg/init/array48.C
new file mode 100644
index 0000000..27fec13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array48.C
@@ -0,0 +1,7 @@ 
+// PR c++/78345
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  const int i;
+} a[1] = []{};			// { dg-error "array.*init" }
diff --git a/gcc/testsuite/g++.dg/torture/pr70499.C b/gcc/testsuite/g++.dg/torture/pr70499.C
index 954fea5..e08c26f 100644
--- a/gcc/testsuite/g++.dg/torture/pr70499.C
+++ b/gcc/testsuite/g++.dg/torture/pr70499.C
@@ -1,5 +1,5 @@ 
 // { dg-do compile }
-// { dg-additional-options "-w -Wno-psabi" }
+// { dg-additional-options "-w -fpermissive -Wno-psabi" }
 // { dg-additional-options "-mavx" { target x86_64-*-* i?86-*-* } }
 
 typedef double __m256d __attribute__ ((__vector_size__ (32), __may_alias__));