C++17 std::launder and aliasing

Jonathan Wakely jwakely@redhat.com
Fri Oct 21 16:29:00 GMT 2016


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.



More information about the Libstdc++ mailing list