This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
(From submission #317.)
Consider:
struct A {}; struct B : A { char c; }; struct C : A { B b; };
Class C satisfies all the conditions to be considered standard-layout, including 11.2 [class.prop] bullet 3.7:
Thus, M(C) is {char,B}, neither of which is a base class of C, and thus C is standard-layout, contrary to popular ABI rules that do not provide pointer interconvertibility between C::b and C.
Suggested resolution (reviewed by CWG 2024-03-01, with no consensus):
Change in 11.2 [class.prop] bullet 3.7 as follows:
- ...
- has no element of the set M(S) of types as a base class, where for any type X, M(X) is defined as follows, where B(S) is a set of types consisting of S and each direct and indirect base class of S. [Footnote: ...] [Note 2: M(X) is the set of the types of all non-base-class subobjects that can be at a zero offset in X. —end note]
- If X is a non-union class type with no non-static data members, the set M(X) is empty.
- If X is a non-union class type with a non-static data member of type X0 that is either of zero size or is the first non-static data member of X (where said member may be an anonymous union), the set M(X)
consists of X0is the union of B(X0) andthe elements ofM(X0).- If X is a union type, the set M(X) is the union of all M(Ui) and
the set containingallUiB(Ui), where each Ui is the type of the ith non-static data member of X.- If X is an array type with element type Xe, the set M(X)
consists of Xeis the union of B(Xe) andthe elements ofM(Xe).- If X is a non-class, non-array type, the set M(X) is empty.
Add more examples in 11.2 [class.prop] paragraph 4:
struct X {}; // standard-layout class struct Y : X { char c; }; // standard-layout class struct Z : X { Y y; }; // not a standard-layout class struct H {}; // standard-layout class struct I : H {}; // standard-layout class struct J { I i; }; // standard-layout class struct K : I { J j; }; // not a standard-layout class