summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-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