This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


On 18/10/16 13:31 +0200, Richard Biener wrote:
On Tue, Oct 18, 2016 at 1:06 PM, Jakub Jelinek <jakub@redhat.com> 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 <new>
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.

Thanks, Richi.

Moving from gcc@ to libstdc++@ as this is now libstdc++-specific.

So we can define std::launder as a no-op for GCC. LLVM apparently does
have some optimizations that need to be disabled by doing the laundry,
and Clang will be adding a T* __builtin_launder(T*) for that.

If we define the __cpp_lib_launder macro in libstdc++ that will imply
that we have a working version of std::launder, even though it doesn't
serve its intended purpose for non-GCC compilers. We could either not
define the macro for non-GCC compilers (which is hard, because they
all pretend to be GCC) or we could do:

namespace std
{
#define __cpp_lib_launder 201606
 template<typename _Tp>
   constexpr _Tp*
   launder(_Tp* __p) noexcept
   {
     static_assert( !is_function_v<_Tp> );
     static_assert( !is_void_v<_Tp> );
#if __clang__
# if __has_builtin(__builtin_launder)
     __p = __builtin_launder(__p);
# endif
#endif
     return __p;
   }
}

This should automatially start doing the right thing when Clang adds
that builtin (as Richard Smith tells me they plan to).

The problem still exists for other non-GCC compilers, but this is a
start. I'll try to find out how ICC would like us to handle this.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]