[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / test / Layout / no-unique-address.cpp
blobd5bb46647b88d0fccb3e4ffc3040ce4d2c5a483a
1 // RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s
3 namespace Empty {
4 struct A {};
5 struct B { [[no_unique_address]] A a; char b; };
6 static_assert(sizeof(B) == 1);
8 // CHECK:*** Dumping AST Record Layout
9 // CHECK: 0 | struct Empty::B
10 // CHECK-NEXT: 0 | struct Empty::A a (empty)
11 // CHECK-NEXT: 0 | char b
12 // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,
13 // CHECK-NEXT: | nvsize=1, nvalign=1]
15 struct C {};
16 struct D {
17 [[no_unique_address]] A a;
18 [[no_unique_address]] C c;
19 char d;
21 static_assert(sizeof(D) == 1);
23 // CHECK:*** Dumping AST Record Layout
24 // CHECK: 0 | struct Empty::D
25 // CHECK-NEXT: 0 | struct Empty::A a (empty)
26 // CHECK-NEXT: 0 | struct Empty::C c (empty)
27 // CHECK-NEXT: 0 | char d
28 // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,
29 // CHECK-NEXT: | nvsize=1, nvalign=1]
31 struct E {
32 [[no_unique_address]] A a1;
33 [[no_unique_address]] A a2;
34 char e;
36 static_assert(sizeof(E) == 2);
38 // CHECK:*** Dumping AST Record Layout
39 // CHECK: 0 | struct Empty::E
40 // CHECK-NEXT: 0 | struct Empty::A a1 (empty)
41 // CHECK-NEXT: 1 | struct Empty::A a2 (empty)
42 // CHECK-NEXT: 0 | char e
43 // CHECK-NEXT: | [sizeof=2, dsize=2, align=1,
44 // CHECK-NEXT: | nvsize=2, nvalign=1]
46 struct F {
47 ~F();
48 [[no_unique_address]] A a1;
49 [[no_unique_address]] A a2;
50 char f;
52 static_assert(sizeof(F) == 2);
54 // CHECK:*** Dumping AST Record Layout
55 // CHECK: 0 | struct Empty::F
56 // CHECK-NEXT: 0 | struct Empty::A a1 (empty)
57 // CHECK-NEXT: 1 | struct Empty::A a2 (empty)
58 // CHECK-NEXT: 0 | char f
59 // CHECK-NEXT: | [sizeof=2, dsize=1, align=1,
60 // CHECK-NEXT: | nvsize=2, nvalign=1]
62 struct G { [[no_unique_address]] A a; ~G(); };
63 static_assert(sizeof(G) == 1);
65 // CHECK:*** Dumping AST Record Layout
66 // CHECK: 0 | struct Empty::G
67 // CHECK-NEXT: 0 | struct Empty::A a (empty)
68 // CHECK-NEXT: | [sizeof=1, dsize=0, align=1,
69 // CHECK-NEXT: | nvsize=1, nvalign=1]
71 struct H { [[no_unique_address]] A a, b; ~H(); };
72 static_assert(sizeof(H) == 2);
74 // CHECK:*** Dumping AST Record Layout
75 // CHECK: 0 | struct Empty::H
76 // CHECK-NEXT: 0 | struct Empty::A a (empty)
77 // CHECK-NEXT: 1 | struct Empty::A b (empty)
78 // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
79 // CHECK-NEXT: | nvsize=2, nvalign=1]
81 struct OversizedEmpty : A {
82 ~OversizedEmpty();
83 [[no_unique_address]] A a;
85 static_assert(sizeof(OversizedEmpty) == 2);
87 // CHECK:*** Dumping AST Record Layout
88 // CHECK: 0 | struct Empty::OversizedEmpty
89 // CHECK-NEXT: 0 | struct Empty::A (base) (empty)
90 // CHECK-NEXT: 1 | struct Empty::A a (empty)
91 // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
92 // CHECK-NEXT: | nvsize=2, nvalign=1]
94 struct HasOversizedEmpty {
95 [[no_unique_address]] OversizedEmpty m;
97 static_assert(sizeof(HasOversizedEmpty) == 2);
99 // CHECK:*** Dumping AST Record Layout
100 // CHECK: 0 | struct Empty::HasOversizedEmpty
101 // CHECK-NEXT: 0 | struct Empty::OversizedEmpty m (empty)
102 // CHECK-NEXT: 0 | struct Empty::A (base) (empty)
103 // CHECK-NEXT: 1 | struct Empty::A a (empty)
104 // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
105 // CHECK-NEXT: | nvsize=2, nvalign=1]
107 struct EmptyWithNonzeroDSize {
108 [[no_unique_address]] A a;
109 int x;
110 [[no_unique_address]] A b;
111 int y;
112 [[no_unique_address]] A c;
114 static_assert(sizeof(EmptyWithNonzeroDSize) == 12);
116 // CHECK:*** Dumping AST Record Layout
117 // CHECK: 0 | struct Empty::EmptyWithNonzeroDSize
118 // CHECK-NEXT: 0 | struct Empty::A a (empty)
119 // CHECK-NEXT: 0 | int x
120 // CHECK-NEXT: 4 | struct Empty::A b (empty)
121 // CHECK-NEXT: 4 | int y
122 // CHECK-NEXT: 8 | struct Empty::A c (empty)
123 // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,
124 // CHECK-NEXT: | nvsize=12, nvalign=4]
126 struct EmptyWithNonzeroDSizeNonPOD {
127 ~EmptyWithNonzeroDSizeNonPOD();
128 [[no_unique_address]] A a;
129 int x;
130 [[no_unique_address]] A b;
131 int y;
132 [[no_unique_address]] A c;
134 static_assert(sizeof(EmptyWithNonzeroDSizeNonPOD) == 12);
136 // CHECK:*** Dumping AST Record Layout
137 // CHECK: 0 | struct Empty::EmptyWithNonzeroDSizeNonPOD
138 // CHECK-NEXT: 0 | struct Empty::A a (empty)
139 // CHECK-NEXT: 0 | int x
140 // CHECK-NEXT: 4 | struct Empty::A b (empty)
141 // CHECK-NEXT: 4 | int y
142 // CHECK-NEXT: 8 | struct Empty::A c (empty)
143 // CHECK-NEXT: | [sizeof=12, dsize=8, align=4,
144 // CHECK-NEXT: | nvsize=9, nvalign=4]
147 namespace POD {
148 // Cannot reuse tail padding of a PDO type.
149 struct A { int n; char c[3]; };
150 struct B { [[no_unique_address]] A a; char d; };
151 static_assert(sizeof(B) == 12);
153 // CHECK:*** Dumping AST Record Layout
154 // CHECK: 0 | struct POD::B
155 // CHECK-NEXT: 0 | struct POD::A a
156 // CHECK-NEXT: 0 | int n
157 // CHECK-NEXT: 4 | char[3] c
158 // CHECK-NEXT: 8 | char d
159 // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,
160 // CHECK-NEXT: | nvsize=12, nvalign=4]
163 namespace NonPOD {
164 struct A { int n; char c[3]; ~A(); };
165 struct B { [[no_unique_address]] A a; char d; };
166 static_assert(sizeof(B) == 8);
168 // CHECK:*** Dumping AST Record Layout
169 // CHECK: 0 | struct NonPOD::B
170 // CHECK-NEXT: 0 | struct NonPOD::A a
171 // CHECK-NEXT: 0 | int n
172 // CHECK-NEXT: 4 | char[3] c
173 // CHECK-NEXT: 7 | char d
174 // CHECK-NEXT: | [sizeof=8, dsize=8, align=4,
175 // CHECK-NEXT: | nvsize=8, nvalign=4]
178 namespace NVSizeGreaterThanDSize {
179 // The nvsize of an object includes the complete size of its empty subobjects
180 // (although it's unclear why). Ensure this corner case is handled properly.
181 struct alignas(8) A { ~A(); }; // dsize 0, nvsize 0, size 8
182 struct B : A { char c; }; // dsize 1, nvsize 8, size 8
183 static_assert(sizeof(B) == 8);
185 // CHECK:*** Dumping AST Record Layout
186 // CHECK: 0 | struct NVSizeGreaterThanDSize::B
187 // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A (base) (empty)
188 // CHECK-NEXT: 0 | char c
189 // CHECK-NEXT: | [sizeof=8, dsize=1, align=8,
190 // CHECK-NEXT: | nvsize=8, nvalign=8]
192 struct V { int n; };
194 // V is at offset 16, not offset 12, because B's tail padding is strangely not
195 // usable for virtual bases.
196 struct C : B, virtual V {};
197 static_assert(sizeof(C) == 24);
199 // CHECK:*** Dumping AST Record Layout
200 // CHECK: 0 | struct NVSizeGreaterThanDSize::C
201 // CHECK-NEXT: 0 | (C vtable pointer)
202 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B (base)
203 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)
204 // CHECK-NEXT: 8 | char c
205 // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)
206 // CHECK-NEXT: 16 | int n
207 // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,
208 // CHECK-NEXT: | nvsize=16, nvalign=8]
210 struct D : virtual V {
211 [[no_unique_address]] B b;
213 static_assert(sizeof(D) == 24);
215 // CHECK:*** Dumping AST Record Layout
216 // CHECK: 0 | struct NVSizeGreaterThanDSize::D
217 // CHECK-NEXT: 0 | (D vtable pointer)
218 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B b
219 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)
220 // CHECK-NEXT: 8 | char c
221 // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)
222 // CHECK-NEXT: 16 | int n
223 // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,
224 // CHECK-NEXT: | nvsize=16, nvalign=8]
226 struct X : virtual A { [[no_unique_address]] A a; };
227 struct E : virtual A {
228 [[no_unique_address]] A a;
229 // Here, we arrange for X to hang over the end of the nvsize of E. This
230 // should force the A vbase to be laid out at offset 24, not 16.
231 [[no_unique_address]] X x;
233 static_assert(sizeof(E) == 32);
235 // CHECK:*** Dumping AST Record Layout
236 // CHECK: 0 | struct NVSizeGreaterThanDSize::E
237 // CHECK-NEXT: 0 | (E vtable pointer)
238 // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A a (empty)
239 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::X x
240 // CHECK-NEXT: 8 | (X vtable pointer)
241 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A a (empty)
242 // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)
243 // CHECK-NEXT: 24 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)
244 // CHECK-NEXT: | [sizeof=32, dsize=16, align=8,
245 // CHECK-NEXT: | nvsize=16, nvalign=8]
248 namespace RepeatedVBase {
249 struct alignas(16) A { ~A(); };
250 struct B : A {};
251 struct X : virtual A, virtual B {};
252 struct Y { [[no_unique_address]] X x; char c; };
253 static_assert(sizeof(Y) == 32);
255 // CHECK:*** Dumping AST Record Layout
256 // CHECK: 0 | struct RepeatedVBase::Y
257 // CHECK-NEXT: 0 | struct RepeatedVBase::X x
258 // CHECK-NEXT: 0 | (X vtable pointer)
259 // CHECK-NEXT: 0 | struct RepeatedVBase::A (virtual base) (empty)
260 // CHECK-NEXT: 16 | struct RepeatedVBase::B (virtual base) (empty)
261 // CHECK-NEXT: 16 | struct RepeatedVBase::A (base) (empty)
262 // CHECK-NEXT: 8 | char c
263 // CHECK-NEXT: | [sizeof=32, dsize=9, align=16,
264 // CHECK-NEXT: | nvsize=9, nvalign=16]