c++: Fix flexible array with synthesized constructor.
authorJason Merrill <jason@redhat.com>
Sun, 9 Feb 2020 23:47:34 +0000 (00:47 +0100)
committerJason Merrill <jason@redhat.com>
Mon, 10 Feb 2020 08:50:34 +0000 (09:50 +0100)
We were already rejecting initialization of a flexible array member in a
constructor; we similarly shouldn't try to clean it up.

PR c++/93618
* tree.c (array_of_unknown_bound_p): New.
* init.c (perform_member_init): Do nothing for flexible arrays.

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/ext/flexary35.C [new file with mode: 0644]

index 90f26c90918df78684a57042bdb73add685c37c7..876e2ebf987063f6945fe1678afed0e6e92c4ec0 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-10  Jason Merrill  <jason@redhat.com>
+
+       PR c++/93618
+       * tree.c (array_of_unknown_bound_p): New.
+       * init.c (perform_member_init): Do nothing for flexible arrays.
+
 2020-02-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/93633
index 037d3b6453825508f226cb57aff6ddc00e173874..043bc404140b6bd19da4678c93aaf6731e514d18 100644 (file)
@@ -7424,6 +7424,7 @@ extern tree build_exception_variant               (tree, tree);
 extern tree bind_template_template_parm                (tree, tree);
 extern tree array_type_nelts_total             (tree);
 extern tree array_type_nelts_top               (tree);
+extern bool array_of_unknown_bound_p           (const_tree);
 extern tree break_out_target_exprs             (tree, bool = false);
 extern tree build_ctor_subob_ref               (tree, tree, tree);
 extern tree replace_placeholders               (tree, tree, bool * = NULL);
index 625062b60adb5200024d7c8a274abb810ddf9b1b..d480660445e8ee66c814ec6ff32af50b6aca4d51 100644 (file)
@@ -801,8 +801,11 @@ perform_member_init (tree member, tree init)
                    member);
     }
 
-  if (maybe_reject_flexarray_init (member, init))
-    return;
+  if (array_of_unknown_bound_p (type))
+    {
+      maybe_reject_flexarray_init (member, init);
+      return;
+    }
 
   if (init && TREE_CODE (init) == TREE_LIST
       && (DIRECT_LIST_INIT_P (TREE_VALUE (init))
index fda630790a242e75c5fdbb323bc124782caf52cb..eb540f851eeb14b7c9c3990d20a6b285670c2344 100644 (file)
@@ -1135,6 +1135,15 @@ build_array_of_n_type (tree elt, int n)
   return build_cplus_array_type (elt, build_index_type (size_int (n - 1)));
 }
 
+/* True iff T is an array of unknown bound.  */
+
+bool
+array_of_unknown_bound_p (const_tree t)
+{
+  return (TREE_CODE (t) == ARRAY_TYPE
+         && !TYPE_DOMAIN (t));
+}
+
 /* True iff T is an N3639 array of runtime bound (VLA).  These were approved
    for C++14 but then removed.  This should only be used for N3639
    specifically; code wondering more generally if something is a VLA should use
diff --git a/gcc/testsuite/g++.dg/ext/flexary35.C b/gcc/testsuite/g++.dg/ext/flexary35.C
new file mode 100644 (file)
index 0000000..b62c718
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/93618
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+template <typename T>
+struct C {
+  ~C () = default;
+  T *p = nullptr;
+};
+
+class A {
+  struct B {
+    int c;
+    C<B*> d[];
+  };
+  void foo (int f) { B s; s.c = f; }
+  B e;
+};