Hi! While thinking about PR59813, I came up with following testcase. Is that valid C++?
What I want to highlight here that we need to treat the clobbers created for C++ destructors differently from clobbers added for when variables go out of scope. Right now we end up with: char buf2[128]; char buf1[128]; <bb 2> [local count: 1073741824]: foo (&buf1); MEM[(struct &)&buf1] ={v} {CLOBBER}; memset (&MEM[(void *)&buf1], 32, 128); bar (&buf1); MEM[(struct &)&buf1] ={v} {CLOBBER}; baz (&buf2); buf2 ={v} {CLOBBER}; buf1 ={v} {CLOBBER}; return; where the MEM[(struct &)&buf1] ={v} {CLOBBER}; is what is coming from the inlined dtor (and the earlier one from inlined ctor), while buf1 ={v} {CLOBBER}; is what is added by the gimplifier for vars that go out of scope. The var conflict code only considers clobbers with VAR_DECLs on the lhs and thus the testcase is not miscompiled. Now, if I manually change the second clobber in the function MEM[(struct &)&buf1] ={v} {CLOBBER}; memset (&MEM[(void *)&buf1], 32, 128); bar (&buf1); - MEM[(struct &)&buf1] ={v} {CLOBBER}; + buf1 ={v} {CLOBBER}; baz (&buf2); buf2 ={v} {CLOBBER}; buf1 ={v} {CLOBBER}; the testcase is miscompiled, so that just points at the need to never fold the clobbers with MEM_REF on the lhs into the form with VAR_DECL on the lhs. Tested on x86_64-linux and i686-linux, is the testcase ok for the trunk? 2019-01-28 Jakub Jelinek <ja...@redhat.com> * g++.dg/torture/alias-1.C: New test. --- gcc/testsuite/g++.dg/torture/alias-1.C.jj 2019-01-28 12:49:21.044341442 +0100 +++ gcc/testsuite/g++.dg/torture/alias-1.C 2019-01-28 12:49:04.697612121 +0100 @@ -0,0 +1,57 @@ +// Verify we don't try to allocate the same stack slot for +// buf1 and buf2 in qux. While there is a CLOBBER stmt for buf1 +// from inlined destructor, the buf1 variable doesn't go out of scope +// until after the baz call. +// { dg-do run } + +#include <new> +#include <cstring> +#include <cstdlib> + +char *p; +struct S { char buf[128]; S () { memset (buf, ' ', 128); }; ~S () {}; }; + +__attribute__((noipa)) void +foo (char *x) +{ + p = x; +} + +__attribute__((noipa)) int +bar (S *x) +{ + return x->buf[12]; +} + +__attribute__((noipa)) void +baz (char *x) +{ + S *a = new (p) (S); + S *b = new (x) (S); + memset (a->buf, '0', 128); + memset (b->buf, '1', 128); + if (bar (a) != '0' || bar (b) != '1') + abort (); + b->~S (); + a->~S (); +} + +__attribute__((noipa)) void +qux () +{ + char buf1[128]; + foo (buf1); + S *p = new (buf1) (S); + bar (p); + p->~S (); + { + char buf2[128]; + baz (buf2); + } +} + +int +main () +{ + qux (); +} Jakub