1 | // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++03 %s |
2 | // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++11 %s |
3 | // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++14 %s |
4 | // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_TWO \ |
5 | // RUN: -Wglobal-constructors -std=c++14 %s |
6 | // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_THREE -xc %s |
7 | |
8 | #define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}} |
9 | |
10 | int ReturnInt(); // expected-note 0+ {{declared here}} |
11 | |
12 | struct PODType { // expected-note 0+ {{declared here}} |
13 | int value; |
14 | int value2; |
15 | }; |
16 | |
17 | #if defined(__cplusplus) |
18 | |
19 | #if __cplusplus >= 201103L |
20 | struct LitType { |
21 | constexpr LitType() : value(0) {} |
22 | constexpr LitType(int x) : value(x) {} |
23 | LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}} |
24 | int value; |
25 | }; |
26 | #endif |
27 | |
28 | struct NonLit { // expected-note 0+ {{declared here}} |
29 | #if __cplusplus >= 201402L |
30 | constexpr NonLit() : value(0) {} |
31 | constexpr NonLit(int x) : value(x) {} |
32 | #else |
33 | NonLit() : value(0) {} // expected-note 0+ {{declared here}} |
34 | NonLit(int x) : value(x) {} |
35 | #endif |
36 | NonLit(void *) : value(-1) {} // expected-note 0+ {{declared here}} |
37 | ~NonLit() {} |
38 | int value; |
39 | }; |
40 | |
41 | struct StoresNonLit { |
42 | #if __cplusplus >= 201402L |
43 | constexpr StoresNonLit() : obj() {} |
44 | constexpr StoresNonLit(int x) : obj(x) {} |
45 | #else |
46 | StoresNonLit() : obj() {} // expected-note 0+ {{declared here}} |
47 | StoresNonLit(int x) : obj(x) {} |
48 | #endif |
49 | StoresNonLit(void *p) : obj(p) {} |
50 | NonLit obj; |
51 | }; |
52 | |
53 | #endif // __cplusplus |
54 | |
55 | |
56 | #if defined(TEST_ONE) // Test semantics of attribute |
57 | |
58 | // Test diagnostics when attribute is applied to non-static declarations. |
59 | void test_func_local(ATTR int param) { // expected-error {{only applies to global variables}} |
60 | ATTR int x = 42; // expected-error {{only applies to}} |
61 | ATTR extern int y; |
62 | } |
63 | struct ATTR class_mem { // expected-error {{only applies to}} |
64 | ATTR int x; // expected-error {{only applies to}} |
65 | }; |
66 | |
67 | // [basic.start.static]p2.1 |
68 | // if each full-expression (including implicit conversions) that appears in |
69 | // the initializer of a reference with static or thread storage duration is |
70 | // a constant expression (5.20) and the reference is bound to a glvalue |
71 | // designating an object with static storage duration, to a temporary object |
72 | // (see 12.2) or subobject thereof, or to a function; |
73 | |
74 | // Test binding to a static glvalue |
75 | const int glvalue_int = 42; |
76 | const int glvalue_int2 = ReturnInt(); |
77 | ATTR const int &glvalue_ref ATTR = glvalue_int; |
78 | ATTR const int &glvalue_ref2 ATTR = glvalue_int2; |
79 | ATTR __thread const int &glvalue_ref_tl = glvalue_int; |
80 | |
81 | void test_basic_start_static_2_1() { |
82 | const int non_global = 42; |
83 | ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}} |
84 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
85 | #if __cplusplus >= 201103L |
86 | // expected-note@-3 {{reference to 'non_global' is not a constant expression}} |
87 | // expected-note@-5 {{declared here}} |
88 | #else |
89 | // expected-note@-6 {{subexpression not valid in a constant expression}} |
90 | #endif |
91 | ATTR static const int &global_init = glvalue_int; |
92 | ATTR static const int &temp_init = 42; |
93 | } |
94 | |
95 | ATTR const int &temp_ref = 42; |
96 | ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} |
97 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
98 | #if __cplusplus >= 201103L |
99 | // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} |
100 | #else |
101 | // expected-note@-5 {{subexpression not valid in a constant expression}} |
102 | #endif |
103 | ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}} |
104 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
105 | #if __cplusplus >= 201103L |
106 | // expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}} |
107 | #else |
108 | // expected-note@-5 {{subexpression not valid in a constant expression}} |
109 | #endif |
110 | |
111 | #if __cplusplus >= 201103L |
112 | ATTR const LitType &lit_temp_ref = 42; |
113 | ATTR const int &subobj_ref = LitType{}.value; |
114 | #endif |
115 | |
116 | ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}} |
117 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
118 | #if __cplusplus >= 201103L |
119 | // expected-note-re@-3 {{non-literal type '{{.*}}' cannot be used in a constant expression}} |
120 | #else |
121 | // expected-note@-5 {{subexpression not valid in a constant expression}} |
122 | #endif |
123 | |
124 | struct TT1 { |
125 | ATTR static const int &no_init; |
126 | ATTR static const int &glvalue_init; |
127 | ATTR static const int &temp_init; |
128 | ATTR static const int &subobj_init; |
129 | #if __cplusplus >= 201103L |
130 | ATTR static thread_local const int &tl_glvalue_init; |
131 | ATTR static thread_local const int &tl_temp_init; // expected-note {{required by 'require_constant_initialization' attribute here}} |
132 | #endif |
133 | }; |
134 | const int &TT1::glvalue_init = glvalue_int; |
135 | const int &TT1::temp_init = 42; |
136 | const int &TT1::subobj_init = PODType().value; |
137 | #if __cplusplus >= 201103L |
138 | thread_local const int &TT1::tl_glvalue_init = glvalue_int; |
139 | thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}} |
140 | // expected-note@-1 {{reference to temporary is not a constant expression}} |
141 | // expected-note@-2 {{temporary created here}} |
142 | #endif |
143 | |
144 | // [basic.start.static]p2.2 |
145 | // if an object with static or thread storage duration is initialized by a |
146 | // constructor call, and if the initialization full-expression is a constant |
147 | // initializer for the object; |
148 | |
149 | void test_basic_start_static_2_2() { |
150 | #if __cplusplus < 201103L |
151 | ATTR static PODType pod; |
152 | #else |
153 | ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}} |
154 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
155 | // expected-note@-2 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}} |
156 | #endif |
157 | ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}} |
158 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
159 | #if __cplusplus >= 201103L |
160 | // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} |
161 | #else |
162 | // expected-note@-5 {{subexpression not valid in a constant expression}} |
163 | #endif |
164 | |
165 | #if __cplusplus >= 201103L |
166 | constexpr LitType l; |
167 | ATTR static LitType static_lit = l; |
168 | ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}} |
169 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
170 | // expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}} |
171 | ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} |
172 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
173 | // expected-note@-2 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} |
174 | ATTR thread_local LitType tls = 42; |
175 | #endif |
176 | } |
177 | |
178 | struct TT2 { |
179 | ATTR static PODType pod_noinit; |
180 | #if __cplusplus >= 201103L |
181 | // expected-note@-2 {{required by 'require_constant_initialization' attribute here}} |
182 | #endif |
183 | ATTR static PODType pod_copy_init; // expected-note {{required by 'require_constant_initialization' attribute here}} |
184 | #if __cplusplus >= 201402L |
185 | ATTR static constexpr LitType lit = {}; |
186 | ATTR static const NonLit non_lit; |
187 | ATTR static const NonLit non_lit_list_init; |
188 | ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initialization' attribute here}} |
189 | #endif |
190 | }; |
191 | PODType TT2::pod_noinit; // expected-note 0+ {{declared here}} |
192 | #if __cplusplus >= 201103L |
193 | // expected-error@-2 {{variable does not have a constant initializer}} |
194 | // expected-note@-3 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}} |
195 | #endif |
196 | PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}} |
197 | #if __cplusplus >= 201103L |
198 | // expected-note@-2 {{read of non-constexpr variable 'pod_noinit' is not allowed in a constant expression}} |
199 | // expected-note@-3 {{in call to 'PODType(pod_noinit)'}} |
200 | #else |
201 | // expected-note@-5 {{subexpression not valid in a constant expression}} |
202 | #endif |
203 | #if __cplusplus >= 201402L |
204 | const NonLit TT2::non_lit(42); |
205 | const NonLit TT2::non_lit_list_init = {42}; |
206 | const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}} |
207 | // expected-note@-1 {{subexpression not valid in a constant expression}} |
208 | #endif |
209 | |
210 | #if __cplusplus >= 201103L |
211 | ATTR LitType lit_ctor; |
212 | ATTR LitType lit_ctor2{}; |
213 | ATTR LitType lit_ctor3 = {}; |
214 | ATTR __thread LitType lit_ctor_tl = {}; |
215 | |
216 | #if __cplusplus >= 201402L |
217 | ATTR NonLit nl_ctor; |
218 | ATTR NonLit nl_ctor2{}; |
219 | ATTR NonLit nl_ctor3 = {}; |
220 | ATTR thread_local NonLit nl_ctor_tl = {}; |
221 | ATTR StoresNonLit snl; |
222 | #else |
223 | ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}} |
224 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
225 | // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} |
226 | ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}} |
227 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
228 | // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} |
229 | ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}} |
230 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
231 | // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} |
232 | ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}} |
233 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
234 | // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} |
235 | ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}} |
236 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
237 | // expected-note@-2 {{non-constexpr constructor 'StoresNonLit' cannot be used in a constant expression}} |
238 | #endif |
239 | |
240 | // Non-literal types cannot appear in the initializer of a non-literal type. |
241 | ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}} |
242 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
243 | // expected-note@-2 {{non-literal type 'NonLit' cannot be used in a constant expression}} |
244 | ATTR int lit_in_init = LitType{42}.value; |
245 | #endif |
246 | |
247 | // [basic.start.static]p2.3 |
248 | // if an object with static or thread storage duration is not initialized by a |
249 | // constructor call and if either the object is value-initialized or every |
250 | // full-expression that appears in its initializer is a constant expression. |
251 | void test_basic_start_static_2_3() { |
252 | ATTR static int static_local = 42; |
253 | ATTR static int static_local2; // zero-initialization takes place |
254 | #if __cplusplus >= 201103L |
255 | ATTR thread_local int tl_local = 42; |
256 | #endif |
257 | } |
258 | |
259 | ATTR int no_init; // zero initialization takes place |
260 | ATTR int arg_init = 42; |
261 | ATTR PODType pod_init = {}; |
262 | ATTR PODType pod_missing_init = {42 /* should have second arg */}; |
263 | ATTR PODType pod_full_init = {1, 2}; |
264 | ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}} |
265 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
266 | #if __cplusplus >= 201103L |
267 | // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} |
268 | #else |
269 | // expected-note@-5 {{subexpression not valid in a constant expression}} |
270 | #endif |
271 | |
272 | #if __cplusplus >= 201103L |
273 | ATTR int val_init{}; |
274 | ATTR int brace_init = {}; |
275 | #endif |
276 | |
277 | ATTR __thread int tl_init = 0; |
278 | typedef const char *StrType; |
279 | |
280 | #if __cplusplus >= 201103L |
281 | |
282 | // Test that the validity of the selected constructor is checked, not just the |
283 | // initializer |
284 | struct NotC { |
285 | constexpr NotC(void *) {} |
286 | NotC(int) {} // expected-note 0+ {{declared here}} |
287 | }; |
288 | template <class T> |
289 | struct TestCtor { |
290 | constexpr TestCtor(int x) : value(x) {} |
291 | // expected-note@-1 {{non-constexpr constructor 'NotC' cannot be used in a constant expression}} |
292 | T value; |
293 | }; |
294 | ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant initializer}} |
295 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
296 | // expected-note@-2 {{in call to 'TestCtor(42)'}} |
297 | #endif |
298 | |
299 | // Test various array types |
300 | ATTR const char *foo[] = {"abc", "def"}; |
301 | ATTR PODType bar[] = {{}, {123, 456}}; |
302 | |
303 | #elif defined(TEST_TWO) // Test for duplicate warnings |
304 | struct NotC { |
305 | constexpr NotC(void *) {} |
306 | NotC(int) {} // expected-note 2 {{declared here}} |
307 | }; |
308 | template <class T> |
309 | struct TestCtor { |
310 | constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}} |
311 | T value; |
312 | }; |
313 | |
314 | ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}} |
315 | // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} |
316 | // expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}} |
317 | ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}} |
318 | // expected-warning@-1 {{declaration requires a global destructor}} |
319 | // expected-note@-2 {{required by 'require_constant_initialization' attribute here}} |
320 | // expected-note@-3 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} |
321 | LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}} |
322 | NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}} |
323 | constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}} |
324 | // expected-note@-1 {{in call to 'TestCtor(42)'}} |
325 | ATTR constexpr TestCtor<NotC> inval_constexpr2(42); // expected-error {{must be initialized by a constant expression}} |
326 | // expected-note@-1 {{in call to 'TestCtor(42)'}} |
327 | |
328 | #elif defined(TEST_THREE) |
329 | #if defined(__cplusplus) |
330 | #error This test requires C |
331 | #endif |
332 | // Test that using the attribute in C results in a diagnostic |
333 | ATTR int x = 0; // expected-warning {{attribute ignored}} |
334 | #else |
335 | #error No test case specified |
336 | #endif // defined(TEST_N) |
337 | |