xref: /llvm-project/clang/test/AST/ByteCode/unions.cpp (revision ac857f9bdd500d274d7996e0fa14aaf8b765d745)
1a07aba5dSTimm Baeder // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
2a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s
3a07aba5dSTimm Baeder // RUN: %clang_cc1 -verify=ref,both %s
4a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
5a07aba5dSTimm Baeder 
6a07aba5dSTimm Baeder union U {
7a07aba5dSTimm Baeder   int a;
8a07aba5dSTimm Baeder   int b;
9a07aba5dSTimm Baeder };
10a07aba5dSTimm Baeder 
11a07aba5dSTimm Baeder constexpr U a = {12};
12a07aba5dSTimm Baeder static_assert(a.a == 12, "");
13a07aba5dSTimm Baeder static_assert(a.b == 0, ""); // both-error {{not an integral constant expression}} \
14a07aba5dSTimm Baeder                              // both-note {{read of member 'b' of union with active member 'a'}}
15a07aba5dSTimm Baeder union U1 {
16a07aba5dSTimm Baeder   int i;
17a07aba5dSTimm Baeder   float f = 3.0f;
18a07aba5dSTimm Baeder };
19a07aba5dSTimm Baeder constexpr U1 u1{};
20a07aba5dSTimm Baeder static_assert(u1.f == 3.0, "");
21a07aba5dSTimm Baeder static_assert(u1.i == 1, ""); // both-error {{not an integral constant expression}} \
22a07aba5dSTimm Baeder                               // both-note {{read of member 'i' of union with active member 'f'}}
23a07aba5dSTimm Baeder 
24a07aba5dSTimm Baeder 
25a07aba5dSTimm Baeder 
26a07aba5dSTimm Baeder union A {
27a07aba5dSTimm Baeder   int a;
28a07aba5dSTimm Baeder   double d;
29a07aba5dSTimm Baeder };
30a07aba5dSTimm Baeder constexpr A aa = {1, 2.0}; // both-error {{excess elements in union initializer}}
31a07aba5dSTimm Baeder constexpr A ab = {.d = 1.0};
32a07aba5dSTimm Baeder static_assert(ab.d == 1.0, "");
33a07aba5dSTimm Baeder static_assert(ab.a == 1, ""); // both-error {{not an integral constant expression}} \
34a07aba5dSTimm Baeder                               // both-note {{read of member 'a' of union with active member 'd'}}
35a07aba5dSTimm Baeder 
36a07aba5dSTimm Baeder 
37a07aba5dSTimm Baeder namespace Empty {
38a07aba5dSTimm Baeder   union E {};
39a07aba5dSTimm Baeder   constexpr E e{};
40a07aba5dSTimm Baeder }
41a07aba5dSTimm Baeder 
42a07aba5dSTimm Baeder namespace SimpleStore {
43a07aba5dSTimm Baeder   union A {
44a07aba5dSTimm Baeder     int a;
45a07aba5dSTimm Baeder     int b;
46a07aba5dSTimm Baeder   };
47a07aba5dSTimm Baeder   constexpr int foo() {
48a07aba5dSTimm Baeder     A a{.b = 4};
49a07aba5dSTimm Baeder     a.b = 10;
50a07aba5dSTimm Baeder     return a.b;
51a07aba5dSTimm Baeder   }
52a07aba5dSTimm Baeder   static_assert(foo() == 10, "");
53a07aba5dSTimm Baeder 
54a07aba5dSTimm Baeder   constexpr int empty() {
55a07aba5dSTimm Baeder     A a{}; /// Just test that this works.
56a07aba5dSTimm Baeder     return 10;
57a07aba5dSTimm Baeder   }
58a07aba5dSTimm Baeder   static_assert(empty() == 10, "");
59a07aba5dSTimm Baeder }
60a07aba5dSTimm Baeder 
61a07aba5dSTimm Baeder namespace ZeroInit {
62a07aba5dSTimm Baeder   struct S { int m; };
63a07aba5dSTimm Baeder   union Z {
64a07aba5dSTimm Baeder     float f;
65a07aba5dSTimm Baeder   };
66a07aba5dSTimm Baeder 
67a07aba5dSTimm Baeder   constexpr Z z{};
68a07aba5dSTimm Baeder   static_assert(z.f == 0.0, "");
69a07aba5dSTimm Baeder }
70a07aba5dSTimm Baeder 
71a07aba5dSTimm Baeder namespace DefaultInit {
72a07aba5dSTimm Baeder   union U1 {
73a07aba5dSTimm Baeder     constexpr U1() {}
74a07aba5dSTimm Baeder     int a, b = 42;
75a07aba5dSTimm Baeder   };
76a07aba5dSTimm Baeder 
77a07aba5dSTimm Baeder   constexpr U1 u1; /// OK.
78a07aba5dSTimm Baeder 
79a07aba5dSTimm Baeder   constexpr int foo() {
80a07aba5dSTimm Baeder     U1 u;
81a07aba5dSTimm Baeder     return u.a; // both-note {{read of member 'a' of union with active member 'b'}}
82a07aba5dSTimm Baeder   }
83a07aba5dSTimm Baeder   static_assert(foo() == 42); // both-error {{not an integral constant expression}} \
84a07aba5dSTimm Baeder                               // both-note {{in call to}}
85a07aba5dSTimm Baeder }
86a07aba5dSTimm Baeder 
87a07aba5dSTimm Baeder #if __cplusplus >= 202002L
88a07aba5dSTimm Baeder namespace SimpleActivate {
89df11ee21STimm Baeder   constexpr int foo() { // both-error {{never produces a constant expression}}
90a07aba5dSTimm Baeder     union {
91a07aba5dSTimm Baeder       int a;
92a07aba5dSTimm Baeder       int b;
93a07aba5dSTimm Baeder     } Z;
94a07aba5dSTimm Baeder 
95a07aba5dSTimm Baeder     Z.a = 10;
96a07aba5dSTimm Baeder     Z.b = 20;
97df11ee21STimm Baeder     return Z.a; // both-note 2{{read of member 'a' of union with active member 'b'}}
98a07aba5dSTimm Baeder   }
99a07aba5dSTimm Baeder   static_assert(foo() == 20); // both-error {{not an integral constant expression}} \
100a07aba5dSTimm Baeder                               // both-note {{in call to}}
101a07aba5dSTimm Baeder 
102a07aba5dSTimm Baeder   constexpr int foo2() {
103a07aba5dSTimm Baeder     union {
104a07aba5dSTimm Baeder       int a;
105a07aba5dSTimm Baeder       int b;
106a07aba5dSTimm Baeder     } Z;
107a07aba5dSTimm Baeder 
108a07aba5dSTimm Baeder     Z.a = 10;
109a07aba5dSTimm Baeder     Z.b = 20;
110a07aba5dSTimm Baeder     return Z.b;
111a07aba5dSTimm Baeder   }
112a07aba5dSTimm Baeder   static_assert(foo2() == 20);
113a07aba5dSTimm Baeder 
114a07aba5dSTimm Baeder 
115a07aba5dSTimm Baeder   constexpr int foo3() {
116a07aba5dSTimm Baeder     union {
117a07aba5dSTimm Baeder       struct {
118a07aba5dSTimm Baeder         float x,y;
119a07aba5dSTimm Baeder       } a;
120a07aba5dSTimm Baeder       int b;
121a07aba5dSTimm Baeder     } Z;
122a07aba5dSTimm Baeder 
123a07aba5dSTimm Baeder     Z.a.y = 10;
124a07aba5dSTimm Baeder 
125a07aba5dSTimm Baeder     return Z.a.x; // both-note {{read of uninitialized object}}
126a07aba5dSTimm Baeder   }
127a07aba5dSTimm Baeder   static_assert(foo3() == 10); // both-error {{not an integral constant expression}} \
128a07aba5dSTimm Baeder                                // both-note {{in call to}}
129a07aba5dSTimm Baeder 
130a07aba5dSTimm Baeder   constexpr int foo4() {
131a07aba5dSTimm Baeder     union {
132a07aba5dSTimm Baeder       struct {
133a07aba5dSTimm Baeder         float x,y;
134a07aba5dSTimm Baeder       } a;
135a07aba5dSTimm Baeder       int b;
136a07aba5dSTimm Baeder     } Z;
137a07aba5dSTimm Baeder 
138a07aba5dSTimm Baeder     Z.a.x = 100;
139a07aba5dSTimm Baeder     Z.a.y = 10;
140a07aba5dSTimm Baeder 
141a07aba5dSTimm Baeder     return Z.a.x;
142a07aba5dSTimm Baeder   }
143a07aba5dSTimm Baeder   static_assert(foo4() == 100);
144a07aba5dSTimm Baeder }
145a07aba5dSTimm Baeder 
146a07aba5dSTimm Baeder namespace IndirectFieldDecl {
147a07aba5dSTimm Baeder   struct C {
148a07aba5dSTimm Baeder     union { int a, b = 2, c; };
149a07aba5dSTimm Baeder     union { int d, e = 5, f; };
150a07aba5dSTimm Baeder     constexpr C() : a(1) {}
151a07aba5dSTimm Baeder   };
152a07aba5dSTimm Baeder   static_assert(C().a == 1, "");
153a07aba5dSTimm Baeder }
154a07aba5dSTimm Baeder 
155a07aba5dSTimm Baeder namespace UnionDtor {
156a07aba5dSTimm Baeder 
157a07aba5dSTimm Baeder   union U {
158a07aba5dSTimm Baeder     int *I;
159a07aba5dSTimm Baeder     constexpr U(int *I) : I(I) {}
160a07aba5dSTimm Baeder     constexpr ~U() {
161a07aba5dSTimm Baeder       *I = 10;
162a07aba5dSTimm Baeder     }
163a07aba5dSTimm Baeder   };
164a07aba5dSTimm Baeder 
165a07aba5dSTimm Baeder   constexpr int foo() {
166a07aba5dSTimm Baeder     int a = 100;
167a07aba5dSTimm Baeder     {
168a07aba5dSTimm Baeder       U u(&a);
169a07aba5dSTimm Baeder     }
170a07aba5dSTimm Baeder     return a;
171a07aba5dSTimm Baeder   }
172a07aba5dSTimm Baeder   static_assert(foo() == 10);
173a07aba5dSTimm Baeder }
174a07aba5dSTimm Baeder 
175a07aba5dSTimm Baeder namespace UnionMemberDtor {
176a07aba5dSTimm Baeder   class UM {
177a07aba5dSTimm Baeder   public:
178a07aba5dSTimm Baeder     int &I;
179a07aba5dSTimm Baeder     constexpr UM(int &I) : I(I) {}
180a07aba5dSTimm Baeder     constexpr ~UM() { I = 200; }
181a07aba5dSTimm Baeder   };
182a07aba5dSTimm Baeder 
183a07aba5dSTimm Baeder   union U {
184a07aba5dSTimm Baeder     UM um;
185a07aba5dSTimm Baeder     constexpr U(int &I) : um(I) {}
186a07aba5dSTimm Baeder     constexpr ~U() {
187a07aba5dSTimm Baeder     }
188a07aba5dSTimm Baeder   };
189a07aba5dSTimm Baeder 
190a07aba5dSTimm Baeder   constexpr int foo() {
191a07aba5dSTimm Baeder     int a = 100;
192a07aba5dSTimm Baeder     {
193a07aba5dSTimm Baeder       U u(a);
194a07aba5dSTimm Baeder     }
195a07aba5dSTimm Baeder 
196a07aba5dSTimm Baeder     return a;
197a07aba5dSTimm Baeder   }
198a07aba5dSTimm Baeder   static_assert(foo() == 100);
199a07aba5dSTimm Baeder }
200a07aba5dSTimm Baeder 
201a07aba5dSTimm Baeder namespace Nested {
202a07aba5dSTimm Baeder   union U {
203a07aba5dSTimm Baeder     int a;
204a07aba5dSTimm Baeder     int b;
205a07aba5dSTimm Baeder   };
206a07aba5dSTimm Baeder 
207a07aba5dSTimm Baeder   union U2 {
208a07aba5dSTimm Baeder     U u;
209a07aba5dSTimm Baeder     U u2;
210a07aba5dSTimm Baeder     int x;
211a07aba5dSTimm Baeder     int y;
212a07aba5dSTimm Baeder   };
213a07aba5dSTimm Baeder 
214df11ee21STimm Baeder  constexpr int foo() { // both-error {{constexpr function never produces a constant expression}}
215a07aba5dSTimm Baeder     U2 u;
216a07aba5dSTimm Baeder     u.u.a = 10;
217df11ee21STimm Baeder     int a = u.y; // both-note 2{{read of member 'y' of union with active member 'u' is not allowed in a constant expression}}
218a07aba5dSTimm Baeder 
219a07aba5dSTimm Baeder     return 1;
220a07aba5dSTimm Baeder   }
221a07aba5dSTimm Baeder   static_assert(foo() == 1); // both-error {{not an integral constant expression}} \
222a07aba5dSTimm Baeder                              // both-note {{in call to}}
223a07aba5dSTimm Baeder 
224a07aba5dSTimm Baeder  constexpr int foo2() {
225a07aba5dSTimm Baeder     U2 u;
226a07aba5dSTimm Baeder     u.u.a = 10;
227a07aba5dSTimm Baeder     return u.u.a;
228a07aba5dSTimm Baeder   }
229a07aba5dSTimm Baeder   static_assert(foo2() == 10);
230a07aba5dSTimm Baeder 
231df11ee21STimm Baeder  constexpr int foo3() { // both-error {{constexpr function never produces a constant expression}}
232a07aba5dSTimm Baeder     U2 u;
233a07aba5dSTimm Baeder     u.u.a = 10;
234df11ee21STimm Baeder     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}}
235a07aba5dSTimm Baeder 
236a07aba5dSTimm Baeder     return 1;
237a07aba5dSTimm Baeder   }
238a07aba5dSTimm Baeder   static_assert(foo3() == 1); // both-error {{not an integral constant expression}} \
239a07aba5dSTimm Baeder                               // both-note {{in call to}}
240a07aba5dSTimm Baeder 
241df11ee21STimm Baeder   constexpr int foo4() { // both-error {{constexpr function never produces a constant expression}}
242a07aba5dSTimm Baeder     U2 u;
243a07aba5dSTimm Baeder 
244a07aba5dSTimm Baeder     u.x = 10;
245a07aba5dSTimm Baeder 
246df11ee21STimm Baeder     return u.u.a; // both-note 2{{read of member 'u' of union with active member 'x' is not allowed in a constant expression}}
247a07aba5dSTimm Baeder   }
248a07aba5dSTimm Baeder   static_assert(foo4() == 1); // both-error {{not an integral constant expression}} \
249a07aba5dSTimm Baeder                               // both-note {{in call to}}
250a07aba5dSTimm Baeder 
251a07aba5dSTimm Baeder }
252a07aba5dSTimm Baeder 
253a07aba5dSTimm Baeder 
254a07aba5dSTimm Baeder namespace Zeroing {
255a07aba5dSTimm Baeder   struct non_trivial_constructor {
256a07aba5dSTimm Baeder       constexpr non_trivial_constructor() : x(100) {}
257a07aba5dSTimm Baeder       int x;
258a07aba5dSTimm Baeder   };
259a07aba5dSTimm Baeder   union U2 {
260a07aba5dSTimm Baeder       int a{1000};
261a07aba5dSTimm Baeder       non_trivial_constructor b;
262a07aba5dSTimm Baeder   };
263a07aba5dSTimm Baeder 
264a07aba5dSTimm Baeder   static_assert(U2().b.x == 100, ""); // both-error {{not an integral constant expression}} \
265a07aba5dSTimm Baeder                                       // both-note {{read of member 'b' of union with active member 'a'}}
266a07aba5dSTimm Baeder 
267a07aba5dSTimm Baeder   union { int a; int b; } constexpr u1{};
268a07aba5dSTimm Baeder   static_assert(u1.a == 0, "");
269a07aba5dSTimm Baeder   static_assert(u1.b == 0, ""); // both-error {{not an integral constant expression}} \
270a07aba5dSTimm Baeder                                 // both-note {{read of member 'b' of union with active member 'a'}}
271a07aba5dSTimm Baeder 
272a07aba5dSTimm Baeder   union U { int a; int b; } constexpr u2 = U();
273a07aba5dSTimm Baeder   static_assert(u2.a == 0, "");
274a07aba5dSTimm Baeder   static_assert(u2.b == 0, ""); // both-error {{not an integral constant expression}} \
275a07aba5dSTimm Baeder                                 // both-note {{read of member 'b' of union with active member 'a'}}
276a07aba5dSTimm Baeder 
277a07aba5dSTimm Baeder 
278a07aba5dSTimm Baeder   struct F {int x; int y; };
279a07aba5dSTimm Baeder   union { F a; int b; } constexpr u3{};
280a07aba5dSTimm Baeder   static_assert(u3.a.x == 0, "");
281a07aba5dSTimm Baeder 
282a07aba5dSTimm Baeder   union U4 { F a; int b; } constexpr u4 = U4();
283a07aba5dSTimm Baeder   static_assert(u4.a.x == 0, "");
284a07aba5dSTimm Baeder 
285a07aba5dSTimm Baeder   union { int a[5]; int b; } constexpr u5{};
286a07aba5dSTimm Baeder   static_assert(u5.a[0] == 0, "");
287a07aba5dSTimm Baeder   static_assert(u5.a[4] == 0, "");
288a07aba5dSTimm Baeder   static_assert(u5.b == 0, ""); // both-error {{not an integral constant expression}} \
289a07aba5dSTimm Baeder                                 // both-note {{read of member 'b' of union with active member 'a'}}
290a07aba5dSTimm Baeder 
291a07aba5dSTimm Baeder   union U6 { int a[5]; int b; } constexpr u6 = U6();
292a07aba5dSTimm Baeder   static_assert(u6.a[0] == 0, "");
293a07aba5dSTimm Baeder   static_assert(u6.a[4] == 0, "");
294a07aba5dSTimm Baeder   static_assert(u6.b == 0, ""); // both-error {{not an integral constant expression}} \
295a07aba5dSTimm Baeder                                 // both-note {{read of member 'b' of union with active member 'a'}}
296a07aba5dSTimm Baeder 
297a07aba5dSTimm Baeder   union UnionWithUnnamedBitfield {
298a07aba5dSTimm Baeder     int : 3;
299a07aba5dSTimm Baeder     int n;
300a07aba5dSTimm Baeder   };
301a07aba5dSTimm Baeder   static_assert(UnionWithUnnamedBitfield().n == 0, "");
302a07aba5dSTimm Baeder   static_assert(UnionWithUnnamedBitfield{}.n == 0, "");
303a07aba5dSTimm Baeder   static_assert(UnionWithUnnamedBitfield{1}.n == 1, "");
304a07aba5dSTimm Baeder }
305a07aba5dSTimm Baeder 
306a07aba5dSTimm Baeder namespace IndirectField {
307a07aba5dSTimm Baeder   struct S {
308a07aba5dSTimm Baeder     struct {
309a07aba5dSTimm Baeder       union {
310a07aba5dSTimm Baeder         struct {
311a07aba5dSTimm Baeder           int a;
312a07aba5dSTimm Baeder           int b;
313a07aba5dSTimm Baeder         };
314a07aba5dSTimm Baeder         int c;
315a07aba5dSTimm Baeder       };
316a07aba5dSTimm Baeder       int d;
317a07aba5dSTimm Baeder     };
318a07aba5dSTimm Baeder     union {
319a07aba5dSTimm Baeder       int e;
320a07aba5dSTimm Baeder       int f;
321a07aba5dSTimm Baeder     };
322a07aba5dSTimm Baeder     constexpr S(int a, int b, int d, int e) : a(a), b(b), d(d), e(e) {}
323a07aba5dSTimm Baeder     constexpr S(int c, int d, int f) : c(c), d(d), f(f) {}
324a07aba5dSTimm Baeder   };
325a07aba5dSTimm Baeder 
326a07aba5dSTimm Baeder   constexpr S s1(1,2,3,4);
327a07aba5dSTimm Baeder   constexpr S s2(5, 6, 7);
328a07aba5dSTimm Baeder 
329a07aba5dSTimm Baeder   static_assert(s1.a == 1, "");
330a07aba5dSTimm Baeder   static_assert(s1.b == 2, "");
331a07aba5dSTimm Baeder 
332a07aba5dSTimm Baeder   static_assert(s1.c == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
333a07aba5dSTimm Baeder   static_assert(s1.d == 3, "");
334a07aba5dSTimm Baeder   static_assert(s1.e == 4, "");
335a07aba5dSTimm Baeder   static_assert(s1.f == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
336a07aba5dSTimm Baeder 
337a07aba5dSTimm Baeder   static_assert(s2.a == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
338a07aba5dSTimm Baeder   static_assert(s2.b == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
339a07aba5dSTimm Baeder   static_assert(s2.c == 5, "");
340a07aba5dSTimm Baeder   static_assert(s2.d == 6, "");
341a07aba5dSTimm Baeder   static_assert(s2.e == 0, ""); // both-error {{constant expression}} both-note {{union with active member}}
342a07aba5dSTimm Baeder   static_assert(s2.f == 7, "");
343a07aba5dSTimm Baeder }
344a07aba5dSTimm Baeder 
345a07aba5dSTimm Baeder namespace CopyCtor {
346a07aba5dSTimm Baeder   union U {
347a07aba5dSTimm Baeder     int a;
348a07aba5dSTimm Baeder     int b;
349a07aba5dSTimm Baeder   };
350a07aba5dSTimm Baeder 
351a07aba5dSTimm Baeder   constexpr U x = {42};
352a07aba5dSTimm Baeder   constexpr U y = x;
353a07aba5dSTimm Baeder   static_assert(y.a == 42, "");
354a07aba5dSTimm Baeder   static_assert(y.b == 42, ""); // both-error {{constant expression}} \
355a07aba5dSTimm Baeder                                 // both-note {{'b' of union with active member 'a'}}
356a07aba5dSTimm Baeder }
357a07aba5dSTimm Baeder 
358a07aba5dSTimm Baeder namespace UnionInBase {
359a07aba5dSTimm Baeder   struct Base {
360a07aba5dSTimm Baeder     int y; // both-note {{subobject declared here}}
361a07aba5dSTimm Baeder   };
362a07aba5dSTimm Baeder   struct A : Base {
363a07aba5dSTimm Baeder     int x;
364a07aba5dSTimm Baeder     int arr[3];
365a07aba5dSTimm Baeder     union { int p, q; };
366a07aba5dSTimm Baeder   };
367a07aba5dSTimm Baeder   union B {
368a07aba5dSTimm Baeder     A a;
369a07aba5dSTimm Baeder     int b;
370a07aba5dSTimm Baeder   };
371a07aba5dSTimm Baeder   constexpr int read_wrong_member_indirect() { // both-error {{never produces a constant}}
372a07aba5dSTimm Baeder     B b = {.b = 1};
373a07aba5dSTimm Baeder     int *p = &b.a.y;
374a07aba5dSTimm Baeder     return *p; // both-note 2{{read of member 'a' of union with active member 'b'}}
375a07aba5dSTimm Baeder 
376a07aba5dSTimm Baeder   }
377a07aba5dSTimm Baeder   static_assert(read_wrong_member_indirect() == 1); // both-error {{not an integral constant expression}} \
378a07aba5dSTimm Baeder                                                     // both-note {{in call to}}
379a07aba5dSTimm Baeder   constexpr int read_uninitialized() {
380a07aba5dSTimm Baeder     B b = {.b = 1};
381a07aba5dSTimm Baeder     int *p = &b.a.y;
382a07aba5dSTimm Baeder     b.a.x = 1;
383a07aba5dSTimm Baeder     return *p; // both-note {{read of uninitialized object}}
384a07aba5dSTimm Baeder   }
385a07aba5dSTimm Baeder   static_assert(read_uninitialized() == 0); // both-error {{constant}} \
386a07aba5dSTimm Baeder                                             // both-note {{in call}}
387a07aba5dSTimm Baeder   constexpr int write_uninitialized() {
388a07aba5dSTimm Baeder     B b = {.b = 1};
389a07aba5dSTimm Baeder     int *p = &b.a.y;
390a07aba5dSTimm Baeder     b.a.x = 1;
391a07aba5dSTimm Baeder     *p = 1;
392a07aba5dSTimm Baeder     return *p;
393a07aba5dSTimm Baeder   }
394a07aba5dSTimm Baeder 
395a07aba5dSTimm Baeder   constexpr B return_uninit() {
396a07aba5dSTimm Baeder     B b = {.b = 1};
397a07aba5dSTimm Baeder     b.a.x = 2;
398a07aba5dSTimm Baeder     return b;
399a07aba5dSTimm Baeder   }
400a07aba5dSTimm Baeder   constexpr B uninit = return_uninit(); // both-error {{constant expression}} \
401a07aba5dSTimm Baeder                                         // both-note {{subobject 'y' is not initialized}}
402a07aba5dSTimm Baeder   static_assert(return_uninit().a.x == 2);
403a07aba5dSTimm Baeder }
404*ac857f9bSTimm Baeder 
405*ac857f9bSTimm Baeder /// FIXME: Our diagnostic here is a little off.
406*ac857f9bSTimm Baeder namespace One {
407*ac857f9bSTimm Baeder   struct A { long x; };
408*ac857f9bSTimm Baeder 
409*ac857f9bSTimm Baeder   union U;
410*ac857f9bSTimm Baeder   constexpr A foo(U *up);
411*ac857f9bSTimm Baeder   union U {
412*ac857f9bSTimm Baeder     A a = foo(this); // both-note {{in call to 'foo(&u)'}}
413*ac857f9bSTimm Baeder     int y;
414*ac857f9bSTimm Baeder   };
415*ac857f9bSTimm Baeder 
416*ac857f9bSTimm Baeder   constexpr A foo(U *up) {
417*ac857f9bSTimm Baeder     return {up->y}; // both-note {{read of member 'y' of union}}
418*ac857f9bSTimm Baeder   }
419*ac857f9bSTimm Baeder 
420*ac857f9bSTimm Baeder   constinit U u = {}; // both-error {{constant init}} \
421*ac857f9bSTimm Baeder                       // both-note {{constinit}}
422*ac857f9bSTimm Baeder }
423*ac857f9bSTimm Baeder 
424a07aba5dSTimm Baeder #endif
425