https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100307
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Summary|[11/12 Regression] Wrong |[11/12 Regression] spurious |placement-new warning |-Wplacement-new with | |negative pointer offset Known to fail| |11.1.0, 12.0 Component|c++ |middle-end --- Comment #2 from Martin Sebor <msebor at gcc dot gnu.org> --- Confirmed with the simplified test case below. Thanks for the report and the small test case! $ cat pr100307.C && gcc -S -Wall pr100307.C void* operator new (__SIZE_TYPE__, void *p) { return p; } static char a[2]; void* f () { char* p = a + 1; char *q = new (p - 1) char (); // bogus -Wplacement-new return q; } void* g () { char* p = a + 1; char *q = new (p - 2) char (); // valid -Wplacement-new return q; } pr100307.C: In function ‘void* f()’: pr100307.C:8:20: warning: placement new constructing an object of type ‘char’ and size ‘1’ in a region of type ‘char*’ and size ‘0’ [-Wplacement-new=] 8 | char *q = new (p - 1) char (); // bogus -Wplacement-new | ~~^~~ pr100307.C:7:9: note: at offset -1 from ‘p’ declared here 7 | char* p = a + 1; | ^ pr100307.C: In function ‘void* g()’: pr100307.C:15:20: warning: placement new constructing an object of type ‘char’ and size ‘1’ in a region of type ‘char*’ and size ‘0’ [-Wplacement-new=] 15 | char *q = new (p - 2) char (); // valid -Wplacement-new | ~~^~~ pr100307.C:14:9: note: at offset -2 from ‘p’ declared here 14 | char* p = a + 1; | ^ When the compute_objsize_r() function sees a pointer whose target it can't determine it sets the size of the pointed to object to the maximum but it doesn't clear the base0 flag to indicate that the offset need not be zero-based. This is done when the source is in SSA form but not before. Clearing the base0 flag avoids the false positive but also makes the valid warning disappear. Running -Wplacement-new in the front end is too early. It needs to run before placement new is inlined but after the program has been converted to SSA. The same bug affects -Wformat-overflow at -O0 (but not at higher optimization levels): $ cat pr100307.c && gcc -S -Wall pr100307.c char a[4]; void f () { char *p = a + 1; __builtin_sprintf (p - 1, "%i", 123); } pr100307.c: In function ‘f’: pr100307.c:6:30: warning: ‘%i’ directive writing 3 bytes into a region of size 0 [-Wformat-overflow=] 6 | __builtin_sprintf (p - 1, "%i", 123); | ^~ pr100307.c:6:3: note: ‘__builtin_sprintf’ output 4 bytes into a destination of size 0 6 | __builtin_sprintf (p - 1, "%i", 123); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~