r304451 - [SemaCXX] Add diagnostics to require_constant_initialization

Keno Fischer via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 1 11:54:17 PDT 2017


Author: kfischer
Date: Thu Jun  1 13:54:16 2017
New Revision: 304451

URL: http://llvm.org/viewvc/llvm-project?rev=304451&view=rev
Log:
[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

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=304451&r1=304450&r2=304451&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jun  1 13:54:16 2017
@@ -11116,6 +11116,17 @@ void Sema::CheckCompleteVariableDeclarat
           << Init->getSourceRange();
         Diag(attr->getLocation(), diag::note_declared_required_constant_init_here)
           << attr->getRange();
+        if (getLangOpts().CPlusPlus11) {
+          APValue Value;
+          SmallVector<PartialDiagnosticAt, 8> 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 &&

Modified: cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp?rev=304451&r1=304450&r2=304451&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp Thu Jun  1 13:54:16 2017
@@ -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+#if __cplusplus >= 201103L
+  // expected-note at -3 {{reference to 'non_global' is not a constant expression}}
+  // expected-note at -5 {{declared here}}
+#else
+  // expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note at -3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+#else
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note at -3 {{non-literal type 'const NonLit' cannot be used in a constant expression}}
+#else
+// expected-note at -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{}.v
 
 ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}}
 // expected-note at -1 {{required by 'require_constant_initialization' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note-re at -3 {{non-literal type '{{.*}}' cannot be used in a constant expression}}
+#else
+// expected-note at -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().
 #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 at -1 {{reference to temporary is not a constant expression}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note at -3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+#else
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+  // expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+  // expected-note at -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 at -2 {{variable does not have a constant initializer}}
+// expected-note at -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 at -2 {{read of non-constexpr variable 'pod_noinit' is not allowed in a constant expression}}
+// expected-note at -3 {{in call to 'PODType(pod_noinit)'}}
+#else
+// expected-note at -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 at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 /* s
 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 at -1 {{required by 'require_constant_initialization' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note at -3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+#else
+// expected-note at -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 <class T>
 struct TestCtor {
   constexpr TestCtor(int x) : value(x) {}
+  // expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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 at -1 {{declaration requires a global destructor}}
 // expected-note at -2 {{required by 'require_constant_initialization' attribute here}}
+// expected-note at -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}}




More information about the cfe-commits mailing list