Message ID | 20160928105732.GA7817@redhat.com |
---|---|
State | New |
Headers | show |
On Wed, Sep 28, 2016 at 12:57 PM, Jonathan Wakely <jwakely@redhat.com> wrote: > 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. To clarify -- the implicit assingment operator for PODs (including unions) simply expands to an aggregate assignment which is subject to TBAA rules and thus in this case instantiates an effective type of _Any_data. Using memcpy would have worked as memcpy _does_ transfer the effective type of the storage. It wasn't points-to deciding things here but TBAA given automatic storage X with effective type T read via an lvalue of type _Any_data. > This attribute tells the middle-end to assume anything those bytes > could contain any type of object, which is exactly what we want. It tells the middle-end that accessing storage via a _pointer_ to such marked type may access storage with a dynamic type that is not compatible with the type. Details ;) Btw, I think the patch is correct. Richard. > 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. > >
On 28/09/16 13:14 +0200, Richard Biener wrote: >On Wed, Sep 28, 2016 at 12:57 PM, Jonathan Wakely <jwakely@redhat.com> wrote: >> 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. > >To clarify -- the implicit assingment operator for PODs (including unions) >simply expands to an aggregate assignment which is subject to TBAA >rules and thus in this case instantiates an effective type of _Any_data. >Using memcpy would have worked as memcpy _does_ transfer >the effective type of the storage. It wasn't points-to deciding things >here but TBAA given automatic storage X with effective type T >read via an lvalue of type _Any_data. > >> This attribute tells the middle-end to assume anything those bytes >> could contain any type of object, which is exactly what we want. > >It tells the middle-end that accessing storage via a _pointer_ to such >marked type may access storage with a dynamic type that is not >compatible with the type. > >Details ;) But important ones, thanks.
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]; }