summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-06-26 20:33:42 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-06-26 20:33:42 +0000
commit6cfb5bf41823be28bca09fe72dd3d4b83f4e1be8 (patch)
treefeee0d7293bfe84c684d266558865331c9a47666
parentf2468c5d9d036f29b7dae03c6753e8474f5cffff (diff)
Check that the initializer of a non-dependent constexpr variable is constant even within templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@306327 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp4
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp16
2 files changed, 14 insertions, 6 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e340456bc6..71f4d069b8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -11100,9 +11100,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
bool IsGlobal = GlobalStorage && !var->isStaticLocal();
QualType baseType = Context.getBaseElementType(type);
- if (!var->getDeclContext()->isDependentContext() &&
- Init && !Init->isValueDependent()) {
-
+ if (Init && !Init->isValueDependent()) {
if (var->isConstexpr()) {
SmallVector<PartialDiagnosticAt, 8> Notes;
if (!var->evaluateValue(Notes) || !var->isInitICE()) {
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 4abbc8e928..3fda2d0a7f 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -608,7 +608,7 @@ namespace DependentValues {
struct I { int n; typedef I V[10]; };
I::V x, y;
-int g();
+int g(); // expected-note {{declared here}}
template<bool B, typename T> struct S : T {
int k;
void f() {
@@ -616,13 +616,23 @@ template<bool B, typename T> struct S : T {
I &i = cells[k];
switch (i.n) {}
- // FIXME: We should be able to diagnose this.
- constexpr int n = g();
+ constexpr int n = g(); // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr function 'g'}}
constexpr int m = this->g(); // ok, could be constexpr
}
};
+extern const int n;
+template<typename T> void f() {
+ // This is ill-formed, because a hypothetical instantiation at the point of
+ // template definition would be ill-formed due to a construct that does not
+ // depend on a template parameter.
+ constexpr int k = n; // expected-error {{must be initialized by a constant expression}}
+}
+// It doesn't matter that the instantiation could later become valid:
+constexpr int n = 4;
+template void f<int>();
+
}
namespace Class {