On Mon, 28 Jan 2019, Jakub Jelinek wrote:

> 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.

Eww :/  That means they are not semantically the same which IMHO is
bad.  If you make buf1 volatile does it trip over
maybe_canonicalize_mem_ref_addr and miscompile?  Or are we somehow
doubly lucky and never share stack space of volatiles...

Richard.

> 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
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to