It was pointed out on gcc-help last night that the -Wplacement-new
warning issues a false positive when a placement new expression is
invoked with an operand that is an element of an array of pointers
(to buffers of unknown size). The attached patch adjusts
the warning so as to avoid this false positive.
The patch also removes the pointless loop that Jakub questioned
below:
https://gcc.gnu.org/ml/gcc-patches/2016-04/msg00050.html
Martin
PR c++/71306 - bogus -Wplacement-new with an array element
gcc/cp/ChangeLog:
2016-05-27 Martin Sebor
PR c++/71306
* init.c (warn_placement_new_too_small): Handle placement new arguments
that are elements of arrays more carefully. Remove a pointless loop.
gcc/testsuite/ChangeLog:
2016-05-27 Martin Sebor
PR c++/71306
* g++.dg/warn/Wplacement-new-size-3.C: New test.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 681ca12..9cbd43f 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2375,7 +2375,8 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
STRIP_NOPS (oper);
- if (TREE_CODE (oper) == ARRAY_REF)
+ if (TREE_CODE (oper) == ARRAY_REF
+ && (addr_expr || TREE_CODE (TREE_TYPE (oper)) == ARRAY_TYPE))
{
/* Similar to the offset computed above, see if the array index
is a compile-time constant. If so, and unless the offset was
@@ -2404,8 +2405,8 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
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)
+ is being used as the argument. */
+ if (TREE_CODE (oper) == COMPONENT_REF)
{
tree op0 = oper;
while (TREE_CODE (op0 = TREE_OPERAND (op0, 0)) == COMPONENT_REF);
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-3.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-3.C
new file mode 100644
index 000..f5dd642
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-3.C
@@ -0,0 +1,40 @@
+// PR c++/71306 - bogus -Wplacement-new with an array element
+// { dg-do compile }
+// { dg-options "-Wplacement-new" }
+
+void* operator new (__SIZE_TYPE__, void *p) { return p; }
+
+struct S64 { char c [64]; };
+
+S64 s2 [2];
+S64* ps2 [2];
+S64* ps2_2 [2][2];
+
+void* pv2 [2];
+
+void f ()
+{
+ char a [2][sizeof (S64)];
+
+ new (a) S64;
+ new (a [0]) S64;
+ new (a [1]) S64;
+
+ // Verify there is no warning with buffers of sufficient size.
+ new ( [0]) S64;
+ new ( [1]) S64;
+
+ // ..and no warning with pointers to buffers of unknown size.
+ new (ps2 [0]) S64;
+ new (ps2 [1]) S64;
+
+ // But a warning when using the ps2_2 array itself as opposed
+ // to the pointers it's elements might point to.
+ new (ps2_2 [0]) S64;// { dg-warning "placement new" }
+ new (ps2_2 [1]) S64;// { dg-warning "placement new" }
+
+ // ..and no warning again with pointers to buffers of unknown
+ // size.
+ new (pv2 [0]) S64;
+ new (pv2 [1]) S64;
+}