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();
11 
12 struct PODType {
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) {}
24   int value;
25 };
26 #endif
27 
28 struct 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 
41 struct 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.
59 void 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 }
63 struct 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
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_initializer' attribute here}}
85   ATTR static const int &global_init = glvalue_int;
86   ATTR static const int &temp_init = 42;
87 }
88 
89 ATTR const int &temp_ref = 42;
90 ATTR 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}}
92 ATTR 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
96 ATTR const LitType &lit_temp_ref = 42;
97 ATTR const int &subobj_ref = LitType{}.value;
98 #endif
99 
100 ATTR 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 
103 struct 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 };
113 const int &TT1::glvalue_init = glvalue_int;
114 const int &TT1::temp_init = 42;
115 const int &TT1::subobj_init = PODType().value;
116 #if __cplusplus >= 201103L
117 thread_local const int &TT1::tl_glvalue_init = glvalue_int;
118 thread_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 
126 void 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 
147 struct 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 };
160 PODType TT2::pod_noinit;
161 #if __cplusplus >= 201103L
162 // expected-error@-2 {{variable does not have a constant initializer}}
163 #endif
164 PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}}
165 #if __cplusplus >= 201402L
166 const NonLit TT2::non_lit(42);
167 const NonLit TT2::non_lit_list_init = {42};
168 const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}}
169 #endif
170 
171 #if __cplusplus >= 201103L
172 ATTR LitType lit_ctor;
173 ATTR LitType lit_ctor2{};
174 ATTR LitType lit_ctor3 = {};
175 ATTR __thread LitType lit_ctor_tl = {};
176 
177 #if __cplusplus >= 201402L
178 ATTR NonLit nl_ctor;
179 ATTR NonLit nl_ctor2{};
180 ATTR NonLit nl_ctor3 = {};
181 ATTR thread_local NonLit nl_ctor_tl = {};
182 ATTR StoresNonLit snl;
183 #else
184 ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}}
185 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
186 ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}}
187 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
188 ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}}
189 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
190 ATTR 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}}
192 ATTR 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.
197 ATTR 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}}
199 ATTR 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.
206 void 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 
214 ATTR int no_init; // zero initialization takes place
215 ATTR int arg_init = 42;
216 ATTR PODType pod_init = {};
217 ATTR PODType pod_missing_init = {42 /* should have second arg */};
218 ATTR PODType pod_full_init = {1, 2};
219 ATTR 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
223 ATTR int val_init{};
224 ATTR int brace_init = {};
225 #endif
226 
227 ATTR __thread int tl_init = 0;
228 typedef 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
234 struct NotC {
235   constexpr NotC(void *) {}
236   NotC(int) {}
237 };
238 template <class T>
239 struct TestCtor {
240   constexpr TestCtor(int x) : value(x) {}
241   T value;
242 };
243 ATTR 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
248 ATTR const char *foo[] = {"abc", "def"};
249 ATTR PODType bar[] = {{}, {123, 456}};
250 
251 #elif defined(TEST_TWO) // Test for duplicate warnings
252 struct NotC {
253   constexpr NotC(void *) {}
254   NotC(int) {} // expected-note 2 {{declared here}}
255 };
256 template <class T>
257 struct TestCtor {
258   constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}}
259   T value;
260 };
261 
262 ATTR 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}}
264 ATTR 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}}
267 LitType const_init_lit(nullptr);              // expected-warning {{declaration requires a global constructor}}
268 NonLit const_init{42};                        // expected-warning {{declaration requires a global destructor}}
269 constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}}
270 // expected-note@-1 {{in call to 'TestCtor(42)'}}
271 ATTR 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
279 ATTR int x = 0; // expected-warning {{attribute ignored}}
280 #else
281 #error No test case specified
282 #endif // defined(TEST_N)
283