loladiro created this revision.
loladiro added reviewers: EricWF, aaron.ballman, rsmith.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.
This hooks up the detailed diagnostics why constant initialization was not
possible if require_constant_initialization reports an error. I have updated
the test to account for the new notes.
Everything works fine, except that in C++11 mode we get:
```
error: 'note' diagnostics expected but not seen:
File
/data/llvm/tools/clang/test/SemaCXX/attr-require-constant-initialization.cpp
Line 229 (directive at
/data/llvm/tools/clang/test/SemaCXX/attr-require-constant-initialization.cpp:231):
non-constexpr constructor 'NonLit' cannot be used in a constant expression
error: 'note' diagnostics seen but not expected:
(frontend): non-literal type 'NonLit' cannot be used in a constant expression
```
This is because of an ImplicitValueInitExpr that gets passed into
CheckLiteralType, but since ImplicitValueInitExpr doesn't have source
information we get an invalid source location. I'm not really sure how to fix
that (Is it possible to test for a note without source location?). Adding the
proper source locations to ImplicitValueInitExpr seemed like a bigger
undertaking than was warranted for this patch, so I'd appreciate guidance on
how to proceed.
Repository:
rL LLVM
https://reviews.llvm.org/D24371
Files:
lib/Sema/SemaDecl.cpp
test/SemaCXX/attr-require-constant-initialization.cpp
Index: test/SemaCXX/attr-require-constant-initialization.cpp
===================================================================
--- test/SemaCXX/attr-require-constant-initialization.cpp
+++ 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,17 +20,17 @@
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) {}
@@ -82,23 +82,44 @@
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_initializer' 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_initializer' 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_initializer' 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_initializer' 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 @@
#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,21 @@
#else
ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initializer' 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_initializer' attribute here}}
-
+ // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
#if __cplusplus >= 201103L
+ // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+
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_initializer' 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_initializer' 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 +184,21 @@
ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initializer' 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)'}}
+#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 +216,25 @@
#else
ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initializer' 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_initializer' 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_initializer' 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_initializer' 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_initializer' attribute here}}
+// expected-note@-2 {{non-constexpr constructor 'NonLit' 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_initializer' attribute here}}
+// expected-note@-2 {{subexpression not valid in a constant expression}}
ATTR int lit_in_init = LitType{42}.value;
#endif
@@ -218,8 +257,9 @@
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_initializer' attribute here}}
-
#if __cplusplus >= 201103L
+// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+
ATTR int val_init{};
ATTR int brace_init = {};
#endif
@@ -233,15 +273,17 @@
// initializer
struct NotC {
constexpr NotC(void *) {}
- NotC(int) {}
+ NotC(int) {} // expected-note {{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_initializer' attribute here}}
+// expected-note@-2 {{in call to 'TestCtor(42)'}}
#endif
// Test various array types
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10532,6 +10532,12 @@
<< Init->getSourceRange();
Diag(attr->getLocation(), diag::note_declared_required_constant_init_here)
<< attr->getRange();
+ APValue Value;
+ SmallVector<PartialDiagnosticAt, 8> Notes;
+ cast<Expr>(var->ensureEvaluatedStmt()->Value)->EvaluateAsInitializer(
+ Value, getASTContext(), var, Notes);
+ for (auto &it : Notes)
+ Diag(it.first, it.second);
}
}
else if (!var->isConstexpr() && IsGlobal &&
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits