re PR c++/80135 (ICE in output_constructor_regular_field, at varasm.c:4968)
authorJakub Jelinek <jakub@redhat.com>
Fri, 15 Dec 2017 20:20:00 +0000 (21:20 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 15 Dec 2017 20:20:00 +0000 (21:20 +0100)
PR c++/80135
PR c++/81922
* typeck2.c (digest_init_r): Change nested argument type from bool to
int.  Use code instead of TREE_CODE (type) where possible.  If
nested == 2, diagnose initialization of flexible array member with
STRING_CST.  Pass nested to process_init_constructor.  Formatting fix.
(digest_init, digest_init_flags): Adjust digest_init_r caller.
(massage_init_elt): Add nested argument.  Pass 2 instead of 1 to
digest_init_r's nested argument if nested is non-zero.
(process_init_constructor_array): Add nested argument.  If nested == 2,
diagnose initialization of flexible array member with non-empty
braced enclosed list.  Pass nested to massage_init_elt.
(process_init_constructor_record, process_init_constructor_union): Add
nested argument, pass it to massage_init_elt.
(process_init_constructor): Add nested argument, pass it to
process_init_constructor_{array,record,union}.
* init.c (find_field_init): Renamed to ...
(find_flexarray_init): ... this.  Return NULL_TREE if init is
error_mark_node.  Don't look through nested CONSTRUCTORs.
(warn_placement_new_too_small): Adjust caller.

* g++.dg/warn/Wplacement-new-size-1.C (fBx1): Initialize nested
flexible array member only with {}.  Add dg-warning.
(fBx2, fBx3): Remove.
* g++.dg/warn/Wplacement-new-size-2.C (fBx1): Initialize nested
flexible array member only with {}.  Add dg-warning.
(fBx2, fBx3): Remove.
* g++.dg/warn/Wplacement-new-size-6.C: New test.
* g++.dg/ext/flexary13.C (main): Remove test for initialization
of nested flexible array member with non-empty initializer.
* g++.dg/ext/flexary25.C: New test.
* g++.dg/ext/flexary26.C: New test.
* g++.dg/ext/flexary27.C: New test.
* g++.dg/parse/pr43765.C: Expect diagnostics about initialization
of nested flexible array member with non-empty initializer.  Expect
C++2A diagnostics about mixing of designated and non-designated
initializers.

From-SVN: r255703

12 files changed:
gcc/cp/ChangeLog
gcc/cp/init.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/flexary13.C
gcc/testsuite/g++.dg/ext/flexary25.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/flexary26.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/flexary27.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/pr43765.C
gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C
gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C
gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C [new file with mode: 0644]

index 1108aeb890c00646898191df859a5f9602b91632..488b9f3f59970472b40d3b72d12fa0c22e667593 100644 (file)
@@ -1,5 +1,26 @@
 2017-12-15  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/80135
+       PR c++/81922
+       * typeck2.c (digest_init_r): Change nested argument type from bool to
+       int.  Use code instead of TREE_CODE (type) where possible.  If
+       nested == 2, diagnose initialization of flexible array member with
+       STRING_CST.  Pass nested to process_init_constructor.  Formatting fix.
+       (digest_init, digest_init_flags): Adjust digest_init_r caller.
+       (massage_init_elt): Add nested argument.  Pass 2 instead of 1 to
+       digest_init_r's nested argument if nested is non-zero.
+       (process_init_constructor_array): Add nested argument.  If nested == 2,
+       diagnose initialization of flexible array member with non-empty
+       braced enclosed list.  Pass nested to massage_init_elt.
+       (process_init_constructor_record, process_init_constructor_union): Add
+       nested argument, pass it to massage_init_elt.
+       (process_init_constructor): Add nested argument, pass it to
+       process_init_constructor_{array,record,union}.
+       * init.c (find_field_init): Renamed to ...
+       (find_flexarray_init): ... this.  Return NULL_TREE if init is
+       error_mark_node.  Don't look through nested CONSTRUCTORs.
+       (warn_placement_new_too_small): Adjust caller.
+
        PR c++/83217
        * decl.c (cp_finish_decomp): If decl's type is REFERENCE_TYPE,
        call complete_type (TREE_TYPE (type)).
index c417c6ba0d5d6d4f0583c893d67f501a816eade5..daa62392857f80a772d594793b89d03748f51f90 100644 (file)
@@ -2453,13 +2453,13 @@ throw_bad_array_new_length (void)
   return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
 }
 
-/* Attempt to find the initializer for field T in the initializer INIT,
-   when non-null.  Returns the initializer when successful and NULL
-   otherwise.  */
+/* Attempt to find the initializer for flexible array field T in the
+   initializer INIT, when non-null.  Returns the initializer when
+   successful and NULL otherwise.  */
 static tree
-find_field_init (tree t, tree init)
+find_flexarray_init (tree t, tree init)
 {
-  if (!init)
+  if (!init || init == error_mark_node)
     return NULL_TREE;
 
   unsigned HOST_WIDE_INT idx;
@@ -2467,16 +2467,10 @@ find_field_init (tree t, tree init)
 
   /* Iterate over all top-level initializer elements.  */
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt)
-    {
-      /* If the member T is found, return it.  */
-      if (field == t)
-       return elt;
-
-      /* Otherwise continue and/or recurse into nested initializers.  */
-      if (TREE_CODE (elt) == CONSTRUCTOR
-         && (init = find_field_init (t, elt)))
-       return init;
-    }
+    /* If the member T is found, return it.  */
+    if (field == t)
+      return elt;
+
   return NULL_TREE;
 }
 
@@ -2645,7 +2639,8 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
                 extension).  If the array member has been initialized,
                 determine its size from the initializer.  Otherwise,
                 the array size is zero.  */
-             if (tree init = find_field_init (oper, DECL_INITIAL (var_decl)))
+             if (tree init = find_flexarray_init (oper,
+                                                  DECL_INITIAL (var_decl)))
                bytes_avail = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (init)));
            }
          else
index b3b3c581afbdee00555bd1252972b52ff863416a..e5bb249b2be6eabafdd6b4de6330c427565fde6b 100644 (file)
@@ -34,7 +34,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 
 static tree
-process_init_constructor (tree type, tree init, tsubst_flags_t complain);
+process_init_constructor (tree type, tree init, int nested,
+                         tsubst_flags_t complain);
 
 
 /* Print an error message stemming from an attempt to use
@@ -996,10 +997,11 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
    For aggregate types, it assumes that reshape_init has already run, thus the
    initializer will have the right shape (brace elision has been undone).
 
-   NESTED is true iff we are being called for an element of a CONSTRUCTOR.  */
+   NESTED is non-zero iff we are being called for an element of a CONSTRUCTOR,
+   2 iff the element of a CONSTRUCTOR is inside another CONSTRUCTOR.  */
 
 static tree
-digest_init_r (tree type, tree init, bool nested, int flags,
+digest_init_r (tree type, tree init, int nested, int flags,
               tsubst_flags_t complain)
 {
   enum tree_code code = TREE_CODE (type);
@@ -1011,7 +1013,7 @@ digest_init_r (tree type, tree init, bool nested, int flags,
 
   /* We must strip the outermost array type when completing the type,
      because the its bounds might be incomplete at the moment.  */
-  if (!complete_type_or_maybe_complain (TREE_CODE (type) == ARRAY_TYPE
+  if (!complete_type_or_maybe_complain (code == ARRAY_TYPE
                                        ? TREE_TYPE (type) : type, NULL_TREE,
                                        complain))
     return error_mark_node;
@@ -1029,11 +1031,9 @@ digest_init_r (tree type, tree init, bool nested, int flags,
   if (code == ARRAY_TYPE)
     {
       if (nested && !TYPE_DOMAIN (type))
-       {
-         /* C++ flexible array members have a null domain.  */
-         pedwarn (loc, OPT_Wpedantic,
-                  "initialization of a flexible array member");
-       }
+       /* C++ flexible array members have a null domain.  */
+       pedwarn (loc, OPT_Wpedantic,
+                "initialization of a flexible array member");
 
       tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
       if (char_type_p (typ1)
@@ -1069,6 +1069,14 @@ digest_init_r (tree type, tree init, bool nested, int flags,
                }
            }
 
+         if (nested == 2 && !TYPE_DOMAIN (type))
+           {
+             if (complain & tf_error)
+               error_at (loc, "initialization of flexible array member "
+                              "in a nested context");
+             return error_mark_node;
+           }
+
          if (type != TREE_TYPE (init)
              && !variably_modified_type_p (type, NULL_TREE))
            {
@@ -1093,8 +1101,7 @@ digest_init_r (tree type, tree init, bool nested, int flags,
     }
 
   /* Handle scalar types (including conversions) and references.  */
-  if ((TREE_CODE (type) != COMPLEX_TYPE
-       || BRACE_ENCLOSED_INITIALIZER_P (init))
+  if ((code != COMPLEX_TYPE || BRACE_ENCLOSED_INITIALIZER_P (init))
       && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
     {
       if (nested)
@@ -1108,11 +1115,11 @@ digest_init_r (tree type, tree init, bool nested, int flags,
 
   /* Come here only for aggregates: records, arrays, unions, complex numbers
      and vectors.  */
-  gcc_assert (TREE_CODE (type) == ARRAY_TYPE
+  gcc_assert (code == ARRAY_TYPE
              || VECTOR_TYPE_P (type)
-             || TREE_CODE (type) == RECORD_TYPE
-             || TREE_CODE (type) == UNION_TYPE
-             || TREE_CODE (type) == COMPLEX_TYPE);
+             || code == RECORD_TYPE
+             || code == UNION_TYPE
+             || code == COMPLEX_TYPE);
 
   /* "If T is a class type and the initializer list has a single
      element of type cv U, where U is T or a class derived from T,
@@ -1132,10 +1139,10 @@ digest_init_r (tree type, tree init, bool nested, int flags,
 
   if (BRACE_ENCLOSED_INITIALIZER_P (init)
       && !TYPE_NON_AGGREGATE_CLASS (type))
-    return process_init_constructor (type, init, complain);
+    return process_init_constructor (type, init, nested, complain);
   else
     {
-      if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE)
+      if (COMPOUND_LITERAL_P (init) && code == ARRAY_TYPE)
        {
          if (complain & tf_error)
            error_at (loc, "cannot initialize aggregate of type %qT with "
@@ -1144,7 +1151,7 @@ digest_init_r (tree type, tree init, bool nested, int flags,
          return error_mark_node;
        }
 
-      if (TREE_CODE (type) == ARRAY_TYPE
+      if (code == ARRAY_TYPE
          && !BRACE_ENCLOSED_INITIALIZER_P (init))
        {
          /* Allow the result of build_array_copy and of
@@ -1171,13 +1178,13 @@ digest_init_r (tree type, tree init, bool nested, int flags,
 tree
 digest_init (tree type, tree init, tsubst_flags_t complain)
 {
-  return digest_init_r (type, init, false, LOOKUP_IMPLICIT, complain);
+  return digest_init_r (type, init, 0, LOOKUP_IMPLICIT, complain);
 }
 
 tree
 digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain)
 {
-  return digest_init_r (type, init, false, flags, complain);
+  return digest_init_r (type, init, 0, flags, complain);
 }
 
 /* Process the initializer INIT for an NSDMI DECL (a FIELD_DECL).  */
@@ -1230,9 +1237,9 @@ picflag_from_initializer (tree init)
 /* Adjust INIT for going into a CONSTRUCTOR.  */
 
 static tree
-massage_init_elt (tree type, tree init, tsubst_flags_t complain)
+massage_init_elt (tree type, tree init, int nested, tsubst_flags_t complain)
 {
-  init = digest_init_r (type, init, true, LOOKUP_IMPLICIT, complain);
+  init = digest_init_r (type, init, nested ? 2 : 1, LOOKUP_IMPLICIT, complain);
   /* Strip a simple TARGET_EXPR when we know this is an initializer.  */
   if (SIMPLE_TARGET_EXPR_P (init))
     init = TARGET_EXPR_INITIAL (init);
@@ -1250,7 +1257,7 @@ massage_init_elt (tree type, tree init, tsubst_flags_t complain)
    which describe the initializers.  */
 
 static int
-process_init_constructor_array (tree type, tree init,
+process_init_constructor_array (tree type, tree init, int nested,
                                tsubst_flags_t complain)
 {
   unsigned HOST_WIDE_INT i, len = 0;
@@ -1273,6 +1280,15 @@ process_init_constructor_array (tree type, tree init,
                       TYPE_SIGN (TREE_TYPE (domain))).to_uhwi ();
       else
        unbounded = true;  /* Take as many as there are.  */
+
+      if (nested == 2 && !domain && !vec_safe_is_empty (v))
+       {
+         if (complain & tf_error)
+           error_at (EXPR_LOC_OR_LOC (init, input_location),
+                     "initialization of flexible array member "
+                     "in a nested context");
+         return PICFLAG_ERRONEOUS;
+       }
     }
   else
     /* Vectors are like simple fixed-size arrays.  */
@@ -1301,7 +1317,8 @@ process_init_constructor_array (tree type, tree init,
       else
        ce->index = size_int (i);
       gcc_assert (ce->value);
-      ce->value = massage_init_elt (TREE_TYPE (type), ce->value, complain);
+      ce->value
+       = massage_init_elt (TREE_TYPE (type), ce->value, nested, complain);
 
       if (ce->value != error_mark_node)
        gcc_assert (same_type_ignoring_top_level_qualifiers_p
@@ -1323,7 +1340,7 @@ process_init_constructor_array (tree type, tree init,
               we can't rely on the back end to do it for us, so make the
               initialization explicit by list-initializing from T{}.  */
            next = build_constructor (init_list_type_node, NULL);
-           next = massage_init_elt (TREE_TYPE (type), next, complain);
+           next = massage_init_elt (TREE_TYPE (type), next, nested, complain);
            if (initializer_zerop (next))
              /* The default zero-initialization is fine for us; don't
                 add anything to the CONSTRUCTOR.  */
@@ -1354,7 +1371,7 @@ process_init_constructor_array (tree type, tree init,
    the initializers.  */
 
 static int
-process_init_constructor_record (tree type, tree init,
+process_init_constructor_record (tree type, tree init, int nested,
                                 tsubst_flags_t complain)
 {
   vec<constructor_elt, va_gc> *v = NULL;
@@ -1436,7 +1453,7 @@ process_init_constructor_record (tree type, tree init,
          if (ce)
            {
              gcc_assert (ce->value);
-             next = massage_init_elt (type, next, complain);
+             next = massage_init_elt (type, next, nested, complain);
              ++idx;
            }
        }
@@ -1462,7 +1479,7 @@ process_init_constructor_record (tree type, tree init,
             for us, so build up TARGET_EXPRs.  If the type in question is
             a class, just build one up; if it's an array, recurse.  */
          next = build_constructor (init_list_type_node, NULL);
-         next = massage_init_elt (TREE_TYPE (field), next, complain);
+         next = massage_init_elt (TREE_TYPE (field), next, nested, complain);
 
          /* Warn when some struct elements are implicitly initialized.  */
          if ((complain & tf_warning)
@@ -1576,7 +1593,7 @@ process_init_constructor_record (tree type, tree init,
    which describe the initializer.  */
 
 static int
-process_init_constructor_union (tree type, tree init,
+process_init_constructor_union (tree type, tree init, int nested,
                                tsubst_flags_t complain)
 {
   constructor_elt *ce;
@@ -1662,7 +1679,8 @@ process_init_constructor_union (tree type, tree init,
     }
 
   if (ce->value && ce->value != error_mark_node)
-    ce->value = massage_init_elt (TREE_TYPE (ce->index), ce->value, complain);
+    ce->value = massage_init_elt (TREE_TYPE (ce->index), ce->value, nested,
+                                 complain);
 
   return picflag_from_initializer (ce->value);
 }
@@ -1682,18 +1700,19 @@ process_init_constructor_union (tree type, tree init,
    of error.  */
 
 static tree
-process_init_constructor (tree type, tree init, tsubst_flags_t complain)
+process_init_constructor (tree type, tree init, int nested,
+                         tsubst_flags_t complain)
 {
   int flags;
 
   gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
 
   if (TREE_CODE (type) == ARRAY_TYPE || VECTOR_TYPE_P (type))
-    flags = process_init_constructor_array (type, init, complain);
+    flags = process_init_constructor_array (type, init, nested, complain);
   else if (TREE_CODE (type) == RECORD_TYPE)
-    flags = process_init_constructor_record (type, init, complain);
+    flags = process_init_constructor_record (type, init, nested, complain);
   else if (TREE_CODE (type) == UNION_TYPE)
-    flags = process_init_constructor_union (type, init, complain);
+    flags = process_init_constructor_union (type, init, nested, complain);
   else
     gcc_unreachable ();
 
index cd208ff1a7ff335352bb744d533376279370a0a4..e1e29f195fd3ea25cc3fcf0a20bfe5e02660bf59 100644 (file)
@@ -1,5 +1,24 @@
 2017-12-15  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/80135
+       PR c++/81922
+       * g++.dg/warn/Wplacement-new-size-1.C (fBx1): Initialize nested
+       flexible array member only with {}.  Add dg-warning.
+       (fBx2, fBx3): Remove.
+       * g++.dg/warn/Wplacement-new-size-2.C (fBx1): Initialize nested
+       flexible array member only with {}.  Add dg-warning.
+       (fBx2, fBx3): Remove.
+       * g++.dg/warn/Wplacement-new-size-6.C: New test.
+       * g++.dg/ext/flexary13.C (main): Remove test for initialization
+       of nested flexible array member with non-empty initializer.
+       * g++.dg/ext/flexary25.C: New test.
+       * g++.dg/ext/flexary26.C: New test.
+       * g++.dg/ext/flexary27.C: New test.
+       * g++.dg/parse/pr43765.C: Expect diagnostics about initialization
+       of nested flexible array member with non-empty initializer.  Expect
+       C++2A diagnostics about mixing of designated and non-designated
+       initializers.
+
        PR c++/83217
        * g++.dg/cpp1z/decomp33.C: New test.
 
index 462ed6520e020261cd56da18bff7e06932305c15..f1f4e22a3ffaeab76077947447c67256596b6126 100644 (file)
@@ -55,10 +55,4 @@ int main ()
       { 1, { 2 } };   // dg-warning "initialization of a flexible array member" }
     ASSERT (s.i == 1 && s.ax.n == 2);
   }
-
-  {
-    AAx s =
-      { 1, { 2, { 3 } } };   // dg-warning "initialization of a flexible array member" }
-    ASSERT (s.i == 1 && s.ax.n == 2 && s.ax.a [0] == 3);
-  }
 }
diff --git a/gcc/testsuite/g++.dg/ext/flexary25.C b/gcc/testsuite/g++.dg/ext/flexary25.C
new file mode 100644 (file)
index 0000000..e0582a9
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/81922
+// { dg-do compile }
+// { dg-options "" }
+
+struct S { const char *a; char b[]; };
+struct T { int a; int b[]; };
+#if __cplusplus >= 201103L
+S c[] { "", "" };              // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+S d[] { "", { 0 } };           // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+T e[] { 1, { 2 }, 3, { 4 } };  // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+T f[] { 1, {}, 3, {} };
+T g { 1, { 1, 2, 3 } };
+S h { "abcd", "" };
+#endif
+S i[] = { "", "", "", "" };    // { dg-error "initialization of flexible array member in a nested context" }
+S j[] = { "", { 1 }, "", { 2, 3 } };   // { dg-error "initialization of flexible array member in a nested context" }
+T k[] = { 1, { 2 }, 3, { 4 } };        // { dg-error "initialization of flexible array member in a nested context" }
+T l[] = { 1, {}, 3, {} };
+T m = { 1, { 1, 2, 3 } };
+S n = { "", "abcde" };
diff --git a/gcc/testsuite/g++.dg/ext/flexary26.C b/gcc/testsuite/g++.dg/ext/flexary26.C
new file mode 100644 (file)
index 0000000..af12772
--- /dev/null
@@ -0,0 +1,26 @@
+// PR c++/81922
+// { dg-do compile }
+// { dg-options "-Wpedantic" }
+
+struct S { const char *a; char b[]; }; // { dg-warning "forbids flexible array member" }
+struct T { int a; int b[]; };  // { dg-warning "forbids flexible array member" }
+#if __cplusplus >= 201103L
+S c[] { "", "" };              // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+                               // { dg-warning "initialization of a flexible array member" "" { target c++11 } .-1 }
+S d[] { "", { 0 } };           // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+                               // { dg-warning "initialization of a flexible array member" "" { target c++11 } .-1 }
+T e[] { 1, { 2 }, 3, { 4 } };  // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+                               // { dg-warning "initialization of a flexible array member" "" { target c++11 } .-1 }
+T f[] { 1, {}, 3, {} };                // { dg-warning "initialization of a flexible array member" "" { target c++11 } }
+T g { 1, { 1, 2, 3 } };                // { dg-warning "initialization of a flexible array member" "" { target c++11 } }
+S h { "abcd", "" };            // { dg-warning "initialization of a flexible array member" "" { target c++11 } }
+#endif
+S i[] = { "", "", "", "" };    // { dg-error "initialization of flexible array member in a nested context" }
+                               // { dg-warning "initialization of a flexible array member" "" { target *-*-* } .-1 }
+S j[] = { "", { 1 }, "", { 2, 3 } };   // { dg-error "initialization of flexible array member in a nested context" }
+                               // { dg-warning "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T k[] = { 1, { 2 }, 3, { 4 } };        // { dg-error "initialization of flexible array member in a nested context" }
+                               // { dg-warning "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T l[] = { 1, {}, 3, {} };      // { dg-warning "initialization of a flexible array member" }
+T m = { 1, { 1, 2, 3 } };      // { dg-warning "initialization of a flexible array member" }
+S n = { "", "abcde" };         // { dg-warning "initialization of a flexible array member" }
diff --git a/gcc/testsuite/g++.dg/ext/flexary27.C b/gcc/testsuite/g++.dg/ext/flexary27.C
new file mode 100644 (file)
index 0000000..9dfa9a2
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/81922
+// { dg-do compile }
+
+struct S { const char *a; char b[]; }; // { dg-error "forbids flexible array member" }
+struct T { int a; int b[]; };  // { dg-error "forbids flexible array member" }
+#if __cplusplus >= 201103L
+S c[] { "", "" };              // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+                               // { dg-error "initialization of a flexible array member" "" { target c++11 } .-1 }
+S d[] { "", { 0 } };           // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+                               // { dg-error "initialization of a flexible array member" "" { target c++11 } .-1 }
+T e[] { 1, { 2 }, 3, { 4 } };  // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+                               // { dg-error "initialization of a flexible array member" "" { target c++11 } .-1 }
+T f[] { 1, {}, 3, {} };                // { dg-error "initialization of a flexible array member" "" { target c++11 } }
+T g { 1, { 1, 2, 3 } };                // { dg-error "initialization of a flexible array member" "" { target c++11 } }
+S h { "abcd", "" };            // { dg-error "initialization of a flexible array member" "" { target c++11 } }
+#endif
+S i[] = { "", "", "", "" };    // { dg-error "initialization of flexible array member in a nested context" }
+                               // { dg-error "initialization of a flexible array member" "" { target *-*-* } .-1 }
+S j[] = { "", { 1 }, "", { 2, 3 } };   // { dg-error "initialization of flexible array member in a nested context" }
+                               // { dg-error "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T k[] = { 1, { 2 }, 3, { 4 } };        // { dg-error "initialization of flexible array member in a nested context" }
+                               // { dg-error "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T l[] = { 1, {}, 3, {} };      // { dg-error "initialization of a flexible array member" }
+T m = { 1, { 1, 2, 3 } };      // { dg-error "initialization of a flexible array member" }
+S n = { "", "abcde" };         // { dg-error "initialization of a flexible array member" }
index 800f2c7cbbb316be00c0a983ca0c2397caf0e64c..5e60220400731ae6cb69ef1da4d1c5feb3a82adb 100644 (file)
@@ -10,8 +10,8 @@ const char *temp[] = {"607", "612", 0};
 
 SomeType vals[] =
     {
-        { 0, values : temp, },
+        { 0, values : temp, },  // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } }
         0
     };   // { dg-error "GNU-style designated initializer for an array|cannot convert" }
 // (note the error above is on the wrong line)
+        // { dg-error "initialization of flexible array member in a nested context" "" { target *-*-* } .-2 }
index b549ae18e892e74a9369d5e586be6d7f77976497..716986d46645dffe2b01869787b6e4cf0e482611 100644 (file)
@@ -82,38 +82,14 @@ void fBx (BAx *pbx, BAx &rbx)
 
 void fBx1 ()
 {
-  BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } };
+  BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } };
 
-  new (bax1.ax.a) char;
+  new (bax1.ax.a) char;            // { dg-warning "placement" }
   new (bax1.ax.a) char[2];  // { dg-warning "placement" }
   new (bax1.ax.a) Int16;    // { dg-warning "placement" }
   new (bax1.ax.a) Int32;    // { dg-warning "placement" }
 }
 
-void fBx2 ()
-{
-  BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } };
-
-  new (bax2.ax.a) char;
-  new (bax2.ax.a) char[2];
-  new (bax2.ax.a) char[3];    // { dg-warning "placement" }
-  new (bax2.ax.a) Int16;
-  new (bax2.ax.a) char[4];    // { dg-warning "placement" }
-  new (bax2.ax.a) Int32;      // { dg-warning "placement" }
-}
-
-void fBx3 ()
-{
-  BAx bax2 = { 1, /* Ax = */ { 3, /* a[] = */ { 4, 5, 6 } } };
-
-  new (bax2.ax.a) char;
-  new (bax2.ax.a) char[2];
-  new (bax2.ax.a) Int16;
-  new (bax2.ax.a) char[3];
-  new (bax2.ax.a) char[4];    // { dg-warning "placement" }
-  new (bax2.ax.a) Int32;      // { dg-warning "placement" }
-}
-
 void fB0 (BA0 *pb0, BA0 &rb0)
 {
   BA0 ba0;
index 23d4324ff8782292ef9fe3cfd9338333e5c2f386..3d470747e24315c12c921c0c0c605ee5ae0e5df9 100644 (file)
@@ -140,38 +140,14 @@ void fBx (BAx *pbx, BAx &rbx)
 
 void fBx1 ()
 {
-  BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } };
+  BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } };
 
-  new (bax1.ax.a) char;
+  new (bax1.ax.a) char;              // { dg-warning "placement" }
   new (bax1.ax.a) char[2];    // { dg-warning "placement" }
   new (bax1.ax.a) Int16;      // { dg-warning "placement" }
   new (bax1.ax.a) Int32;      // { dg-warning "placement" }
 }
 
-void fBx2 ()
-{
-  BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } };
-
-  new (bax2.ax.a) char;
-  new (bax2.ax.a) char[2];
-  new (bax2.ax.a) char[3];    // { dg-warning "placement" }
-  new (bax2.ax.a) Int16;
-  new (bax2.ax.a) char[4];    // { dg-warning "placement" }
-  new (bax2.ax.a) Int32;      // { dg-warning "placement" }
-}
-
-void fBx3 ()
-{
-  BAx bax2 = { 1, /* Ax = */ { 3, /* a[] = */ { 4, 5, 6 } } };
-
-  new (bax2.ax.a) char;
-  new (bax2.ax.a) char[2];
-  new (bax2.ax.a) Int16;
-  new (bax2.ax.a) char[3];
-  new (bax2.ax.a) char[4];    // { dg-warning "placement" }
-  new (bax2.ax.a) Int32;      // { dg-warning "placement" }
-}
-
 void fB0 (BA0 *pb0, BA0 &rb0)
 {
   BA0 ba0;
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C
new file mode 100644 (file)
index 0000000..06dfb3a
--- /dev/null
@@ -0,0 +1,48 @@
+// { dg-do compile }
+// { dg-options "-Wno-pedantic -Wplacement-new=1" }
+
+typedef __typeof__ (sizeof 0) size_t;
+
+void* operator new (size_t, void *p) { return p; }
+void* operator new[] (size_t, void *p) { return p; }
+
+struct Ax { char n, a []; };
+
+typedef __INT16_TYPE__ Int16;
+typedef __INT32_TYPE__ Int32;
+
+struct BAx { int i; Ax ax; };
+
+void fBx1 ()
+{
+  BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } };       // { dg-error "initialization of flexible array member in a nested context" }
+
+  new (bax1.ax.a) char;     // { dg-warning "placement" }
+  new (bax1.ax.a) char[2];  // { dg-warning "placement" }
+  new (bax1.ax.a) Int16;    // { dg-warning "placement" }
+  new (bax1.ax.a) Int32;    // { dg-warning "placement" }
+}
+
+void fBx2 ()
+{
+  BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } };    // { dg-error "initialization of flexible array member in a nested context" }
+
+  new (bax2.ax.a) char;       // { dg-warning "placement" }
+  new (bax2.ax.a) char[2];    // { dg-warning "placement" }
+  new (bax2.ax.a) char[3];    // { dg-warning "placement" }
+  new (bax2.ax.a) Int16;      // { dg-warning "placement" }
+  new (bax2.ax.a) char[4];    // { dg-warning "placement" }
+  new (bax2.ax.a) Int32;      // { dg-warning "placement" }
+}
+
+void fBx3 ()
+{
+  BAx bax2 = { 1, /* Ax = */ { 3, /* a[] = */ { 4, 5, 6 } } }; // { dg-error "initialization of flexible array member in a nested context" }
+
+  new (bax2.ax.a) char;       // { dg-warning "placement" }
+  new (bax2.ax.a) char[2];    // { dg-warning "placement" }
+  new (bax2.ax.a) Int16;      // { dg-warning "placement" }
+  new (bax2.ax.a) char[3];    // { dg-warning "placement" }
+  new (bax2.ax.a) char[4];    // { dg-warning "placement" }
+  new (bax2.ax.a) Int32;      // { dg-warning "placement" }
+}