123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- // 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;
- 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@-2 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}}
- #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; // expected-note {{required by 'require_constant_initialization' attribute here}}
- #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@-3 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}}
- #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};
- const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}}
- // expected-note@-1 {{subexpression not valid in a constant expression}}
- #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)
|