@@ -709,13 +709,6 @@ <h4><a href="#data-member-pointers"> 2.3.1 Data Member Pointers </a></h4>
709709
710710< p >
711711A null data member pointer is represented as an offset of < code > -1</ code > .
712- Unfortunately, it is possible to generate a data member pointer with an
713- offset of < code > -1</ code > using explicit derived-to-base conversions.
714- If this is done, implementations following this ABI may misbehave.
715- < span class ="future-abi "> Recommendation for new platforms: consider using
716- a different representation for data member pointers, such as left-shifting
717- the offset by one and using a non-zero low bit to indicate a non-null
718- value.</ span >
719712
720713< p >
721714Note that by < code > [dcl.init]</ code > , "zero initialization" of a data
@@ -732,6 +725,45 @@ <h4><a href="#data-member-pointers"> 2.3.1 Data Member Pointers </a></h4>
732725to cross a < code > virtual</ code > base relationship, and so a static offset
733726is always known.
734727
728+ < p >
729+ Data member pointers that identify members of their class will always
730+ store non-negative offsets. Unfortunately, it is possible to apply
731+ conversions to a non-null data member pointer that will cause it to
732+ hold a negative offset. If this value is < code > -1</ code > , the member
733+ pointer will subsequently be treated as a null pointer. This is
734+ considered an irreparable defect in this ABI.
735+ < span class ="future-abi "> Recommendation for new platforms: consider using
736+ a different representation for data member pointers, such as left-shifting
737+ the offset by one and using a non-zero low bit to indicate a non-null
738+ value.</ span >
739+
740+ < p >
741+ It is relatively difficult to demonstrate this defect in well-defined
742+ code. It is possible to convert a member pointer to a member pointer in
743+ a derived class and then cast it back it to a different base class; if the
744+ second base class is stored after the first, the resulting offset will be
745+ negative. However, this cast has undefined behavior because the member is
746+ no longer a member of a base or derived class of the member pointer's
747+ class. To demonstrate the defect, either an empty base class or an empty
748+ data member must be involved. For example:
749+
750+ < pre >
751+ struct alignas(2) B1 {};
752+
753+ struct B2 : B1 {};
754+ struct B3 : B1 {};
755+
756+ struct D : B2, B3 {
757+ char a, b;
758+ };
759+
760+ // The offset in D of the B3 base subobject is 2, but the
761+ // offset of the data member b is 1.
762+ auto mptr = static_cast< char B3::* > (&D::b);
763+
764+ char B::*mptr = static_cast< char B::* > (static_cast< char C::* > (&A::a));
765+ </ pre >
766+
735767< a name ="member-function-pointers "> </ a >
736768< h4 > < a href ="#member-function-pointers "> 2.3.2 Member Function Pointers </ a > </ h4 >
737769
0 commit comments