Re: [PATCH] c++/71306 - bogus -Wplacement-new with an array element

2016-05-31 Thread Jason Merrill
On Mon, May 30, 2016 at 6:59 PM, Martin Sebor  wrote:
> On 05/30/2016 12:42 PM, Jason Merrill wrote:
>>
>> OK.
>
> Sorry, I should have asked to begin with: Is it okay to backport
> this fix to the 6.x branch too?

Yes.

Jason


Re: [PATCH] c++/71306 - bogus -Wplacement-new with an array element

2016-05-30 Thread Martin Sebor

On 05/30/2016 12:42 PM, Jason Merrill wrote:

OK.


Sorry, I should have asked to begin with: Is it okay to backport
this fix to the 6.x branch too?

Martin


Re: [PATCH] c++/71306 - bogus -Wplacement-new with an array element

2016-05-30 Thread Jason Merrill

OK.

Jason


[PATCH] c++/71306 - bogus -Wplacement-new with an array element

2016-05-27 Thread Martin Sebor

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;
+}