aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-10-29 18:26:47 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-10-29 18:26:47 +0000
commit9568f0c13a84695c5cc064e7c32412f84604cb1e (patch)
treeb5b5e53ec7d314157aba221be61f7b66cbbce934
parentba927d9b26ead2ad535c7761b8862d8e82c41b13 (diff)
Partially roll back r166898; it exposed a bug in the standard.
The problem is as follows: C++11 has contexts which are not potentially-evaluated, and yet in which we are required or encouraged to perform constant evaluation. In such contexts, we are not permitted to implicitly define special member functions for literal types, therefore we cannot evalaute those constant expressions. Punt on this in one more context for now by skipping checking constexpr variable initializers if they occur in dependent contexts. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166956 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp27
2 files changed, 25 insertions, 5 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 0eb123105b..52ee80f833 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7200,7 +7200,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Expr *Init = var->getInit();
bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal();
- if (Init && !Init->isValueDependent()) {
+ if (!var->getDeclContext()->isDependentContext() &&
+ Init && !Init->isValueDependent()) {
if (IsGlobal && !var->isConstexpr() &&
getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor,
var->getLocation())
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 9a9746ee29..0dd7ffe5a9 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -521,7 +521,7 @@ namespace DependentValues {
struct I { int n; typedef I V[10]; };
I::V x, y;
-int g(); // expected-note {{here}}
+int g();
template<bool B, typename T> struct S : T {
int k;
void f() {
@@ -529,9 +529,8 @@ template<bool B, typename T> struct S : T {
I &i = cells[k];
switch (i.n) {}
- constexpr int n = g(); // \
- // expected-error {{must be initialized by a constant expression}} \
- // expected-note {{non-constexpr function 'g'}}
+ // FIXME: We should be able to diagnose this.
+ constexpr int n = g();
constexpr int m = this->g(); // ok, could be constexpr
}
@@ -1435,3 +1434,23 @@ namespace TypeId {
constexpr auto &y = typeid(g()); // expected-error{{constant expression}} \
// expected-note{{typeid applied to expression of polymorphic type 'TypeId::A' is not allowed in a constant expression}}
}
+
+namespace PR14203 {
+ struct duration {
+ constexpr duration() {}
+ constexpr operator int() const { return 0; }
+ };
+ template<typename T> void f() {
+ // If we want to evaluate this at the point of the template definition, we
+ // need to trigger the implicit definition of the move constructor at that
+ // point.
+ // FIXME: C++ does not permit us to implicitly define it at the appropriate
+ // times, since it is only allowed to be implicitly defined when it is
+ // odr-used.
+ constexpr duration d = duration();
+ }
+ // FIXME: It's unclear whether this is valid. On the one hand, we're not
+ // allowed to generate a move constructor. On the other hand, if we did,
+ // this would be a constant expression.
+ int n = sizeof(short{duration(duration())}); // expected-error {{non-constant-expression cannot be narrowed}} expected-note {{override}}
+}