summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-05 22:27:37 +0000
committermsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-05 22:27:37 +0000
commita7cc1f9413bc7e462eca0bd1ed30f77e5e693062 (patch)
tree541c8bae08fe762974822bede51ea47ee085418f
parentfcb25f28b7b0986849618f615188f7f092db3ccd (diff)
downloadgcc-a7cc1f9413bc7e462eca0bd1ed30f77e5e693062.tar.gz
PR c++/69662 - -Wplacement-new on allocated one element array members
gcc/testsuite/ChangeLog: PR c++/69662 * g++.dg/warn/Wplacement-new-size-1.C: New test. * g++.dg/warn/Wplacement-new-size-2.C: New test. gcc/cp/ChangeLog: PR c++/69662 * init.c (find_field_init): New function. (warn_placement_new_too_small): Call it. Handle one-element arrays at ends of structures special. gcc/c-family/ChangeLog: PR c++/69662 * c.opt (Warning options): Update -Wplacement-new to take an optional argument. gcc/ChangeLog: PR c++/69662 * doc/invoke.texi: Update -Wplacement-new to take an optional argument. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233190 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c.opt6
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/init.c91
-rw-r--r--gcc/doc/invoke.texi35
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C139
-rw-r--r--gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C197
9 files changed, 478 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e61921fc06..9a51133e00e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2016-02-05 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69662
+ * doc/invoke.texi: Update -Wplacement-new to take an optional
+ argument.
+
2016-02-06 Richard Henderson <rth@redhat.com>
PR c/69643
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index abe970193ff..c4f6bc42a7c 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-02-05 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69662
+ * c.opt (Warning options): Update -Wplacement-new to take
+ an optional argument.
+
2016-02-01 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/69543
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index f243744a978..04dec78eb8e 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -777,7 +777,11 @@ ObjC ObjC++ Var(warn_protocol) Init(1) Warning
Warn if inherited methods are unimplemented.
Wplacement-new
-C++ Var(warn_placement_new) Init(1) Warning
+C++ Warning Alias(Wplacement-new=, 1, 0)
+Warn for placement new expressions with undefined behavior.
+
+Wplacement-new=
+C++ Joined RejectNegative UInteger Var(warn_placement_new) Init(-1) Warning
Warn for placement new expressions with undefined behavior.
Wredundant-decls
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a7f2b34e425..427425ae17a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-05 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69662
+ * init.c (find_field_init): New function.
+ (warn_placement_new_too_small): Call it. Handle one-element arrays
+ at ends of structures special.
+
2016-02-05 Jason Merrill <jason@redhat.com>
PR c++/68948
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 976ada84587..cb2e852fdfc 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2285,6 +2285,33 @@ 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. */
+static tree
+find_field_init (tree t, tree init)
+{
+ if (!init)
+ return NULL_TREE;
+
+ unsigned HOST_WIDE_INT idx;
+ tree field, elt;
+
+ /* 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;
+ }
+ return NULL_TREE;
+}
+
/* Attempt to verify that the argument, OPER, of a placement new expression
refers to an object sufficiently large for an object of TYPE or an array
of NELTS of such objects when NELTS is non-null, and issue a warning when
@@ -2375,10 +2402,25 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
oper = TREE_OPERAND (oper, 0);
}
+ /* Refers to the declared object that constains the subobject referenced
+ by OPER. When the object is initialized, makes it possible to determine
+ the actual size of a flexible array member used as the buffer passed
+ as OPER to placement new. */
+ tree var_decl = NULL_TREE;
+ /* True when operand is a COMPONENT_REF, to distinguish flexible array
+ members from arrays of unspecified size. */
+ bool compref = TREE_CODE (oper) == COMPONENT_REF;
+
/* Descend into a struct or union to find the member whose address
is being used as the agument. */
while (TREE_CODE (oper) == COMPONENT_REF)
- oper = TREE_OPERAND (oper, 1);
+ {
+ tree op0 = oper;
+ while (TREE_CODE (op0 = TREE_OPERAND (op0, 0)) == COMPONENT_REF);
+ if (TREE_CODE (op0) == VAR_DECL)
+ var_decl = op0;
+ oper = TREE_OPERAND (oper, 1);
+ }
if ((addr_expr || !POINTER_TYPE_P (TREE_TYPE (oper)))
&& (TREE_CODE (oper) == VAR_DECL
@@ -2387,7 +2429,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
{
/* A possibly optimistic estimate of the number of bytes available
in the destination buffer. */
- unsigned HOST_WIDE_INT bytes_avail;
+ unsigned HOST_WIDE_INT bytes_avail = 0;
/* True when the estimate above is in fact the exact size
of the destination buffer rather than an estimate. */
bool exact_size = true;
@@ -2410,20 +2452,45 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
as the optimistic estimate of the available space in it. */
bytes_avail = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (oper)));
}
+ else if (var_decl)
+ {
+ /* Constructing into a buffer provided by the flexible array
+ member of a declared object (which is permitted as a G++
+ extension). If the array member has been initialized,
+ determine its size from the initializer. Otherwise,
+ the array size is zero. */
+ bytes_avail = 0;
+
+ if (tree init = find_field_init (oper, DECL_INITIAL (var_decl)))
+ bytes_avail = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (init)));
+ }
else
{
/* Bail if neither the size of the object nor its type is known. */
return;
}
- /* Avoid diagnosing flexible array members (accepted as an extension
- and diagnosed with -Wpedantic).
- Constructing objects that appear to overflow the C99 equivalent of
- flexible array members (i.e., array members of size zero or one)
- are diagnosed in C++ since their declaration cannot be diagnosed. */
- if (bytes_avail == 0 && TREE_CODE (TREE_TYPE (oper)) == ARRAY_TYPE)
- return;
+ tree_code oper_code = TREE_CODE (TREE_TYPE (oper));
+ if (compref && oper_code == ARRAY_TYPE)
+ {
+ /* Avoid diagnosing flexible array members (which are accepted
+ as an extension and diagnosed with -Wpedantic) and zero-length
+ arrays (also an extension).
+ Overflowing construction in one-element arrays is diagnosed
+ only at level 2. */
+ if (bytes_avail == 0 && !var_decl)
+ return;
+
+ tree nelts = array_type_nelts_top (TREE_TYPE (oper));
+ tree nelts_cst = maybe_constant_value (nelts);
+ if (TREE_CODE (nelts_cst) == INTEGER_CST
+ && integer_onep (nelts_cst)
+ && !var_decl
+ && warn_placement_new < 2)
+ return;
+ }
+
/* The size of the buffer can only be adjusted down but not up. */
gcc_checking_assert (0 <= adjust);
@@ -2452,7 +2519,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
{
if (nelts)
if (CONSTANT_CLASS_P (nelts))
- warning_at (loc, OPT_Wplacement_new,
+ warning_at (loc, OPT_Wplacement_new_,
exact_size ?
"placement new constructing an object of type "
"%<%T [%wu]%> and size %qwu in a region of type %qT "
@@ -2464,7 +2531,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
TREE_TYPE (oper),
bytes_avail);
else
- warning_at (loc, OPT_Wplacement_new,
+ warning_at (loc, OPT_Wplacement_new_,
exact_size ?
"placement new constructing an array of objects "
"of type %qT and size %qwu in a region of type %qT "
@@ -2475,7 +2542,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
type, bytes_need, TREE_TYPE (oper),
bytes_avail);
else
- warning_at (loc, OPT_Wplacement_new,
+ warning_at (loc, OPT_Wplacement_new_,
exact_size ?
"placement new constructing an object of type %qT "
"and size %qwu in a region of type %qT and size %qwi"
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 650099ec1ff..0a2a6f45d7c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -281,7 +281,8 @@ Objective-C and Objective-C++ Dialects}.
-Woverride-init-side-effects -Woverlength-strings @gol
-Wpacked -Wpacked-bitfield-compat -Wpadded @gol
-Wparentheses -Wno-pedantic-ms-format @gol
--Wplacement-new -Wpointer-arith -Wno-pointer-to-int-cast @gol
+-Wplacement-new -Wplacement-new=@var{n} @gol
+-Wpointer-arith -Wno-pointer-to-int-cast @gol
-Wno-pragmas -Wredundant-decls -Wno-return-local-addr @gol
-Wreturn-type -Wsequence-point -Wshadow -Wno-shadow-ivar @gol
-Wshift-overflow -Wshift-overflow=@var{n} @gol
@@ -4894,6 +4895,7 @@ width specifiers @code{I32}, @code{I64}, and @code{I} used on Windows targets,
which depend on the MS runtime.
@item -Wplacement-new
+@itemx -Wplacement-new=@var{n}
@opindex Wplacement-new
@opindex Wno-placement-new
Warn about placement new expressions with undefined behavior, such as
@@ -4906,7 +4908,36 @@ char buf [64];
new (buf) int[64];
@end smallexample
This warning is enabled by default.
-
+
+@table @gcctabopt
+@item -Wplacement-new=1
+This is the default warning level of @option{-Wplacement-new}. At this
+level the warning is not issued for some strictly undefined constructs that
+GCC allows as extensions for compatibility with legacy code. For example,
+the following @code{new} expression is not diagnosed at this level even
+though it has undefined behavior according to the C++ standard because
+it writes past the end of the one-element array.
+@smallexample
+struct S @{ int n, a[1]; @};
+S *s = (S *)malloc (sizeof *s + 31 * sizeof s->a[0]);
+new (s->a)int [32]();
+@end smallexample
+
+@item -Wplacement-new=2
+At this level, in addition to diagnosing all the same constructs as at level
+1, a diagnostic is also issued for placement new expressions that construct
+an object in the last member of structure whose type is an array of a single
+element and whose size is less than the size of the object being constructed.
+While the previous example would be diagnosed, the following construct makes
+use of the flexible member array extension to avoid the warning at level 2.
+@smallexample
+struct S @{ int n, a[]; @};
+S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
+new (s->a)int [32]();
+@end smallexample
+
+@end table
+
@item -Wpointer-arith
@opindex Wpointer-arith
@opindex Wno-pointer-arith
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d8f088d1bd7..cce24b4eb2f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-02-05 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69662
+ * g++.dg/warn/Wplacement-new-size-1.C: New test.
+ * g++.dg/warn/Wplacement-new-size-2.C: New test.
+
2016-02-06 Richard HEnderson <rth@redhat.com>
PR c/69643
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C
new file mode 100644
index 00000000000..b549ae18e89
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C
@@ -0,0 +1,139 @@
+// PR c++/69662 - -Wplacement-new on allocated one element array members
+// Exercising the more permissive -Wplacement-new=1. The difference
+// between -Wplacement-new=1 is denoted by "no warning at level 1" in
+// the comments below.
+// { 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 []; };
+struct A0 { char n, a [0]; };
+struct A1 { char n, a [1]; };
+struct A2 { char n, a [2]; };
+
+typedef __INT16_TYPE__ Int16;
+typedef __INT32_TYPE__ Int32;
+
+void fAx (Ax *px, Ax &rx)
+{
+ Ax ax;
+ new (ax.a) Int32; // { dg-warning "placement" }
+ new (px->a) Int32;
+ new (rx.a) Int32;
+}
+
+void fAx2 ()
+{
+ Ax ax2 = { 1, { 2, 3 } };
+
+ new (ax2.a) Int16;
+ new (ax2.a) Int32; // { dg-warning "placement" }
+}
+
+void fA0 (A0 *p0, A0 &r0)
+{
+ A0 a0;
+ new (a0.a) Int32; // { dg-warning "placement" }
+ new (p0->a) Int32;
+ new (r0.a) Int32;
+}
+
+void fA1 (A1 *p1, A1 &r1)
+{
+ A1 a1;
+ new (a1.a) Int32; // { dg-warning "placement" }
+ new (p1->a) Int32; // no warning at level 1
+ new (r1.a) Int32; // no warning at level 1
+}
+
+void fA2 (A2 *p2, A2 &r2)
+{
+ A2 a2;
+ new (a2.a) Int32; // { dg-warning "placement" }
+ new (p2->a) Int32; // { dg-warning "placement" }
+ new (r2.a) Int32; // { dg-warning "placement" }
+}
+
+struct BAx { int i; Ax ax; };
+struct BA0 { int i; A0 a0; };
+struct BA1 { int i; A1 a1; };
+struct BA2 { int i; A2 a2; };
+
+void fBx (BAx *pbx, BAx &rbx)
+{
+ BAx bax;
+ new (bax.ax.a) char; // { dg-warning "placement" }
+ new (bax.ax.a) Int16; // { dg-warning "placement" }
+ new (bax.ax.a) Int32; // { dg-warning "placement" }
+
+ new (pbx->ax.a) char;
+ new (rbx.ax.a) char;
+ new (pbx->ax.a) Int16;
+ new (rbx.ax.a) Int16;
+ new (pbx->ax.a) Int32;
+ new (rbx.ax.a) Int32;
+ new (pbx->ax.a) int[1234];
+ new (rbx.ax.a) int[5678];
+}
+
+void fBx1 ()
+{
+ BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } };
+
+ new (bax1.ax.a) char;
+ 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;
+ new (ba0.a0.a) Int32; // { dg-warning "placement" }
+ new (pb0->a0.a) Int32;
+ new (rb0.a0.a) Int32;
+}
+
+void fB1 (BA1 *pb1, BA1 &rb1)
+{
+ BA1 ba1;
+ new (ba1.a1.a) Int32; // { dg-warning "placement" }
+ new (pb1->a1.a) Int32; // no warning at level 1
+ new (rb1.a1.a) Int32; // no warning at level 1
+}
+
+void fB2 (BA2 *pb2, BA2 &rb2)
+{
+ BA2 ba2;
+ new (ba2.a2.a) Int32; // { dg-warning "placement" }
+ new (pb2->a2.a) Int32; // { dg-warning "placement" }
+ new (rb2.a2.a) Int32; // { dg-warning "placement" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C
new file mode 100644
index 00000000000..23d4324ff87
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C
@@ -0,0 +1,197 @@
+// PR c++/69662 - -Wplacement-new on allocated one element array members
+// Exercising -Wplacement-new=2.
+// { dg-do compile }
+// { dg-options "-Wno-pedantic -Wplacement-new=2" }
+
+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 []; };
+struct A0 { char n, a [0]; };
+struct A1 { char n, a [1]; };
+struct A2 { char n, a [2]; };
+
+typedef __INT16_TYPE__ Int16;
+typedef __INT32_TYPE__ Int32;
+
+void fAx (Ax *px, Ax &rx)
+{
+ Ax ax;
+
+ new (ax.a) Int32; // { dg-warning "placement" }
+ new (ax.a) Int32[1]; // { dg-warning "placement" }
+
+ new (px->a) Int32;
+ new (px->a) Int32[1];
+
+ new (rx.a) Int32;
+ new (rx.a) Int32[2];
+}
+
+void fAx2 ()
+{
+ // Initialization of non-static objects with flexible array members
+ // isn't allowed in C and should perhaps be disallowed in C++ as
+ // well to avoid c++/69696 - incorrect initialization of block-scope
+ // flexible array members.
+ Ax ax2 = { 1, { 2, 3 } };
+
+ new (ax2.a) Int16;
+ new (ax2.a) Int16[1];
+ new (ax2.a) Int16[2]; // { dg-warning "placement" }
+ new (ax2.a) Int32; // { dg-warning "placement" }
+ new (ax2.a) Int32[2]; // { dg-warning "placement" }
+}
+
+void fAx3 ()
+{
+ static Ax ax3 = { 1, { 2, 3, 4 } };
+
+ new (ax3.a) Int16;
+ new (ax3.a) Int16[1];
+ new (ax3.a) Int16[2]; // { dg-warning "placement" }
+ new (ax3.a) Int32; // { dg-warning "placement" }
+ new (ax3.a) Int32[1]; // { dg-warning "placement" }
+}
+
+static Ax ax4 = { 1, { 2, 3, 4, 5 } };
+
+void fAx4 ()
+{
+ new (ax4.a) Int16;
+ new (ax4.a) Int16[1];
+ new (ax4.a) Int16[2];
+ new (ax4.a) Int32;
+ new (ax4.a) Int32[1];
+ new (ax4.a) Int32[2]; // { dg-warning "placement" }
+}
+
+void fA0 (A0 *p0, A0 &r0)
+{
+ A0 a0;
+
+ new (a0.a) Int32; // { dg-warning "placement" }
+ new (a0.a) Int32[1]; // { dg-warning "placement" }
+
+ new (p0->a) Int32;
+ new (p0->a) Int32[1];
+ new (p0->a) Int32[2];
+
+ new (r0.a) Int32;
+ new (r0.a) Int32[1];
+ new (r0.a) Int32[2];
+}
+
+void fA1 (A1 *p1, A1 &r1)
+{
+ A1 a1;
+
+ new (a1.a) Int32; // { dg-warning "placement" }
+ new (a1.a) Int32[1]; // { dg-warning "placement" }
+
+ new (p1->a) Int32; // { dg-warning "placement" }
+ new (p1->a) Int32[1]; // { dg-warning "placement" }
+ new (p1->a) Int32[2]; // { dg-warning "placement" }
+
+ new (r1.a) Int32; // { dg-warning "placement" }
+ new (r1.a) Int32[1]; // { dg-warning "placement" }
+ new (r1.a) Int32[2]; // { dg-warning "placement" }
+}
+
+void fA2 (A2 *p2, A2 &r2)
+{
+ A2 a2;
+ new (a2.a) Int32; // { dg-warning "placement" }
+ new (a2.a) Int32[1]; // { dg-warning "placement" }
+ new (a2.a) Int32[2]; // { dg-warning "placement" }
+
+ new (p2->a) Int32; // { dg-warning "placement" }
+ new (p2->a) Int32[1]; // { dg-warning "placement" }
+ new (p2->a) Int32[2]; // { dg-warning "placement" }
+
+ new (r2.a) Int32; // { dg-warning "placement" }
+ new (r2.a) Int32[1]; // { dg-warning "placement" }
+ new (r2.a) Int32[2]; // { dg-warning "placement" }
+}
+
+struct BAx { int i; Ax ax; };
+struct BA0 { int i; A0 a0; };
+struct BA1 { int i; A1 a1; };
+struct BA2 { int i; A2 a2; };
+
+void fBx (BAx *pbx, BAx &rbx)
+{
+ BAx bax;
+ new (bax.ax.a) char; // { dg-warning "placement" }
+ new (bax.ax.a) Int16; // { dg-warning "placement" }
+ new (bax.ax.a) Int32; // { dg-warning "placement" }
+
+ new (pbx->ax.a) char;
+ new (rbx.ax.a) char;
+ new (pbx->ax.a) Int16;
+ new (rbx.ax.a) Int16;
+ new (pbx->ax.a) Int32;
+ new (rbx.ax.a) Int32;
+ new (pbx->ax.a) int[1234];
+ new (rbx.ax.a) int[5678];
+}
+
+void fBx1 ()
+{
+ BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } };
+
+ new (bax1.ax.a) char;
+ 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;
+ new (ba0.a0.a) Int32; // { dg-warning "placement" }
+ new (pb0->a0.a) Int32;
+ new (rb0.a0.a) Int32;
+}
+
+void fB1 (BA1 *pb1, BA1 &rb1)
+{
+ BA1 ba1;
+ new (ba1.a1.a) Int32; // { dg-warning "placement" }
+ new (pb1->a1.a) Int32; // { dg-warning "placement" }
+ new (rb1.a1.a) Int32; // { dg-warning "placement" }
+}
+
+void fB2 (BA2 *pb2, BA2 &rb2)
+{
+ BA2 ba2;
+ new (ba2.a2.a) Int32; // { dg-warning "placement" }
+ new (pb2->a2.a) Int32; // { dg-warning "placement" }
+ new (rb2.a2.a) Int32; // { dg-warning "placement" }
+}