This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
Consider:
struct A {}; struct AA : A { int y; }; struct B : A { int x; }; struct C : AA, B {}; constexpr int f(const A &a) { int A::*mp = static_cast<int A::*>(&B::x); return a.*mp; } extern char x[f(static_cast<const AA &>(C{{{}, 13}, {{}, 42}}))]; extern char x[13];
Subclause 7.6.4 [expr.mptr.oper] paragraph 4 specifies:
Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression. If the dynamic type of E1 does not contain the member to which E2 refers, the behavior is undefined.
In the example, the dynamic type of a is C, which does contain B::x, and the undefined behavior provision does not trigger. Thus the call to f is required to yield 42; however common implementations produce 13. The behavior for this case ought to be undefined.
Suggested resolution:
Change in 7.6.4 [expr.mptr.oper] paragraph 4 as follows:
Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression.If the dynamic type of E1 does not contain the member to which E2 refers,Where the type of E2 is "pointer to member of T", C is the (unique) class of which the member to which E2 refers is a direct member, and B is the object of type T that either is the result of E1 or is the uniquely so-typed base subobject thereof, if B is neither of type C nor a base class subobject of an object of type C, then the behavior is undefined.