[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / AST / ByteCode / unions.cpp
blob7b39bb1bb9316e7e94a49f1f4eabe1c9d465c894
1 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
2 // RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s
3 // RUN: %clang_cc1 -verify=ref,both %s
4 // RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
6 union U {
7 int a;
8 int b;
9 };
11 constexpr U a = {12};
12 static_assert(a.a == 12, "");
13 static_assert(a.b == 0, ""); // both-error {{not an integral constant expression}} \
14 // both-note {{read of member 'b' of union with active member 'a'}}
15 union U1 {
16 int i;
17 float f = 3.0f;
19 constexpr U1 u1{};
20 static_assert(u1.f == 3.0, "");
21 static_assert(u1.i == 1, ""); // both-error {{not an integral constant expression}} \
22 // both-note {{read of member 'i' of union with active member 'f'}}
26 union A {
27 int a;
28 double d;
30 constexpr A aa = {1, 2.0}; // both-error {{excess elements in union initializer}}
31 constexpr A ab = {.d = 1.0};
32 static_assert(ab.d == 1.0, "");
33 static_assert(ab.a == 1, ""); // both-error {{not an integral constant expression}} \
34 // both-note {{read of member 'a' of union with active member 'd'}}
37 namespace Empty {
38 union E {};
39 constexpr E e{};
42 namespace SimpleStore {
43 union A {
44 int a;
45 int b;
47 constexpr int foo() {
48 A a{.b = 4};
49 a.b = 10;
50 return a.b;
52 static_assert(foo() == 10, "");
54 constexpr int empty() {
55 A a{}; /// Just test that this works.
56 return 10;
58 static_assert(empty() == 10, "");
61 namespace ZeroInit {
62 struct S { int m; };
63 union Z {
64 float f;
67 constexpr Z z{};
68 static_assert(z.f == 0.0, "");
71 namespace DefaultInit {
72 union U1 {
73 constexpr U1() {}
74 int a, b = 42;
77 constexpr U1 u1; /// OK.
79 constexpr int foo() {
80 U1 u;
81 return u.a; // both-note {{read of member 'a' of union with active member 'b'}}
83 static_assert(foo() == 42); // both-error {{not an integral constant expression}} \
84 // both-note {{in call to}}
87 #if __cplusplus >= 202002L
88 namespace SimpleActivate {
89 constexpr int foo() { // both-error {{never produces a constant expression}}
90 union {
91 int a;
92 int b;
93 } Z;
95 Z.a = 10;
96 Z.b = 20;
97 return Z.a; // both-note 2{{read of member 'a' of union with active member 'b'}}
99 static_assert(foo() == 20); // both-error {{not an integral constant expression}} \
100 // both-note {{in call to}}
102 constexpr int foo2() {
103 union {
104 int a;
105 int b;
106 } Z;
108 Z.a = 10;
109 Z.b = 20;
110 return Z.b;
112 static_assert(foo2() == 20);
115 constexpr int foo3() {
116 union {
117 struct {
118 float x,y;
119 } a;
120 int b;
121 } Z;
123 Z.a.y = 10;
125 return Z.a.x; // both-note {{read of uninitialized object}}
127 static_assert(foo3() == 10); // both-error {{not an integral constant expression}} \
128 // both-note {{in call to}}
130 constexpr int foo4() {
131 union {
132 struct {
133 float x,y;
134 } a;
135 int b;
136 } Z;
138 Z.a.x = 100;
139 Z.a.y = 10;
141 return Z.a.x;
143 static_assert(foo4() == 100);
146 namespace IndirectFieldDecl {
147 struct C {
148 union { int a, b = 2, c; };
149 union { int d, e = 5, f; };
150 constexpr C() : a(1) {}
152 static_assert(C().a == 1, "");
155 namespace UnionDtor {
157 union U {
158 int *I;
159 constexpr U(int *I) : I(I) {}
160 constexpr ~U() {
161 *I = 10;
165 constexpr int foo() {
166 int a = 100;
168 U u(&a);
170 return a;
172 static_assert(foo() == 10);
175 namespace UnionMemberDtor {
176 class UM {
177 public:
178 int &I;
179 constexpr UM(int &I) : I(I) {}
180 constexpr ~UM() { I = 200; }
183 union U {
184 UM um;
185 constexpr U(int &I) : um(I) {}
186 constexpr ~U() {
190 constexpr int foo() {
191 int a = 100;
193 U u(a);
196 return a;
198 static_assert(foo() == 100);
201 namespace Nested {
202 union U {
203 int a;
204 int b;
207 union U2 {
208 U u;
209 U u2;
210 int x;
211 int y;
214 constexpr int foo() { // both-error {{constexpr function never produces a constant expression}}
215 U2 u;
216 u.u.a = 10;
217 int a = u.y; // both-note 2{{read of member 'y' of union with active member 'u' is not allowed in a constant expression}}
219 return 1;
221 static_assert(foo() == 1); // both-error {{not an integral constant expression}} \
222 // both-note {{in call to}}
224 constexpr int foo2() {
225 U2 u;
226 u.u.a = 10;
227 return u.u.a;
229 static_assert(foo2() == 10);
231 constexpr int foo3() { // both-error {{constexpr function never produces a constant expression}}
232 U2 u;
233 u.u.a = 10;
234 int a = u.u.b; // both-note 2{{read of member 'b' of union with active member 'a' is not allowed in a constant expression}}
236 return 1;
238 static_assert(foo3() == 1); // both-error {{not an integral constant expression}} \
239 // both-note {{in call to}}
241 constexpr int foo4() { // both-error {{constexpr function never produces a constant expression}}
242 U2 u;
244 u.x = 10;
246 return u.u.a; // both-note 2{{read of member 'u' of union with active member 'x' is not allowed in a constant expression}}
248 static_assert(foo4() == 1); // both-error {{not an integral constant expression}} \
249 // both-note {{in call to}}
254 namespace Zeroing {
255 struct non_trivial_constructor {
256 constexpr non_trivial_constructor() : x(100) {}
257 int x;
259 union U2 {
260 int a{1000};
261 non_trivial_constructor b;
264 static_assert(U2().b.x == 100, ""); // both-error {{not an integral constant expression}} \
265 // both-note {{read of member 'b' of union with active member 'a'}}
267 union { int a; int b; } constexpr u1{};
268 static_assert(u1.a == 0, "");
269 static_assert(u1.b == 0, ""); // both-error {{not an integral constant expression}} \
270 // both-note {{read of member 'b' of union with active member 'a'}}
272 union U { int a; int b; } constexpr u2 = U();
273 static_assert(u2.a == 0, "");
274 static_assert(u2.b == 0, ""); // both-error {{not an integral constant expression}} \
275 // both-note {{read of member 'b' of union with active member 'a'}}
278 struct F {int x; int y; };
279 union { F a; int b; } constexpr u3{};
280 static_assert(u3.a.x == 0, "");
282 union U4 { F a; int b; } constexpr u4 = U4();
283 static_assert(u4.a.x == 0, "");
285 union { int a[5]; int b; } constexpr u5{};
286 static_assert(u5.a[0] == 0, "");
287 static_assert(u5.a[4] == 0, "");
288 static_assert(u5.b == 0, ""); // both-error {{not an integral constant expression}} \
289 // both-note {{read of member 'b' of union with active member 'a'}}
291 union U6 { int a[5]; int b; } constexpr u6 = U6();
292 static_assert(u6.a[0] == 0, "");
293 static_assert(u6.a[4] == 0, "");
294 static_assert(u6.b == 0, ""); // both-error {{not an integral constant expression}} \
295 // both-note {{read of member 'b' of union with active member 'a'}}
297 union UnionWithUnnamedBitfield {
298 int : 3;
299 int n;
301 static_assert(UnionWithUnnamedBitfield().n == 0, "");
302 static_assert(UnionWithUnnamedBitfield{}.n == 0, "");
303 static_assert(UnionWithUnnamedBitfield{1}.n == 1, "");
306 namespace IndirectField {
307 struct S {
308 struct {
309 union {
310 struct {
311 int a;
312 int b;
314 int c;
316 int d;
318 union {
319 int e;
320 int f;
322 constexpr S(int a, int b, int d, int e) : a(a), b(b), d(d), e(e) {}
323 constexpr S(int c, int d, int f) : c(c), d(d), f(f) {}
326 constexpr S s1(1,2,3,4);
327 constexpr S s2(5, 6, 7);
329 static_assert(s1.a == 1, "");
330 static_assert(s1.b == 2, "");
332 static_assert(s1.c == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
333 static_assert(s1.d == 3, "");
334 static_assert(s1.e == 4, "");
335 static_assert(s1.f == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
337 static_assert(s2.a == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
338 static_assert(s2.b == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
339 static_assert(s2.c == 5, "");
340 static_assert(s2.d == 6, "");
341 static_assert(s2.e == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
342 static_assert(s2.f == 7, "");
345 namespace CopyCtor {
346 union U {
347 int a;
348 int b;
351 constexpr U x = {42};
352 constexpr U y = x;
353 static_assert(y.a == 42, "");
354 static_assert(y.b == 42, ""); // both-error {{constant expression}} \
355 // both-note {{'b' of union with active member 'a'}}
358 namespace UnionInBase {
359 struct Base {
360 int y; // both-note {{subobject declared here}}
362 struct A : Base {
363 int x;
364 int arr[3];
365 union { int p, q; };
367 union B {
368 A a;
369 int b;
371 constexpr int read_wrong_member_indirect() { // both-error {{never produces a constant}}
372 B b = {.b = 1};
373 int *p = &b.a.y;
374 return *p; // both-note 2{{read of member 'a' of union with active member 'b'}}
377 static_assert(read_wrong_member_indirect() == 1); // both-error {{not an integral constant expression}} \
378 // both-note {{in call to}}
379 constexpr int read_uninitialized() {
380 B b = {.b = 1};
381 int *p = &b.a.y;
382 b.a.x = 1;
383 return *p; // both-note {{read of uninitialized object}}
385 static_assert(read_uninitialized() == 0); // both-error {{constant}} \
386 // both-note {{in call}}
387 constexpr int write_uninitialized() {
388 B b = {.b = 1};
389 int *p = &b.a.y;
390 b.a.x = 1;
391 *p = 1;
392 return *p;
395 constexpr B return_uninit() {
396 B b = {.b = 1};
397 b.a.x = 2;
398 return b;
400 constexpr B uninit = return_uninit(); // both-error {{constant expression}} \
401 // both-note {{subobject 'y' is not initialized}}
402 static_assert(return_uninit().a.x == 2);
404 #endif