Skip to content

Commit dcf92a2

Browse files
authored
[clang][NFC] Add examples from [dcl.init.aggr] to C++ conformance tests (#91435)
This patch adds examples from 2024-04-22 draft of [[dcl.init.aggr]](http://eel.is/c++draft/dcl.init.aggr) to C++ conformance tests. Testing is done via constant evaluation and static asserts. As far as I can see, the rest of the conformance suite is typically testing the latest language mode at the time of writing (with a notable exception of defect report tests), so I'm also testing in the latest language mode.
1 parent a51d92a commit dcf92a2

File tree

1 file changed

+294
-0
lines changed

1 file changed

+294
-0
lines changed

clang/test/CXX/dcl/dcl.init/aggr.cpp

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
// RUN: %clang_cc1 -std=c++2c -verify %s
2+
3+
namespace ex1 {
4+
struct C {
5+
union {
6+
int a;
7+
const char* p;
8+
};
9+
int x;
10+
};
11+
12+
constexpr C c = { .a = 1, .x = 3 };
13+
static_assert(c.a == 1);
14+
static_assert(c.x == 3);
15+
16+
static constexpr C c2 = { .a = 1.0, .x = 3 };
17+
// expected-error@-1 {{type 'double' cannot be narrowed to 'int' in initializer list}}
18+
// expected-note@-2 {{insert an explicit cast to silence this issue}}
19+
} // namespace ex1
20+
21+
namespace ex2 {
22+
struct A {
23+
int x;
24+
struct B {
25+
int i;
26+
int j;
27+
} b;
28+
};
29+
30+
constexpr A a = { 1, { 2, 3 } };
31+
static_assert(a.x == 1);
32+
static_assert(a.b.i == 2);
33+
static_assert(a.b.j == 3);
34+
35+
struct base1 { int b1, b2 = 42; };
36+
struct base2 {
37+
constexpr base2() {
38+
b3 = 43;
39+
}
40+
int b3;
41+
};
42+
struct derived : base1, base2 {
43+
int d;
44+
};
45+
46+
constexpr derived d1{{1, 2}, {}, 4};
47+
static_assert(d1.b1 == 1);
48+
static_assert(d1.b2 == 2);
49+
static_assert(d1.b3 == 43);
50+
static_assert(d1.d == 4);
51+
52+
constexpr derived d2{{}, {}, 4};
53+
static_assert(d2.b1 == 0);
54+
static_assert(d2.b2 == 42);
55+
static_assert(d2.b3 == 43);
56+
static_assert(d2.d == 4);
57+
} // namespace ex2
58+
59+
namespace ex3 {
60+
struct S {
61+
int a;
62+
const char* b;
63+
int c;
64+
int d = b[a];
65+
};
66+
67+
constexpr S ss = { 1, "asdf" };
68+
static_assert(ss.a == 1);
69+
static_assert(__builtin_strcmp(ss.b, "asdf") == 0);
70+
static_assert(ss.c == int{});
71+
static_assert(ss.d == ss.b[ss.a]);
72+
73+
struct string {
74+
int d = 43;
75+
};
76+
77+
struct A {
78+
string a;
79+
int b = 42;
80+
int c = -1;
81+
};
82+
83+
constexpr A a{.c = 21};
84+
static_assert(a.a.d == string{}.d);
85+
static_assert(a.b == 42);
86+
static_assert(a.c == 21);
87+
} // namespace ex3
88+
89+
namespace ex4 {
90+
int x[] = { 1, 3, 5 };
91+
static_assert(sizeof(x) / sizeof(int) == 3);
92+
} // namespace ex4
93+
94+
namespace ex5 {
95+
struct X { int i, j, k; };
96+
97+
constexpr X a[] = { 1, 2, 3, 4, 5, 6 };
98+
constexpr X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };
99+
static_assert(sizeof(a) == sizeof(b));
100+
static_assert(a[0].i == b[0].i);
101+
static_assert(a[0].j == b[0].j);
102+
static_assert(a[0].k == b[0].k);
103+
static_assert(a[1].i == b[1].i);
104+
static_assert(a[1].j == b[1].j);
105+
static_assert(a[1].k == b[1].k);
106+
} // namespace ex5
107+
108+
namespace ex6 {
109+
struct S {
110+
int y[] = { 0 };
111+
// expected-error@-1 {{array bound cannot be deduced from a default member initializer}}
112+
};
113+
} // namespace ex6
114+
115+
namespace ex7 {
116+
struct A {
117+
int i;
118+
static int s;
119+
int j;
120+
int :17;
121+
int k;
122+
};
123+
124+
constexpr A a = { 1, 2, 3 };
125+
static_assert(a.i == 1);
126+
static_assert(a.j == 2);
127+
static_assert(a.k == 3);
128+
} // namespace ex7
129+
130+
namespace ex8 {
131+
struct A;
132+
extern A a;
133+
struct A {
134+
const A& a1 { A{a,a} };
135+
const A& a2 { A{} };
136+
// expected-error@-1 {{default member initializer for 'a2' needed within definition of enclosing class 'A' outside of member functions}}
137+
// expected-note@-2 {{default member initializer declared here}}
138+
};
139+
A a{a,a};
140+
141+
struct B {
142+
int n = B{}.n;
143+
// expected-error@-1 {{default member initializer for 'n' needed within definition of enclosing class 'B' outside of member functions}}
144+
// expected-note@-2 {{default member initializer declared here}}
145+
};
146+
} // namespace ex8
147+
148+
namespace ex9 {
149+
constexpr int x[2][2] = { 3, 1, 4, 2 };
150+
static_assert(x[0][0] == 3);
151+
static_assert(x[0][1] == 1);
152+
static_assert(x[1][0] == 4);
153+
static_assert(x[1][1] == 2);
154+
155+
constexpr float y[4][3] = {
156+
{ 1 }, { 2 }, { 3 }, { 4 }
157+
};
158+
static_assert(y[0][0] == 1);
159+
static_assert(y[0][1] == 0);
160+
static_assert(y[0][2] == 0);
161+
static_assert(y[1][0] == 2);
162+
static_assert(y[1][1] == 0);
163+
static_assert(y[1][2] == 0);
164+
static_assert(y[2][0] == 3);
165+
static_assert(y[2][1] == 0);
166+
static_assert(y[2][2] == 0);
167+
static_assert(y[3][0] == 4);
168+
static_assert(y[3][1] == 0);
169+
static_assert(y[3][2] == 0);
170+
} // namespace ex9
171+
172+
namespace ex10 {
173+
struct S1 { int a, b; };
174+
struct S2 { S1 s, t; };
175+
176+
constexpr S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 };
177+
constexpr S2 y[2] = {
178+
{
179+
{ 1, 2 },
180+
{ 3, 4 }
181+
},
182+
{
183+
{ 5, 6 },
184+
{ 7, 8 }
185+
}
186+
};
187+
static_assert(x[0].s.a == 1);
188+
static_assert(x[0].s.b == 2);
189+
static_assert(x[0].t.a == 3);
190+
static_assert(x[0].t.b == 4);
191+
static_assert(x[1].s.a == 5);
192+
static_assert(x[1].s.b == 6);
193+
static_assert(x[1].t.a == 7);
194+
static_assert(x[1].t.b == 8);
195+
} // namespace ex10
196+
197+
namespace ex11 {
198+
char cv[4] = { 'a', 's', 'd', 'f', 0 };
199+
// expected-error@-1 {{excess elements in array initializer}}
200+
} // namespace ex11
201+
202+
namespace ex12 {
203+
constexpr float y[4][3] = {
204+
{ 1, 3, 5 },
205+
{ 2, 4, 6 },
206+
{ 3, 5, 7 },
207+
};
208+
static_assert(y[0][0] == 1);
209+
static_assert(y[0][1] == 3);
210+
static_assert(y[0][2] == 5);
211+
static_assert(y[1][0] == 2);
212+
static_assert(y[1][1] == 4);
213+
static_assert(y[1][2] == 6);
214+
static_assert(y[2][0] == 3);
215+
static_assert(y[2][1] == 5);
216+
static_assert(y[2][2] == 7);
217+
static_assert(y[3][0] == 0.0);
218+
static_assert(y[3][1] == 0.0);
219+
static_assert(y[3][2] == 0.0);
220+
221+
constexpr float z[4][3] = {
222+
1, 3, 5, 2, 4, 6, 3, 5, 7
223+
};
224+
static_assert(z[0][0] == 1);
225+
static_assert(z[0][1] == 3);
226+
static_assert(z[0][2] == 5);
227+
static_assert(z[1][0] == 2);
228+
static_assert(z[1][1] == 4);
229+
static_assert(z[1][2] == 6);
230+
static_assert(z[2][0] == 3);
231+
static_assert(z[2][1] == 5);
232+
static_assert(z[2][2] == 7);
233+
static_assert(z[3][0] == 0.0);
234+
static_assert(z[3][1] == 0.0);
235+
static_assert(z[3][2] == 0.0);
236+
} // namespace ex12
237+
238+
namespace ex13 {
239+
struct S { } s;
240+
struct A {
241+
S s1;
242+
int i1;
243+
S s2;
244+
int i2;
245+
S s3;
246+
int i3;
247+
} a = {
248+
{ }, // Required initialization
249+
0,
250+
s, // Required initialization
251+
0
252+
}; // Initialization not required for A​::​s3 because A​::​i3 is also not initialized
253+
} // namespace ex13
254+
255+
namespace ex14 {
256+
struct A {
257+
int i;
258+
constexpr operator int() const { return 42; };
259+
};
260+
struct B {
261+
A a1, a2;
262+
int z;
263+
};
264+
constexpr A a{};
265+
constexpr B b = { 4, a, a };
266+
static_assert(b.a1.i == 4);
267+
static_assert(b.a2.i == a.i);
268+
static_assert(b.z == a.operator int());
269+
} // namespace ex14
270+
271+
namespace ex15 {
272+
union u { // #ex15-u
273+
int a;
274+
const char* b;
275+
};
276+
277+
u a = { 1 };
278+
u b = a;
279+
u c = 1;
280+
// expected-error@-1 {{no viable conversion from 'int' to 'u'}}
281+
// expected-note@#ex15-u {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const u &' for 1st argument}}
282+
// expected-note@#ex15-u {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'u &&' for 1st argument}}
283+
u d = { 0, "asdf" };
284+
// expected-error@-1 {{excess elements in union initializer}}
285+
u e = { "asdf" };
286+
// expected-error@-1 {{cannot initialize a member subobject of type 'int' with an lvalue of type 'const char[5]'}}
287+
u f = { .b = "asdf" };
288+
u g = {
289+
.a = 1, // #ex15-g-a
290+
.b = "asdf"
291+
// expected-error@-1 {{initializer partially overrides prior initialization of this subobject}}
292+
// expected-note@#ex15-g-a {{previous initialization is here}}
293+
};
294+
} // namespace ex15

0 commit comments

Comments
 (0)