From 1c77e0e09f63effae7503c429654161843e1730f Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 1 Jun 2017 18:54:16 +0000 Subject: [PATCH] [SemaCXX] Add diagnostics to require_constant_initialization Summary: This hooks up the detailed diagnostics of why constant initialization was not possible if require_constant_initialization reports an error. I have updated the test to account for the new notes. Reviewed By: EricWF Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D24371 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@304451 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 11 +++ .../attr-require-constant-initialization.cpp | 72 ++++++++++++++++--- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a9adbec4f8..ea1f7526a8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -11116,6 +11116,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { << Init->getSourceRange(); Diag(attr->getLocation(), diag::note_declared_required_constant_init_here) << attr->getRange(); + if (getLangOpts().CPlusPlus11) { + APValue Value; + SmallVector Notes; + Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes); + for (auto &it : Notes) + Diag(it.first, it.second); + } else { + Diag(CacheCulprit->getExprLoc(), + diag::note_invalid_subexpr_in_const_expr) + << CacheCulprit->getSourceRange(); + } } } else if (!var->isConstexpr() && IsGlobal && diff --git a/test/SemaCXX/attr-require-constant-initialization.cpp b/test/SemaCXX/attr-require-constant-initialization.cpp index 3ed51071cd..0df9f2e880 100644 --- a/test/SemaCXX/attr-require-constant-initialization.cpp +++ b/test/SemaCXX/attr-require-constant-initialization.cpp @@ -7,9 +7,9 @@ #define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}} -int ReturnInt(); +int ReturnInt(); // expected-note 0+ {{declared here}} -struct PODType { +struct PODType { // expected-note 0+ {{declared here}} int value; int value2; }; @@ -20,20 +20,20 @@ struct PODType { struct LitType { constexpr LitType() : value(0) {} constexpr LitType(int x) : value(x) {} - LitType(void *) : value(-1) {} + LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}} int value; }; #endif -struct NonLit { +struct NonLit { // expected-note 0+ {{declared here}} #if __cplusplus >= 201402L constexpr NonLit() : value(0) {} constexpr NonLit(int x) : value(x) {} #else - NonLit() : value(0) {} + NonLit() : value(0) {} // expected-note 0+ {{declared here}} NonLit(int x) : value(x) {} #endif - NonLit(void *) : value(-1) {} + NonLit(void *) : value(-1) {} // expected-note 0+ {{declared here}} ~NonLit() {} int value; }; @@ -43,7 +43,7 @@ struct StoresNonLit { constexpr StoresNonLit() : obj() {} constexpr StoresNonLit(int x) : obj(x) {} #else - StoresNonLit() : obj() {} + StoresNonLit() : obj() {} // expected-note 0+ {{declared here}} StoresNonLit(int x) : obj(x) {} #endif StoresNonLit(void *p) : obj(p) {} @@ -82,6 +82,12 @@ 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; } @@ -89,8 +95,18 @@ void test_basic_start_static_2_1() { 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; @@ -99,6 +115,11 @@ ATTR const int &subobj_ref = LitType{}.value; 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; @@ -116,6 +137,8 @@ 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 @@ -129,17 +152,25 @@ void test_basic_start_static_2_2() { #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 } @@ -157,15 +188,23 @@ struct TT2 { ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initialization' attribute here}} #endif }; -PODType TT2::pod_noinit; +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 @@ -183,19 +222,25 @@ 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 @@ -218,6 +263,11 @@ 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{}; @@ -233,15 +283,17 @@ typedef const char *StrType; // initializer struct NotC { constexpr NotC(void *) {} - NotC(int) {} + NotC(int) {} // expected-note 0+ {{declared here}} }; template 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 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 @@ -261,9 +313,11 @@ struct TestCtor { 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 inval_constexpr(42); // expected-error {{must be initialized by a constant expression}} -- 2.40.0