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