C++17 std::launder and aliasing

Richard Biener rguenther@suse.de
Mon Oct 24 12:01:00 GMT 2016


On Mon, 24 Oct 2016, Jonathan Wakely wrote:

> On 24/10/16 13:47 +0200, Jakub Jelinek wrote:
> > On Mon, Oct 24, 2016 at 01:38:13PM +0200, Richard Biener wrote:
> > > Certainly a possibility - though points-to information is _not_ affected
> > > by launder semantics.  std::launder only is a memory optimization
> > > barrier for aliasing accesses (I believe even TBAA is valid as it
> > > constrains the types that can be instantiated at the place).  For that
> > > to work you'd have to instead make it have a VDEF and (optionally)
> > > add special code to the stmt_may_use/clobber alias helpers.
> > 
> > I guess the question is if std::launder affects just the returned pointer,
> > or something else too.
> > 
> > struct A {
> >  virtual int f();
> >  virtual int g() { return 2; }
> > };
> > struct B : A {
> >  virtual int f() { new (this) A; return 1; }
> >  virtual int g() { return 1; }
> > };
> > int A::f() { new (this) B; return 2; }
> > static_assert(sizeof(B) == sizeof(A), "");
> > 
> > int main() {
> >  A a;
> >  int b = a.f();
> >  int c = std::launder(&a)->g();
> >  int d = a.g(); // Is this UB?
> 
> Yes, I think that's UB according to 3.8 [basic.life] p8. The name 'a'
> cannot be used to manipulate the new object at that location, because
> the second bullet of p8 is not true.

Ok, so with two std::launder (&a) and launder being CONST we'd happily
CSE them.  Which means repeatedly laundering &a wouldn't work.  You'd
have to do

  A *p = std::launder (&a)->g();
  A *q = std::launder(p)->f();
  std::launder (q)->g();
...

?

> >  int e = std::launder(&a)->f();
> >  if(b != 2 || c != 1 || d != 1 || f != 1)
> >    std::abort();
> > }
> > 
> > 	Jakub
> 
> 

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



More information about the Libstdc++ mailing list