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 <ja...@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.

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__));

Reply via email to