Skip to content

Commit 8db4972

Browse files
authored
Merge pull request #50 from zygoloid/no-unique-address
Add layout rule for [[no_unique_address]] (C++20 P0840R2)
2 parents 72e84eb + 6a0ed4d commit 8db4972

File tree

1 file changed

+50
-19
lines changed

1 file changed

+50
-19
lines changed

abi.html

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,16 @@ <h3><a href="#definitions"> 1.1 Definitions </a></h3>
163163
<p>
164164
<dt> <i>empty class</i> </dt>
165165
<dd>
166-
A class with no non-static data members,
166+
A class with no non-static data members other than empty data members,
167167
no unnamed bit-fields other than zero-width bit-fields,
168168
no virtual functions, no virtual base classes,
169169
and no non-empty non-virtual proper base classes.
170170

171+
<p>
172+
<dt> <i>empty data member</i> </dt>
173+
<dd>
174+
A potentially-overlapping non-static data member of empty class type.
175+
171176
<p>
172177
<dt> <i>inheritance graph</i> </dt>
173178
<dd>
@@ -268,14 +273,18 @@ <h3><a href="#definitions"> 1.1 Definitions </a></h3>
268273
<dd>
269274
<p>
270275
In general, a type is considered a POD for the purposes of layout if
271-
it is a POD type (in the sense of ISO C++ [basic.types]). However, a
272-
POD-struct or POD-union (in the sense of ISO C++ [class]) with a
276+
it is a POD type (in the sense of ISO C++ [basic.types]). However, a
277+
type is not considered to be a POD for the purpose of layout if it is:
278+
<ul>
279+
<li>a POD-struct or POD-union (in the sense of ISO C++ [class]) with a
273280
bit-field whose declared width is wider than the declared type
274-
of the bit-field is not a POD for the purpose of layout. Similarly, an
275-
array type is not a POD for the purpose of layout if the element type
276-
of the array is not a POD for the purpose of layout. Where references
277-
to the ISO C++ are made in this paragraph, the Technical Corrigendum 1
278-
version of the standard is intended.
281+
of the bit-field, or
282+
<li>an array type whose element type is not a POD for the purpose of layout, or
283+
<li>a POD-struct with one or more potentially-overlapping non-static
284+
data members.
285+
</ul>
286+
Where references to the ISO C++ are made in this paragraph, the Technical
287+
Corrigendum 1 version of the standard is intended.
279288
</p>
280289

281290
<p>
@@ -303,6 +312,12 @@ <h3><a href="#definitions"> 1.1 Definitions </a></h3>
303312
</p>
304313
</dd>
305314

315+
<p>
316+
<dt> <i>potentially-overlapping subobject</i> </dt>
317+
<dd>
318+
A base class subobject or a non-static data member declared with
319+
the <tt>[[no_unique_address]]</tt> attribute.
320+
306321
<p>
307322
<dt> <i>primary base class</i> </dt> <dd> For a dynamic class, the
308323
unique base class (if any) with which it shares the virtual pointer at
@@ -694,7 +709,6 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
694709

695710
(See the description of these terms in
696711
<a href=#general><b>General</b></a> above.)
697-
Further, assume for data members that nvsize==size, and nvalign==align.
698712
Layout (of type C) is done using the following procedure.
699713

700714
<ol type=I>
@@ -833,7 +847,7 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
833847
and update sizeof(C) to max(sizeof(C),dsize(C)).
834848

835849
<p>
836-
<li> If D is not an empty base class or D is a data member:
850+
<li> If D is not an empty base class and D is not an empty data member:
837851

838852
<p>
839853
Start at offset dsize(C),
@@ -857,28 +871,34 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
857871

858872
<p>
859873
If D is a base class, update sizeof(C) to max (sizeof(C),
860-
offset(D)+nvsize(D)). Otherwise, if D is a data member,
874+
offset(D)+nvsize(D)).
875+
Otherwise, if D is a potentially-overlapping data member,
876+
update sizeof(C) to max (sizeof(C), offset(D)+max (nvsize(D), dsize(D))).
877+
Otherwise, if D is a data member,
861878
update sizeof(C) to max (sizeof(C), offset(D)+sizeof(D)).
862879

863880
<p>
864881
If D is a base class (not empty in this case),
865882
update dsize(C) to offset(D)+nvsize(D),
866883
and align(C) to max (align(C), nvalign(D)).
867-
If D is a data member,
884+
If D is a potentially-overlapping data member,
885+
update dsize(C) to offset(D)+max (nvsize(D), dsize(D)),
886+
align(C) to max (align(C), align(D)).
887+
If D is any other data member,
868888
update dsize(C) to offset(D)+sizeof(D),
869889
align(C) to max (align(C), align(D)).
870890
</p>
871891

872892
<p>
873-
<li> If D is an empty proper base class:
893+
<li> If D is an empty proper base class or an empty data member:
874894

875895
<p>
876896
Its allocation is similar to case (2) above,
877897
except that additional candidate offsets are considered before
878898
starting at dsize(C).
879899
First, attempt to place D at offset zero.
880900
If unsuccessful (due to a component type conflict),
881-
proceed with attempts at dsize(C) as for non-empty bases.
901+
proceed with attempts at dsize(C) as for non-empty bases and members.
882902
As for that case, if there is a type conflict at dsize(C)
883903
(with alignment updated as necessary),
884904
increment the candidate offset by nvalign(D),
@@ -887,9 +907,9 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
887907

888908
<p>
889909
Once offset(D) has been chosen, update sizeof(C) to max (sizeof(C),
890-
offset(D)+sizeof(D)) and align(C) to max (alignof(C),
891-
nvalign(D)). Since D is an empty base class, no update of
892-
dsize(C) is needed.
910+
offset(D)+sizeof(D)), and update align(C) to max (alignof(C),
911+
nvalign(D)) for a base class or max (alignof(C), align(D)) for
912+
a data member. Since D is empty, no update of dsize(C) is needed.
893913

894914
</ol>
895915

@@ -967,8 +987,19 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
967987
<p>
968988
<li> <h5> Finalization </h5>
969989
<p>
970-
Round sizeof(C) up to a non-zero multiple of align(C). If C is a POD,
971-
but not a POD for the purpose of layout, set nvsize(C) = sizeof(C).
990+
For each potentially-overlapping non-static data member D of C,
991+
update sizeof(C) to max (sizeof(C), offset(D)+sizeof(D)). Example:
992+
993+
<pre><code>
994+
struct alignas(16) A { ~A(); }; // dsize 0, nvsize 0, size 16
995+
struct B : A {}; // dsize 0, nvsize 16, size 16
996+
struct X : virtual A, virtual B {}; // dsize 8, nvsize 8, size 32
997+
struct Y { [[no_unique_address]] X x; char c; }; // dsize 9, nvsize 9, size 32
998+
</code></pre>
999+
1000+
<p>
1001+
Then, round sizeof(C) up to a non-zero multiple of align(C). If C is a POD,
1002+
but not a POD for the purpose of layout, set dsize(C) = nvsize(C) = sizeof(C).
9721003

9731004
</ol>
9741005

0 commit comments

Comments
 (0)