Skip to content

Commit 37ee702

Browse files
committed
Add layout rule for [[no_unique_address]] (C++20 P0840R2)
Fixes #49
1 parent 685a656 commit 37ee702

File tree

1 file changed

+51
-17
lines changed

1 file changed

+51
-17
lines changed

abi.html

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +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 other than zero-width bitfields,
166+
A class with no non-static data members other than zero-width bitfields
167+
and empty data members,
167168
no virtual functions, no virtual base classes,
168169
and no non-empty non-virtual proper base classes.
169170

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+
170176
<p>
171177
<dt> <i>inheritance graph</i> </dt>
172178
<dd>
@@ -267,12 +273,18 @@ <h3><a href="#definitions"> 1.1 Definitions </a></h3>
267273
<dd>
268274
<p>
269275
In general, a type is considered a POD for the purposes of layout if
270-
it is a POD type (in the sense of ISO C++ [basic.types]). However, a
271-
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]).
277+
However, a type is not considered to be a POD for the purpose of layout
278+
if it is:
279+
<ul>
280+
<li>a POD-struct or POD-union (in the sense of ISO C++ [class]) with a
272281
bitfield member whose declared width is wider than the declared type
273-
of the bitfield is not a POD for the purpose of layout. Similarly, an
274-
array type is not a POD for the purpose of layout if the element type
275-
of the array is not a POD for the purpose of layout. Where references
282+
of the bitfield, or
283+
<li>an array type whose element type is not a POD for the purpose of layout, or
284+
<li>a POD-struct with one or more potentially-overlapping non-static
285+
data members.
286+
</ul>
287+
Where references
276288
to the ISO C++ are made in this paragraph, the Technical Corrigendum 1
277289
version of the standard is intended.
278290
</p>
@@ -302,6 +314,12 @@ <h3><a href="#definitions"> 1.1 Definitions </a></h3>
302314
</p>
303315
</dd>
304316

317+
<p>
318+
<dt> <i>potentially-overlapping subobject</i> </dt>
319+
<dd>
320+
A base class subobject or a non-static data member declared with
321+
the <tt>[[no_unique_address]]</tt> attribute.
322+
305323
<p>
306324
<dt> <i>primary base class</i> </dt> <dd> For a dynamic class, the
307325
unique base class (if any) with which it shares the virtual pointer at
@@ -693,7 +711,6 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
693711

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

699716
<ol type=I>
@@ -832,7 +849,7 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
832849
and update sizeof(C) to max(sizeof(C),dsize(C)).
833850

834851
<p>
835-
<li> If D is not an empty base class or D is a data member:
852+
<li> If D is not an empty base class and D is not an empty data member:
836853

837854
<p>
838855
Start at offset dsize(C),
@@ -856,28 +873,34 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
856873

857874
<p>
858875
If D is a base class, update sizeof(C) to max (sizeof(C),
859-
offset(D)+nvsize(D)). Otherwise, if D is a data member,
876+
offset(D)+nvsize(D)).
877+
Otherwise, if D is a potentially-overlapping data member,
878+
update sizeof(C) to max (sizeof(C), offset(D)+max (nvsize(D), dsize(D))).
879+
Otherwise, if D is a data member,
860880
update sizeof(C) to max (sizeof(C), offset(D)+sizeof(D)).
861881

862882
<p>
863883
If D is a base class (not empty in this case),
864884
update dsize(C) to offset(D)+nvsize(D),
865885
and align(C) to max (align(C), nvalign(D)).
866-
If D is a data member,
886+
If D is a potentially-overlapping data member,
887+
update dsize(C) to offset(D)+max (nvsize(D), dsize(D)),
888+
align(C) to max (align(C), align(D)).
889+
If D is any other data member,
867890
update dsize(C) to offset(D)+sizeof(D),
868891
align(C) to max (align(C), align(D)).
869892
</p>
870893

871894
<p>
872-
<li> If D is an empty proper base class:
895+
<li> If D is an empty proper base class or an empty data member:
873896

874897
<p>
875898
Its allocation is similar to case (2) above,
876899
except that additional candidate offsets are considered before
877900
starting at dsize(C).
878901
First, attempt to place D at offset zero.
879902
If unsuccessful (due to a component type conflict),
880-
proceed with attempts at dsize(C) as for non-empty bases.
903+
proceed with attempts at dsize(C) as for non-empty bases and members.
881904
As for that case, if there is a type conflict at dsize(C)
882905
(with alignment updated as necessary),
883906
increment the candidate offset by nvalign(D),
@@ -886,9 +909,9 @@ <h3><a href="#class-types"> 2.4 Non-POD Class Types </a></h3>
886909

887910
<p>
888911
Once offset(D) has been chosen, update sizeof(C) to max (sizeof(C),
889-
offset(D)+sizeof(D)) and align(C) to max (alignof(C),
890-
nvalign(D)). Since D is an empty base class, no update of
891-
dsize(C) is needed.
912+
offset(D)+sizeof(D)), and update align(C) to max (alignof(C),
913+
nvalign(D)) for a base class or max (alignof(C), align(D)) for
914+
a data member. Since D is empty, no update of dsize(C) is needed.
892915

893916
</ol>
894917

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

9721006
</ol>
9731007

0 commit comments

Comments
 (0)