mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-24 22:08:57 -04:00

This also clarifies some terminology used by the diagnostic (methods -> Objective-C methods, fields -> non-static data members, etc). Many of the tests needed to be updated in multiple places for the diagnostic wording tweaks. The first instance of the diagnostic for that attribute is fully specified and subsequent instances cut off the complete list (to make it easier if additional subjects are added in the future for the attribute). llvm-svn: 319002
337 lines
14 KiB
C++
337 lines
14 KiB
C++
// 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}};
|
|
|
|
#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)
|