From c5e1b5e6a99f1ab78dafb54262d8f1fff998cb26 Mon Sep 17 00:00:00 2001 From: Evgeny Shulgin Date: Fri, 25 Feb 2022 16:55:08 +0100 Subject: [PATCH] [Clang][Sema] Do not evaluate value-dependent immediate invocations Value-dependent ConstantExprs are not meant to be evaluated. There is an assert in Expr::EvaluateAsConstantExpr that ensures this condition. But before this patch the method was called without prior check. Fixes https://github.com/llvm/llvm-project/issues/52768 Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D119375 --- clang/lib/Sema/SemaExpr.cpp | 5 ++++- clang/test/SemaCXX/cxx2a-consteval.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 454e21e..b24caa5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16817,7 +16817,10 @@ ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) { ConstantExpr::getStorageKind(Decl->getReturnType().getTypePtr(), getASTContext()), /*IsImmediateInvocation*/ true); - ExprEvalContexts.back().ImmediateInvocationCandidates.emplace_back(Res, 0); + /// Value-dependent constant expressions should not be immediately + /// evaluated until they are instantiated. + if (!Res->isValueDependent()) + ExprEvalContexts.back().ImmediateInvocationCandidates.emplace_back(Res, 0); return Res; } diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index e909f2f..941d47d 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -613,6 +613,32 @@ static_assert(is_same::value); } // namespace unevaluated +namespace value_dependent { + +consteval int foo(int x) { + return x; +} + +template constexpr int bar() { + // Previously this call was rejected as value-dependent constant expressions + // can't be immediately evaluated. Now we show that we don't immediately + // evaluate them until they are instantiated. + return foo(X); +} + +template constexpr int baz() { + constexpr int t = sizeof(T); + // Previously this call was rejected as `t` is value-dependent and its value + // is unknown until the function is instantiated. Now we show that we don't + // reject such calls. + return foo(t); +} + +static_assert(bar<15>() == 15); +static_assert(baz() == sizeof(int)); + +} // namespace value_dependent + namespace PR50779 { struct derp { int b = 0; -- 2.7.4