Re: C++17 std::launder and aliasing

2016-10-18 Thread Richard Biener
On Tue, Oct 18, 2016 at 1:06 PM, Jakub Jelinek  wrote:
> Hi!
>
> http://wg21.link/p0137
> adds std::launder which is supposed to be some kind of aliasing optimization
> barrier.
>
> What is unclear to me is if we really need compiler support for that.
> I have unfortunately not found many examples:
>
> http://stackoverflow.com/questions/39382501/what-is-the-purpose-of-stdlaunder
> mentions something like:
> #include 
> int
> foo ()
> {
>   struct X { const int n; };
>   union U { X x; float f; };
>   U u = {{ 1 }};
>   int a = u.x.n;
>   X *p = new (&u.x) X {2};
>   int b = u.x.n;// UB, needs std::launder(&u.x.n)
>   return a + b;
> }
> but g++ handles it as returning 3 even without that.
> So, do we need to do anything here even in the current gcc aliasing model,
> which is very permissive (my understanding is that usually we treat all
> writes as possibly placement new-ish changes)?

The standard mentions that appearantly const and reference "sub-objects" are
unchanging when you access them.  Cruically they changed 3.8/1 to

The lifetime of an object o of type T ends when...

 * the storage which the object occupies is released, or is reused by
an object that is not nested within o ([intro.object])

the subobject notion is new.  I suppse this was done to formally allow
construction of objects
in char[] members w/o ending the containings object lifetime.  I think
this is somewhat of a mistake
as obviously two (sub-)objects can't be life at the same time at the
same memory location
(which the undefined behavior above implies).

And yes, GCC doesn't need anything special as it handles sub-object
lifetime properly
(any store may end it) and it doesn't exploit the "constness" of const
declared members
or reference members.

> Then I found something like:
> https://groups.google.com/a/isocpp.org/forum/#!msg/std-discussion/XYvVlTc3-to/HbhebSRnAgAJ
> which of course doesn't work with -flifetime-dse=2, I'd strongly hope that
> all those attempts there are UB even with std::launder.

Obviously std::launder now invites people to invent fancy things (all
UB), similar
to how reinterpret_cast<>s name invited people to think it has anything to do
with TBAA.

std::launder is about object lifetime, nothing else IIUC.

> Adding __builtin_launder as void * -> void * builtin (ECF_CONST) or perhaps
> typegeneric one that returns the same pointer as given to it (and not
> teaching alias analysis about what that builtin does) is certainly possible,
> the question is how to expand it at RTL time (does it also need to be some
> kind of opt barrier, say like __asm ("" : "+g" (ptr));, or not?

As said, nothing needed for the middle-end.

Richard.

> Jakub


C++17 std::launder and aliasing

2016-10-18 Thread Jakub Jelinek
Hi!

http://wg21.link/p0137
adds std::launder which is supposed to be some kind of aliasing optimization
barrier.

What is unclear to me is if we really need compiler support for that.
I have unfortunately not found many examples:

http://stackoverflow.com/questions/39382501/what-is-the-purpose-of-stdlaunder
mentions something like:
#include 
int
foo ()
{
  struct X { const int n; };
  union U { X x; float f; };
  U u = {{ 1 }};
  int a = u.x.n;
  X *p = new (&u.x) X {2};
  int b = u.x.n;// UB, needs std::launder(&u.x.n)
  return a + b;
}
but g++ handles it as returning 3 even without that.
So, do we need to do anything here even in the current gcc aliasing model,
which is very permissive (my understanding is that usually we treat all
writes as possibly placement new-ish changes)?

Then I found something like:
https://groups.google.com/a/isocpp.org/forum/#!msg/std-discussion/XYvVlTc3-to/HbhebSRnAgAJ
which of course doesn't work with -flifetime-dse=2, I'd strongly hope that
all those attempts there are UB even with std::launder.

Adding __builtin_launder as void * -> void * builtin (ECF_CONST) or perhaps
typegeneric one that returns the same pointer as given to it (and not
teaching alias analysis about what that builtin does) is certainly possible,
the question is how to expand it at RTL time (does it also need to be some
kind of opt barrier, say like __asm ("" : "+g" (ptr));, or not?

Jakub