Created on 2020-11-10.00:00:00 last changed 1 month ago
Proposed resolution (approved by CWG 2023-08-25):
Change in 11.4.1 [class.mem.general] paragraph 23 as follows:
The common initial sequence of two standard-layout struct (11.2 [class.prop]) types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that
- corresponding entities have layout-compatible types (6.9 [basic.types]),
- corresponding entities have the same alignment requirements (6.8.3 [basic.align]),
either both entities are declared with the no_unique_address attribute (9.13.11 [dcl.attr.nouniqueaddr]) or neither is,if a has-attribute-expression (15.2 [cpp.cond]) is not 0 for the no_unique_address attribute, then neither entity is declared with the no_unique_address attribute (9.13.11 [dcl.attr.nouniqueaddr]), and- either both entities are bit-fields with the same width or neither is a bit-field.
[Accepted as a DR at the November, 2023 meeting.]
The interaction of [[no_unique_address]] and the definition of common initial sequence is still problematic. Subclause 11.4.1 [class.mem.general] bullet 23.3 specifies that corresponding members in a common initial sequence are not allowed to differ with respect to the presence or absence of a [[no_unique_address]] attribute. However, the Itanium ABI will not allocate two successive data members of the same empty class type at the same address, causing non-conforming behavior for the following example:
struct A {};
struct B {};
struct C {
[[no_unique_address]] A a;
[[no_unique_address]] B b;
};
struct D {
[[no_unique_address]] A a1;
[[no_unique_address]] A a2;
};
static_assert(offsetof(C, b) == offsetof(D, a2));
Since "common initial sequence" and "layout compatible" are concepts mostly used for C compatibility, but [[no_unique_address]] does not exist in C, it seems reasonable to terminate a common initial sequence at the first data member that is declared [[no_unique_address]].
Another concern is the behavior of std::is_layout_compatible on implementations that ignore [[no_unique_address]]. On such an implementation, the following example would be considered layout-compatible, although it actually is not:
struct E {};
struct A {
E e;
int i;
};
struct B {
[[no_unique_address]] E e;
int i;
};
static_assert(
std::is_layout_compatible_v<A, B>
);
Alternative possible resolution [SUPERSEDED]:
Change in 11.4.1 [class.mem.general] paragraph 23 as follows:
The common initial sequence of two standard-layout struct (11.2 [class.prop]) types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that
- corresponding entities have layout-compatible types (6.9 [basic.types]),
- corresponding entities have the same alignment requirements (6.8.3 [basic.align]),
either both entities are declared with the no_unique_address attribute (9.13.11 [dcl.attr.nouniqueaddr]) or neither is,neither entity is declared with the no_unique_address attribute (9.13.11 [dcl.attr.nouniqueaddr]), and- either both entities are bit-fields with the same width or neither is a bit-field.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2025-09-12 22:42:26 | admin | set | status: open -> cd7 |
| 2025-09-12 22:42:26 | admin | set | status: drwp -> open |
| 2024-04-05 21:43:46 | admin | set | status: dr -> drwp |
| 2023-12-19 10:15:28 | admin | set | status: ready -> dr |
| 2023-11-10 14:27:11 | admin | set | status: tentatively ready -> ready |
| 2023-08-26 21:49:54 | admin | set | status: open -> tentatively ready |
| 2023-07-10 21:53:51 | admin | set | messages: + msg7355 |
| 2020-11-10 00:00:00 | admin | create | |