Clang Project

clang_source_code/test/SemaCXX/attr-require-constant-initialization.cpp
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
10int ReturnInt(); // expected-note 0+ {{declared here}}
11
12struct PODType { // expected-note 0+ {{declared here}}
13  int value;
14  int value2;
15};
16
17#if defined(__cplusplus)
18
19#if __cplusplus >= 201103L
20struct 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
28struct 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
41struct 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.
59void 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}
63struct 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
75const int glvalue_int = 42;
76const int glvalue_int2 = ReturnInt();
77ATTR const int &glvalue_ref ATTR = glvalue_int;
78ATTR const int &glvalue_ref2 ATTR = glvalue_int2;
79ATTR __thread const int &glvalue_ref_tl = glvalue_int;
80
81void 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
95ATTR const int &temp_ref = 42;
96ATTR 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
103ATTR 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
112ATTR const LitType &lit_temp_ref = 42;
113ATTR const int &subobj_ref = LitType{}.value;
114#endif
115
116ATTR 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
124struct 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};
134const int &TT1::glvalue_init = glvalue_int;
135const int &TT1::temp_init = 42;
136const int &TT1::subobj_init = PODType().value;
137#if __cplusplus >= 201103L
138thread_local const int &TT1::tl_glvalue_init = glvalue_int;
139thread_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
149void 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
178struct 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};
191PODType 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
196PODType 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
204const NonLit TT2::non_lit(42);
205const NonLit TT2::non_lit_list_init = {42};
206const 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
211ATTR LitType lit_ctor;
212ATTR LitType lit_ctor2{};
213ATTR LitType lit_ctor3 = {};
214ATTR __thread LitType lit_ctor_tl = {};
215
216#if __cplusplus >= 201402L
217ATTR NonLit nl_ctor;
218ATTR NonLit nl_ctor2{};
219ATTR NonLit nl_ctor3 = {};
220ATTR thread_local NonLit nl_ctor_tl = {};
221ATTR StoresNonLit snl;
222#else
223ATTR 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}}
226ATTR 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}}
229ATTR 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}}
232ATTR 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}}
235ATTR 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.
241ATTR 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}}
244ATTR 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.
251void 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
259ATTR int no_init; // zero initialization takes place
260ATTR int arg_init = 42;
261ATTR PODType pod_init = {};
262ATTR PODType pod_missing_init = {42 /* should have second arg */};
263ATTR PODType pod_full_init = {1, 2};
264ATTR 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
273ATTR int val_init{};
274ATTR int brace_init = {};
275#endif
276
277ATTR __thread int tl_init = 0;
278typedef 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
284struct NotC {
285  constexpr NotC(void *) {}
286  NotC(int) {} // expected-note 0+ {{declared here}}
287};
288template <class T>
289struct 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};
294ATTR 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
300ATTR const char *foo[] = {"abc", "def"};
301ATTR PODType bar[] = {{}, {123, 456}};
302
303#elif defined(TEST_TWO) // Test for duplicate warnings
304struct NotC {
305  constexpr NotC(void *) {}
306  NotC(int) {} // expected-note 2 {{declared here}}
307};
308template <class T>
309struct TestCtor {
310  constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}}
311  T value;
312};
313
314ATTR 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}}
317ATTR 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}}
321LitType const_init_lit(nullptr);              // expected-warning {{declaration requires a global constructor}}
322NonLit const_init{42};                        // expected-warning {{declaration requires a global destructor}}
323constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}}
324// expected-note@-1 {{in call to 'TestCtor(42)'}}
325ATTR 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
333ATTR int x = 0; // expected-warning {{attribute ignored}}
334#else
335#error No test case specified
336#endif // defined(TEST_N)
337