std::function::swap does swap(_M_functor, x._M_functor) which
exchanges the underlying bytes of the two _Any_data PODs using that
type's implicit assignment operator. However, unlike using placement
new to construct an object in the storage, simply memcpying the bytes
doesn't change the effective type of the storage, so alias analysis
decides it can't point to whatever we've tried to store in there.

This attribute tells the middle-end to assume anything those bytes
could contain any type of object, which is exactly what we want.

        PR libstdc++/77686
        * include/std/functional (_Any_data): Add may_alias attribute.

Tested powerpc64le-linux, committing to trunk and gcc-6-branch.

std::any doesn't have the same problem, because I defined an _Op_xfer
operation that uses placement new to copy the object into the
destination, so the dynamic type is changed correctly.  I haven't
checked whether optional and variant might have similar problems in
any implicit copy/move operations working on POD storage.


commit f8578f058f049c36ddfae1bf654f3dc93fd8b7ef
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed Sep 28 11:41:08 2016 +0100

    libstdc++/77686 use may_alias for std::function storage
    
        PR libstdc++/77686
        * include/std/functional (_Any_data): Add may_alias attribute.

diff --git a/libstdc++-v3/include/std/functional 
b/libstdc++-v3/include/std/functional
index 8b2389c..74e65c7 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1401,7 +1401,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
     void (_Undefined_class::*_M_member_pointer)();
   };
 
-  union _Any_data
+  union [[gnu::may_alias]] _Any_data
   {
     void*       _M_access()       { return &_M_pod_data[0]; }
     const void* _M_access() const { return &_M_pod_data[0]; }

Reply via email to