Closed frederick-vs-ja closed 1 year ago
Yes, I think you're right. Because data members are always laid out after non-virtual base subobjects, and (standard) data member pointers cannot identify a member of a virtual base, the restriction that the class type of the member pointer must be a base or derived class should make it impossible to have negative offsets in a data member pointer.
@zygoloid will find this interesting.
I can write up a patch.
Ah, unfortunately this is still a problem. Consider a member pointer of type T A::*
. Members of base subobjects must always be at non-negative offsets from the address point of A
. Members of classes for which A
is a base subobject are usually at positive offsets from the address point of A
because data members are added after non-virtual base subobjects, but there are two exceptions:
dsize
where there is not a component type conflict. Because adding an empty base does not update dsize
, this offset can be greater than dsize
after adding the base if there are either component type conflicts at dsize
(due to a previous empty base) or if the empty base has an alignment requirement greater than 1. The offset from the empty base class to a data member of the derived class can therefore be negative. godbolt[[no_unique_address]]
) are added using the same rule and can therefore end up at offset zero even if there are non-empty base classes. The offset from the base class to the empty data member can therefore be negative. godboltPR clarifying this situation here: https://github.com/itanium-cxx-abi/cxx-abi/pull/163
PR #97 claimed that
However, it seemly raises undefined behavior to do so according to [expr.static.cast]/13:
The sentence seemly states that it's UB to form a pointer-to-member that behaves "side cast". If a pointer-to-data-member with offset -1 is formed, it apparantly must be formed by side cast, which is UB.
E.g.
Clang rejects this example (while gcc generates a pointer-to-member with offset -1). Godbolt link.
CCing @rjmccall