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