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 5 6 union U { 7 int a; 8 int b; 9 }; 10 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; 18 }; 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'}} 23 24 25 26 union A { 27 int a; 28 double d; 29 }; 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'}} 35 36 37 namespace Empty { 38 union E {}; 39 constexpr E e{}; 40 } 41 42 namespace SimpleStore { 43 union A { 44 int a; 45 int b; 46 }; 47 constexpr int foo() { 48 A a{.b = 4}; 49 a.b = 10; 50 return a.b; 51 } 52 static_assert(foo() == 10, ""); 53 54 constexpr int empty() { 55 A a{}; /// Just test that this works. 56 return 10; 57 } 58 static_assert(empty() == 10, ""); 59 } 60 61 namespace ZeroInit { 62 struct S { int m; }; 63 union Z { 64 float f; 65 }; 66 67 constexpr Z z{}; 68 static_assert(z.f == 0.0, ""); 69 } 70 71 namespace DefaultInit { 72 union U1 { 73 constexpr U1() {} 74 int a, b = 42; 75 }; 76 77 constexpr U1 u1; /// OK. 78 79 constexpr int foo() { 80 U1 u; 81 return u.a; // both-note {{read of member 'a' of union with active member 'b'}} 82 } 83 static_assert(foo() == 42); // both-error {{not an integral constant expression}} \ 84 // both-note {{in call to}} 85 } 86 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; 94 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'}} 98 } 99 static_assert(foo() == 20); // both-error {{not an integral constant expression}} \ 100 // both-note {{in call to}} 101 102 constexpr int foo2() { 103 union { 104 int a; 105 int b; 106 } Z; 107 108 Z.a = 10; 109 Z.b = 20; 110 return Z.b; 111 } 112 static_assert(foo2() == 20); 113 114 115 constexpr int foo3() { 116 union { 117 struct { 118 float x,y; 119 } a; 120 int b; 121 } Z; 122 123 Z.a.y = 10; 124 125 return Z.a.x; // both-note {{read of uninitialized object}} 126 } 127 static_assert(foo3() == 10); // both-error {{not an integral constant expression}} \ 128 // both-note {{in call to}} 129 130 constexpr int foo4() { 131 union { 132 struct { 133 float x,y; 134 } a; 135 int b; 136 } Z; 137 138 Z.a.x = 100; 139 Z.a.y = 10; 140 141 return Z.a.x; 142 } 143 static_assert(foo4() == 100); 144 } 145 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) {} 151 }; 152 static_assert(C().a == 1, ""); 153 } 154 155 namespace UnionDtor { 156 157 union U { 158 int *I; 159 constexpr U(int *I) : I(I) {} 160 constexpr ~U() { 161 *I = 10; 162 } 163 }; 164 165 constexpr int foo() { 166 int a = 100; 167 { 168 U u(&a); 169 } 170 return a; 171 } 172 static_assert(foo() == 10); 173 } 174 175 namespace UnionMemberDtor { 176 class UM { 177 public: 178 int &I; 179 constexpr UM(int &I) : I(I) {} 180 constexpr ~UM() { I = 200; } 181 }; 182 183 union U { 184 UM um; 185 constexpr U(int &I) : um(I) {} 186 constexpr ~U() { 187 } 188 }; 189 190 constexpr int foo() { 191 int a = 100; 192 { 193 U u(a); 194 } 195 196 return a; 197 } 198 static_assert(foo() == 100); 199 } 200 201 namespace Nested { 202 union U { 203 int a; 204 int b; 205 }; 206 207 union U2 { 208 U u; 209 U u2; 210 int x; 211 int y; 212 }; 213 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}} 218 219 return 1; 220 } 221 static_assert(foo() == 1); // both-error {{not an integral constant expression}} \ 222 // both-note {{in call to}} 223 224 constexpr int foo2() { 225 U2 u; 226 u.u.a = 10; 227 return u.u.a; 228 } 229 static_assert(foo2() == 10); 230 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}} 235 236 return 1; 237 } 238 static_assert(foo3() == 1); // both-error {{not an integral constant expression}} \ 239 // both-note {{in call to}} 240 241 constexpr int foo4() { // both-error {{constexpr function never produces a constant expression}} 242 U2 u; 243 244 u.x = 10; 245 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}} 247 } 248 static_assert(foo4() == 1); // both-error {{not an integral constant expression}} \ 249 // both-note {{in call to}} 250 251 } 252 253 254 namespace Zeroing { 255 struct non_trivial_constructor { 256 constexpr non_trivial_constructor() : x(100) {} 257 int x; 258 }; 259 union U2 { 260 int a{1000}; 261 non_trivial_constructor b; 262 }; 263 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'}} 266 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'}} 271 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'}} 276 277 278 struct F {int x; int y; }; 279 union { F a; int b; } constexpr u3{}; 280 static_assert(u3.a.x == 0, ""); 281 282 union U4 { F a; int b; } constexpr u4 = U4(); 283 static_assert(u4.a.x == 0, ""); 284 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'}} 290 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'}} 296 297 union UnionWithUnnamedBitfield { 298 int : 3; 299 int n; 300 }; 301 static_assert(UnionWithUnnamedBitfield().n == 0, ""); 302 static_assert(UnionWithUnnamedBitfield{}.n == 0, ""); 303 static_assert(UnionWithUnnamedBitfield{1}.n == 1, ""); 304 } 305 306 namespace IndirectField { 307 struct S { 308 struct { 309 union { 310 struct { 311 int a; 312 int b; 313 }; 314 int c; 315 }; 316 int d; 317 }; 318 union { 319 int e; 320 int f; 321 }; 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) {} 324 }; 325 326 constexpr S s1(1,2,3,4); 327 constexpr S s2(5, 6, 7); 328 329 static_assert(s1.a == 1, ""); 330 static_assert(s1.b == 2, ""); 331 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}} 336 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, ""); 343 } 344 345 namespace CopyCtor { 346 union U { 347 int a; 348 int b; 349 }; 350 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'}} 356 } 357 358 namespace UnionInBase { 359 struct Base { 360 int y; // both-note {{subobject declared here}} 361 }; 362 struct A : Base { 363 int x; 364 int arr[3]; 365 union { int p, q; }; 366 }; 367 union B { 368 A a; 369 int b; 370 }; 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'}} 375 376 } 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}} 384 } 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; 393 } 394 395 constexpr B return_uninit() { 396 B b = {.b = 1}; 397 b.a.x = 2; 398 return b; 399 } 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); 403 } 404 405 /// FIXME: Our diagnostic here is a little off. 406 namespace One { 407 struct A { long x; }; 408 409 union U; 410 constexpr A foo(U *up); 411 union U { 412 A a = foo(this); // both-note {{in call to 'foo(&u)'}} 413 int y; 414 }; 415 416 constexpr A foo(U *up) { 417 return {up->y}; // both-note {{read of member 'y' of union}} 418 } 419 420 constinit U u = {}; // both-error {{constant init}} \ 421 // both-note {{constinit}} 422 } 423 424 #endif 425