Full name of submitter: Lénárd Szolnoki
Reference (section label): [class.prop]/3.7
has no element of the set $M(\mathtt{S})$ of types as a base class, where for any type X, $M(\mathtt{X})$ is defined as follows.
- If
X is a non-union class type with no non-static data members, the set $M(\mathtt{X})$ is empty.
- If
X is a non-union class type with a non-static data member of type $\mathtt{X}_0$ 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(\mathtt{X})$ consists of $\mathtt{X}_0$ and the elements of $M(\mathtt{X}_0)$.
- If
X is a union type, the set $M(\mathtt{X})$ is the union of all $M(\mathtt{U}_i)$ and the set containing all $\mathtt{U}_i$,
where each $\mathtt{U}_i$ is the type of the $i^\text{th}$ non-static data member of X.
- If
X is an array type with element type $\mathtt{X}_e$, the set $M(\mathtt{X})$ consists of $\mathtt{X}_e$ and the elements of $M(\mathtt{X}_e)$.
- If
X is a non-class, non-array type, the set $M(\mathtt{X})$ is empty.
Issue description:
Consider the following code:
struct A {};
struct B : A { char ch; };
struct C : A {
B b;
};
Class C stastfies all the conditions to be considered standard-layout, including [class.prop]/3.7. Evaluating [class.prop]/3.7:
-
$M(C)$: [class.prop]/3.7.2 applies, $M(C)$ is the union of $\{B\}$ and $M(B)$.
-
$M(B)$: same applies, $M(B)$ is union of $\{char\}$ and $M(char)$.
-
$M(char)$: [class.prop]/3.7.5, it's an empty set.
Therefore $M(C)$ is $\{B, char\}$, none of which is a base of class C.
The corresponding note suggests that the intention is to not consider such classes as standard-layout.
Practical issues as implemented in some ABIs:
On gcc and clang the following compiles with the example code above:
static_assert(std::is_standard_layout_v<C>);
static_assert(offsetof(C, b) == 1);
This contradicts pointer-interconvertibility rules for standard layout types.
On MSVC the following compiles:
static_assert(std::is_standard_layout_v<C>);
static_assert(sizeof(C) == 1);
Which means that the two distinct subobjects of type A must share the same address. This contradicts [intro.object], where it's specified that these must have distinct addresses. As far as I know the MS ABI has issues in general with this rule.
Suggested resolution:
In [class.prop]/3.7 include direct and indirect base classes of first members.
has no element of the set $M(\mathtt{S})$ of types as a base class, where for any type X, $M(\mathtt{X})$ is defined as follows.
- If
X is a non-union class type with no non-static data members, the set $M(\mathtt{X})$ is empty.
- If
X is a non-union class type with a non-static data member of type $\mathtt{X}_0$ 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(\mathtt{X})$ consists of $\mathtt{X}_0$, direct and indirect base classes of $\mathtt{X}_0$ and the elements of $M(\mathtt{X}_0)$.
- If
X is a union type, the set $M(\mathtt{X})$ is the union of all $M(\mathtt{U}_i)$, the set containing all $\mathtt{U}_i$ and the set containing the direct and indirect base classes of all $\mathtt{U}_i$,
where each $\mathtt{U}_i$ is the type of the $i^\text{th}$ non-static data member of X.
- If
X is an array type with element type $\mathtt{X}_e$, the set $M(\mathtt{X})$ consists of $\mathtt{X}_e$, direct and indirect base classes of $\mathtt{X}_e$ and the elements of $M(\mathtt{X}_e)$.
- If
X is a non-class, non-array type, the set $M(\mathtt{X})$ is empty.
Full name of submitter: Lénárd Szolnoki
Reference (section label): [class.prop]/3.7
Issue description:
Consider the following code:
Class
Cstastfies all the conditions to be considered standard-layout, including [class.prop]/3.7. Evaluating [class.prop]/3.7:Therefore$M(C)$ is $\{B, char\}$ , none of which is a base of class
C.The corresponding note suggests that the intention is to not consider such classes as standard-layout.
Practical issues as implemented in some ABIs:
On gcc and clang the following compiles with the example code above:
This contradicts pointer-interconvertibility rules for standard layout types.
On MSVC the following compiles:
Which means that the two distinct subobjects of type A must share the same address. This contradicts [intro.object], where it's specified that these must have distinct addresses. As far as I know the MS ABI has issues in general with this rule.
Suggested resolution:
In [class.prop]/3.7 include direct and indirect base classes of first members.