blob: 73f81cb1fc1d2774360638853890cac7640eae6e [file] [log] [blame]
Eric Fiselier341e8252016-09-02 18:53:31 +00001// 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();
11
12struct PODType {
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) {}
24 int value;
25};
26#endif
27
28struct NonLit {
29#if __cplusplus >= 201402L
30 constexpr NonLit() : value(0) {}
31 constexpr NonLit(int x) : value(x) {}
32#else
33 NonLit() : value(0) {}
34 NonLit(int x) : value(x) {}
35#endif
36 NonLit(void *) : value(-1) {}
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() {}
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 variables with static or thread}}
60 ATTR int x = 42; // expected-error {{only applies to variables with static or thread}}
61 ATTR extern int y;
62}
63struct ATTR class_mem { // expected-error {{only applies to variables with static or thread}}
64 ATTR int x; // expected-error {{only applies to variables with static or thread}}
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_initializer' attribute here}}
85 ATTR static const int &global_init = glvalue_int;
86 ATTR static const int &temp_init = 42;
87}
88
89ATTR const int &temp_ref = 42;
90ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
91// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
92ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}}
93// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
94
95#if __cplusplus >= 201103L
96ATTR const LitType &lit_temp_ref = 42;
97ATTR const int &subobj_ref = LitType{}.value;
98#endif
99
100ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}}
101// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
102
103struct TT1 {
104 ATTR static const int &no_init;
105 ATTR static const int &glvalue_init;
106 ATTR static const int &temp_init;
107 ATTR static const int &subobj_init;
108#if __cplusplus >= 201103L
109 ATTR static thread_local const int &tl_glvalue_init;
110 ATTR static thread_local const int &tl_temp_init; // expected-note {{required by 'require_constant_initializer' attribute here}}
111#endif
112};
113const int &TT1::glvalue_init = glvalue_int;
114const int &TT1::temp_init = 42;
115const int &TT1::subobj_init = PODType().value;
116#if __cplusplus >= 201103L
117thread_local const int &TT1::tl_glvalue_init = glvalue_int;
118thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}}
119#endif
120
121// [basic.start.static]p2.2
122// if an object with static or thread storage duration is initialized by a
123// constructor call, and if the initialization full-expression is a constant
124// initializer for the object;
125
126void test_basic_start_static_2_2() {
127#if __cplusplus < 201103L
128 ATTR static PODType pod;
129#else
130 ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}}
131// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
132#endif
133 ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
134 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
135
136#if __cplusplus >= 201103L
137 constexpr LitType l;
138 ATTR static LitType static_lit = l;
139 ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}}
140 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
141 ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
142 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
143 ATTR thread_local LitType tls = 42;
144#endif
145}
146
147struct TT2 {
148 ATTR static PODType pod_noinit;
149#if __cplusplus >= 201103L
150// expected-note@-2 {{required by 'require_constant_initializer' attribute here}}
151#endif
152 ATTR static PODType pod_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}}
153#if __cplusplus >= 201402L
154 ATTR static constexpr LitType lit = {};
155 ATTR static const NonLit non_lit;
156 ATTR static const NonLit non_lit_list_init;
157 ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}}
158#endif
159};
160PODType TT2::pod_noinit;
161#if __cplusplus >= 201103L
162// expected-error@-2 {{variable does not have a constant initializer}}
163#endif
164PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}}
165#if __cplusplus >= 201402L
166const NonLit TT2::non_lit(42);
167const NonLit TT2::non_lit_list_init = {42};
168const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}}
169#endif
170
171#if __cplusplus >= 201103L
172ATTR LitType lit_ctor;
173ATTR LitType lit_ctor2{};
174ATTR LitType lit_ctor3 = {};
175ATTR __thread LitType lit_ctor_tl = {};
176
177#if __cplusplus >= 201402L
178ATTR NonLit nl_ctor;
179ATTR NonLit nl_ctor2{};
180ATTR NonLit nl_ctor3 = {};
181ATTR thread_local NonLit nl_ctor_tl = {};
182ATTR StoresNonLit snl;
183#else
184ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}}
185// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
186ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}}
187// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
188ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}}
189// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
190ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}}
191// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
192ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}}
193// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
194#endif
195
196// Non-literal types cannot appear in the initializer of a non-literal type.
197ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}}
198// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
199ATTR int lit_in_init = LitType{42}.value;
200#endif
201
202// [basic.start.static]p2.3
203// if an object with static or thread storage duration is not initialized by a
204// constructor call and if either the object is value-initialized or every
205// full-expression that appears in its initializer is a constant expression.
206void test_basic_start_static_2_3() {
207 ATTR static int static_local = 42;
208 ATTR static int static_local2; // zero-initialization takes place
209#if __cplusplus >= 201103L
210 ATTR thread_local int tl_local = 42;
211#endif
212}
213
214ATTR int no_init; // zero initialization takes place
215ATTR int arg_init = 42;
216ATTR PODType pod_init = {};
217ATTR PODType pod_missing_init = {42 /* should have second arg */};
218ATTR PODType pod_full_init = {1, 2};
219ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
220// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
221
222#if __cplusplus >= 201103L
223ATTR int val_init{};
224ATTR int brace_init = {};
225#endif
226
227ATTR __thread int tl_init = 0;
228typedef const char *StrType;
229
230#if __cplusplus >= 201103L
231
232// Test that the validity of the selected constructor is checked, not just the
233// initializer
234struct NotC {
235 constexpr NotC(void *) {}
236 NotC(int) {}
237};
238template <class T>
239struct TestCtor {
240 constexpr TestCtor(int x) : value(x) {}
241 T value;
242};
243ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant initializer}}
244// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
245#endif
246
247// Test various array types
248ATTR const char *foo[] = {"abc", "def"};
249ATTR PODType bar[] = {{}, {123, 456}};
250
251#elif defined(TEST_TWO) // Test for duplicate warnings
252struct NotC {
253 constexpr NotC(void *) {}
254 NotC(int) {} // expected-note 2 {{declared here}}
255};
256template <class T>
257struct TestCtor {
258 constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}}
259 T value;
260};
261
262ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}}
263// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
264ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}}
265// expected-warning@-1 {{declaration requires a global destructor}}
266// expected-note@-2 {{required by 'require_constant_initializer' attribute here}}
267LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}}
268NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}}
269constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}}
270// expected-note@-1 {{in call to 'TestCtor(42)'}}
271ATTR constexpr TestCtor<NotC> inval_constexpr2(42); // expected-error {{must be initialized by a constant expression}}
272// expected-note@-1 {{in call to 'TestCtor(42)'}}
273
274#elif defined(TEST_THREE)
275#if defined(__cplusplus)
276#error This test requires C
277#endif
278// Test that using the attribute in C results in a diagnostic
279ATTR int x = 0; // expected-warning {{attribute ignored}}
280#else
281#error No test case specified
282#endif // defined(TEST_N)