[cxx-abi-dev] pointer-to-data-member representation for null pointer is not conforming
John McCall
rjmccall at apple.com
Fri Dec 21 05:24:32 UTC 2012
On Dec 20, 2012, at 9:14 PM, Dennis Handly <dhandly at cup.hp.com> wrote:
>> From: Richard Smith <richardsmith at google.com>
>> struct E {};
>> struct X : E {};
>> struct C : E, X { char x; };
>
>> char C::*c1 = &C::x;
>> char X::*x = (char(X::*))c1;
>> char C::*c2 = x2;
>
> Should this just be "x"?
>
>> [expr.static.cast]p12, we can convert a pointer to a member of a derived
>> class to a pointer to a member of a base class
>
> Even if that class doesn't have members of that type?
Yes. There's a note in [expr.static.cast]p12 that makes this pretty clear:
N3376 [expr.static.cast]p12:
If class B contains the original member, or is a base or derived class of
the class containing the original member, the resulting pointer to member
points to the original member. Otherwise, the result of the cast is undefined.
[Note: although class B need not contain the original member, the dynamic
type of the object on which the pointer to member is dereferenced must
contain the original member; see [expr.mptr.oper]. — end note]
It's one of the laundry list of things that completely dooms any type-specific
optimization of member pointers.
I would personally have preferred a completely different pointer-to-member
model where base classes have to be complete types and upcasts are
undefined unless the member is a member of the base class, but that is
not the language that the committee has seen fit to bless us with.
>> the conversion from x to c2 preserves the -1 value (conversion of
>> a null member pointer produces a null member pointer), giving the wrong
>> value for x2, and resulting in main returning 0, where the standard
>> requires it to return 1 (likewise, returning x != 0 would produce the wrong
>> value).
>
> I assume that x and x2 are really the same, typo?
>
> Trying this with g++ (4.2.1), I get the right answer.
I believe there are situations in which g++ doesn't appropriately check for null
before applying a non-trivial pointer-to-member conversion. For example,
given Richard's setup,
int X::*x = 0;
int C::*c = x; // g++ just adds the offset, making this no longer a null member pointer
> Looking at the assembly, there doesn't seem to be any code to handle NULL
> being cast back to a derived class.
Yep.
John.
More information about the cxx-abi-dev
mailing list