diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticASTKinds.td | 3 | ||||
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 10 | ||||
| -rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx2a.cpp | 19 |
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}} +} |

