Here, we were going down the wrong path in perform_member_init because of
the incorrect parens around the mem-initializer for the array.  And then
cxx_eval_vec_init_1 didn't know what to do with a CONSTRUCTOR as the
initializer.  The latter issue was a straightforward fix, but I also wanted
to fix us silently accepting the parens, which led to factoring out handling
of TREE_LIST and flexarrays.  The latter led to adjusting the expected
behavior on flexary29.C: we should complain about the initializer, but not
complain about a missing initializer.

As I commented on PR 92812, in this process I noticed that we weren't
handling C++20 parenthesized aggregate initialization as a mem-initializer.
So my TREE_LIST handling includes a commented out section that should
probably be part of a future fix for that issue; with it uncommented we
continue to crash on the testcase in C++20 mode, but should instead complain
about the braced-init-list not being a valid initializer for an A.

Tested x86_64-pc-linux-gnu, applying to trunk.

        PR c++/86917
        * init.c (perform_member_init): Simplify.
        * constexpr.c (cx_check_missing_mem_inits): Allow uninitialized
        flexarray.
        (cxx_eval_vec_init_1): Handle CONSTRUCTOR.
---
 gcc/cp/constexpr.c                            | 11 ++++-
 gcc/cp/init.c                                 | 48 ++++++-------------
 .../g++.dg/cpp0x/constexpr-array23.C          | 24 ++++++++++
 gcc/testsuite/g++.dg/cpp0x/desig2.C           |  4 +-
 gcc/testsuite/g++.dg/cpp0x/desig3.C           |  4 +-
 gcc/testsuite/g++.dg/cpp0x/desig4.C           |  4 +-
 gcc/testsuite/g++.dg/ext/array1.C             |  2 +-
 gcc/testsuite/g++.dg/ext/flexary29.C          |  2 +-
 gcc/testsuite/g++.dg/init/array28.C           |  2 +-
 9 files changed, 57 insertions(+), 44 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 3962763fb21..c35ec5acc97 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -826,7 +826,12 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool 
complain)
                return true;
              continue;
            }
-         ftype = strip_array_types (TREE_TYPE (field));
+         ftype = TREE_TYPE (field);
+         if (!ftype || !TYPE_P (ftype) || !COMPLETE_TYPE_P (ftype))
+           /* A flexible array can't be intialized here, so don't complain
+              that it isn't.  */
+           continue;
+         ftype = strip_array_types (ftype);
          if (type_has_constexpr_default_constructor (ftype))
            {
              /* It's OK to skip a member with a trivial constexpr ctor.
@@ -3784,6 +3789,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree 
atype, tree init,
   unsigned HOST_WIDE_INT i;
   tsubst_flags_t complain = ctx->quiet ? tf_none : tf_warning_or_error;
 
+  if (init && TREE_CODE (init) == CONSTRUCTOR)
+    return cxx_eval_bare_aggregate (ctx, init, lval,
+                                   non_constant_p, overflow_p);
+
   /* For the default constructor, build up a call to the default
      constructor of the element type.  We only need to handle class types
      here, as for a constructor to be constexpr, all members must be
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 543d127abcd..625062b60ad 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -801,6 +801,17 @@ perform_member_init (tree member, tree init)
                    member);
     }
 
+  if (maybe_reject_flexarray_init (member, init))
+    return;
+
+  if (init && TREE_CODE (init) == TREE_LIST
+      && (DIRECT_LIST_INIT_P (TREE_VALUE (init))
+         /* FIXME C++20 parenthesized aggregate init (PR 92812).  */
+         || !(/* cxx_dialect >= cxx2a ? CP_AGGREGATE_TYPE_P (type) */
+              /* :  */CLASS_TYPE_P (type))))
+    init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
+                                           tf_warning_or_error);
+
   if (init == void_type_node)
     {
       /* mem() means value-initialization.  */
@@ -832,12 +843,7 @@ perform_member_init (tree member, tree init)
     }
   else if (init
           && (TYPE_REF_P (type)
-              /* Pre-digested NSDMI.  */
-              || (((TREE_CODE (init) == CONSTRUCTOR
-                    && TREE_TYPE (init) == type)
-                   /* { } mem-initializer.  */
-                   || (TREE_CODE (init) == TREE_LIST
-                       && DIRECT_LIST_INIT_P (TREE_VALUE (init))))
+              || (TREE_CODE (init) == CONSTRUCTOR
                   && (CP_AGGREGATE_TYPE_P (type)
                       || is_std_init_list (type)))))
     {
@@ -847,10 +853,7 @@ perform_member_init (tree member, tree init)
         persists until the constructor exits."  */
       unsigned i; tree t;
       releasing_vec cleanups;
-      if (TREE_CODE (init) == TREE_LIST)
-       init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
-                                               tf_warning_or_error);
-      if (TREE_TYPE (init) != type)
+      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init), type))
        {
          if (BRACE_ENCLOSED_INITIALIZER_P (init)
              && CP_AGGREGATE_TYPE_P (type))
@@ -876,23 +879,6 @@ perform_member_init (tree member, tree init)
     {
       if (TREE_CODE (type) == ARRAY_TYPE)
        {
-         if (init)
-           {
-             /* Check to make sure the member initializer is valid and
-                something like a CONSTRUCTOR in: T a[] = { 1, 2 } and
-                if it isn't, return early to avoid triggering another
-                error below.  */
-             if (maybe_reject_flexarray_init (member, init))
-               return;
-
-             if (TREE_CODE (init) != TREE_LIST || TREE_CHAIN (init))
-               init = error_mark_node;
-             else
-               init = TREE_VALUE (init);
-
-             if (BRACE_ENCLOSED_INITIALIZER_P (init))
-               init = digest_init (type, init, tf_warning_or_error);
-           }
          if (init == NULL_TREE
              || same_type_ignoring_top_level_qualifiers_p (type,
                                                            TREE_TYPE (init)))
@@ -962,16 +948,10 @@ perform_member_init (tree member, tree init)
                                                      /*using_new=*/false,
                                                      /*complain=*/true);
        }
-      else if (TREE_CODE (init) == TREE_LIST)
-       /* There was an explicit member initialization.  Do some work
-          in that case.  */
-       init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
-                                               tf_warning_or_error);
 
       maybe_warn_list_ctor (member, init);
 
-      /* Reject a member initializer for a flexible array member.  */
-      if (init && !maybe_reject_flexarray_init (member, init))
+      if (init)
        finish_expr_stmt (cp_build_modify_expr (input_location, decl,
                                                INIT_EXPR, init,
                                                tf_warning_or_error));
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C
new file mode 100644
index 00000000000..1323271a0a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C
@@ -0,0 +1,24 @@
+// PR c++/86917
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  constexpr A () : c (0) {}
+  static const A z;
+  unsigned c;
+};
+
+struct B
+{                              // This should really be target { ! c++2a }
+  typedef A W[4];              // { dg-error "paren" "" { target *-*-* } .+1 }
+  constexpr B () : w ({ A::z, A::z, A::z, A::z }) {} // { dg-error "constant" }
+  W w;
+};
+
+struct C
+{
+  C ();
+  B w[1];
+};
+
+C::C () { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/desig2.C 
b/gcc/testsuite/g++.dg/cpp0x/desig2.C
index 5ac2d15d952..21724e04796 100644
--- a/gcc/testsuite/g++.dg/cpp0x/desig2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/desig2.C
@@ -15,9 +15,9 @@ private:
 };
 
 SomeClass::SomeClass()
- : member({
+ : member{
    [INDEX1] = { .field = 0 },
    [INDEX2] = { .field = 1 }
- })
+ }
 {
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/desig3.C 
b/gcc/testsuite/g++.dg/cpp0x/desig3.C
index 0a50b742d45..5c27833d5c1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/desig3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/desig3.C
@@ -13,9 +13,9 @@ private:
 };
 
 SomeClass::SomeClass()
- : member({
+ : member{
    [INDEX1] = { .field = 0 },
    [INDEX2] = { .field = 1 }
- })
+ }
 {
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/desig4.C 
b/gcc/testsuite/g++.dg/cpp0x/desig4.C
index ff88d82adc0..4180e0983ea 100644
--- a/gcc/testsuite/g++.dg/cpp0x/desig4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/desig4.C
@@ -13,9 +13,9 @@ private:
 };
 
 SomeClass::SomeClass()
- : member({
+ : member{
    [INDEX1] = { .field = 0 },  // { dg-error "constant expression" }
    [INDEX2] = { .field = 1 }   // { dg-error "constant expression" }
- })
+ }
 {
 }
diff --git a/gcc/testsuite/g++.dg/ext/array1.C 
b/gcc/testsuite/g++.dg/ext/array1.C
index 7e54dc91939..f4c3630be16 100644
--- a/gcc/testsuite/g++.dg/ext/array1.C
+++ b/gcc/testsuite/g++.dg/ext/array1.C
@@ -3,7 +3,7 @@
 
 class A { 
 public: 
-  A() : argc(0), argv() { }; 
+  A() : argc(0), argv() { };   // { dg-error "flexible array" }
 private: 
   int argc; 
   char* argv[]; 
diff --git a/gcc/testsuite/g++.dg/ext/flexary29.C 
b/gcc/testsuite/g++.dg/ext/flexary29.C
index a696fd9804f..8fef06e6a97 100644
--- a/gcc/testsuite/g++.dg/ext/flexary29.C
+++ b/gcc/testsuite/g++.dg/ext/flexary29.C
@@ -4,7 +4,7 @@
 
 struct A
 {
-  constexpr A() : i(), x() {}
+  constexpr A() : i(), x() {}  // { dg-error "flexible" }
   int i;
   char x[];
 };
diff --git a/gcc/testsuite/g++.dg/init/array28.C 
b/gcc/testsuite/g++.dg/init/array28.C
index 8cf19ba4331..9869354279d 100644
--- a/gcc/testsuite/g++.dg/init/array28.C
+++ b/gcc/testsuite/g++.dg/init/array28.C
@@ -2,6 +2,6 @@
 
 struct Foo { explicit Foo(int) { } };
 struct Goo {
-  Goo() : x(Foo(4), Foo(5)) { } // { dg-error "array" }
+  Goo() : x(Foo(4), Foo(5)) { } // { dg-error "" }
   Foo x[2];
 };

base-commit: 5bc9d2f5ed4c39a7cad74db34e2bb125e012fa60
-- 
2.18.1

Reply via email to