summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-09-29 06:22:54 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-09-29 06:22:54 +0000
commit1e8c0850b1f58752c7c0174ed703e8215b2a4d31 (patch)
tree61fea645ec7785800228fb29b9732bc49440b2c6
parent4566f87649cc12063c8234e70e34b3a2b393679e (diff)
downloadbcm5719-llvm-1e8c0850b1f58752c7c0174ed703e8215b2a4d31.tar.gz
bcm5719-llvm-1e8c0850b1f58752c7c0174ed703e8215b2a4d31.zip
For now, disallow lifetime-extended temporaries with non-trivial (but
constexpr) destructors from being used in the values of constexpr variables. The standard rules here are unclear at best, so rejecting the problematic cases seems prudent. Prior to this change, we would fail to run the destructors for these temporaries, even if they had side-effects, which is certainly not the right behavior. llvm-svn: 373161
-rw-r--r--clang/include/clang/Basic/DiagnosticASTKinds.td3
-rw-r--r--clang/lib/AST/ExprConstant.cpp10
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx2a.cpp19
3 files changed, 31 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index eb2a1f02fd8..f4eeebd73ab 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -210,6 +210,9 @@ def note_constexpr_destroy_out_of_lifetime : Note<
"destroying object '%0' whose lifetime has already ended">;
def note_constexpr_unsupported_destruction : Note<
"non-trivial destruction of type %0 in a constant expression is not supported">;
+def note_constexpr_unsupported_tempoarary_nontrivial_dtor : Note<
+ "non-trivial destruction of lifetime-extended temporary with type %0 "
+ "used in the result of a constant expression is not yet supported">;
def note_constexpr_unsupported_unsized_array : Note<
"array-to-pointer decay of array member without known bound is not supported">;
def note_constexpr_unsized_array_indexed : Note<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b0c0c2e8d98..f91e0782b89 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1999,10 +1999,18 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
} else if (const auto *MTE = dyn_cast_or_null<MaterializeTemporaryExpr>(
Base.dyn_cast<const Expr *>())) {
if (CheckedTemps.insert(MTE).second) {
+ QualType TempType = getType(Base);
+ if (TempType.isDestructedType()) {
+ Info.FFDiag(MTE->getExprLoc(),
+ diag::note_constexpr_unsupported_tempoarary_nontrivial_dtor)
+ << TempType;
+ return false;
+ }
+
APValue *V = Info.Ctx.getMaterializedTemporaryValue(MTE, false);
assert(V && "evasluation result refers to uninitialised temporary");
if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
- Info, MTE->getExprLoc(), getType(Base), *V,
+ Info, MTE->getExprLoc(), TempType, *V,
Usage, SourceLocation(), CheckedTemps))
return false;
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index 152bfcf0a7b..5e05c292984 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1250,3 +1250,22 @@ namespace dtor_call {
as.b.~A(); // expected-note {{destruction of member 'b' of union with active member 'a'}}
}
}
+
+namespace temp_dtor {
+ void f();
+ struct A {
+ bool b;
+ constexpr ~A() { if (b) f(); }
+ };
+
+ // We can't accept either of these unless we start actually registering the
+ // destructors of the A temporaries to run on shutdown. It's unclear what the
+ // intended standard behavior is so we reject this for now.
+ constexpr A &&a = A{false}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}
+ void f() { a.b = true; }
+
+ constexpr A &&b = A{true}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}
+
+ // FIXME: We could in prinicple accept this.
+ constexpr const A &c = A{false}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}
+}
OpenPOWER on IntegriCloud