Izaron updated this revision to Diff 409035. Izaron added a comment. I've added an assert that will prevent similar bugs. Let's look if we're good with this one? Here is the list of eval contexts: https://github.com/llvm/llvm-project/blob/87b218b42b14e392aa0363a413d440b77bf04bd4/clang/include/clang/Sema/Sema.h#L1191-L1239 Should we also check for `PotentiallyEvaluatedIfUsed` or it is too much? Looks like only two eval contexts from the list may be evaluated in run-time.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D119651/new/ https://reviews.llvm.org/D119651 Files: clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaCXX/cxx2a-consteval.cpp Index: clang/test/SemaCXX/cxx2a-consteval.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-consteval.cpp +++ clang/test/SemaCXX/cxx2a-consteval.cpp @@ -613,6 +613,24 @@ } // namespace unevaluated +namespace templated { + +consteval int f(int v) { + return v; +} + +template <typename T> +consteval int g(T a) { + // Previously this call was rejected due to incorrect evaluation context + // type in instantiations. Now we show that this call is OK. + int n = f(a); + return n; +} + +static_assert(g(100) == 100); + +} // namespace templated + namespace PR50779 { struct derp { int b = 0; Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5326,8 +5326,13 @@ Var->setImplicitlyInline(); if (OldVar->getInit()) { - EnterExpressionEvaluationContext Evaluated( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); + ExpressionEvaluationContext Context = + ExpressionEvaluationContext::PotentiallyEvaluated; + // If current context is constant evaluated, the variable initializer + // context is also constant evaluated + if (isConstantEvaluated()) + Context = ExpressionEvaluationContext::ConstantEvaluated; + EnterExpressionEvaluationContext Evaluated(*this, Context, Var); // Instantiate the initializer. ExprResult Init; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -16637,6 +16637,11 @@ ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, LambdaContextDecl, ExprContext); + assert( + !(ExprEvalContexts.back().Context == + ExpressionEvaluationContext::PotentiallyEvaluated && + ExprEvalContexts[ExprEvalContexts.size() - 2].isConstantEvaluated()) && + "Can't have an evaluated context within an unevaluated context!"); // Discarded statements and immediate contexts nested in other // discarded statements or immediate context are themselves
Index: clang/test/SemaCXX/cxx2a-consteval.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-consteval.cpp +++ clang/test/SemaCXX/cxx2a-consteval.cpp @@ -613,6 +613,24 @@ } // namespace unevaluated +namespace templated { + +consteval int f(int v) { + return v; +} + +template <typename T> +consteval int g(T a) { + // Previously this call was rejected due to incorrect evaluation context + // type in instantiations. Now we show that this call is OK. + int n = f(a); + return n; +} + +static_assert(g(100) == 100); + +} // namespace templated + namespace PR50779 { struct derp { int b = 0; Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5326,8 +5326,13 @@ Var->setImplicitlyInline(); if (OldVar->getInit()) { - EnterExpressionEvaluationContext Evaluated( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); + ExpressionEvaluationContext Context = + ExpressionEvaluationContext::PotentiallyEvaluated; + // If current context is constant evaluated, the variable initializer + // context is also constant evaluated + if (isConstantEvaluated()) + Context = ExpressionEvaluationContext::ConstantEvaluated; + EnterExpressionEvaluationContext Evaluated(*this, Context, Var); // Instantiate the initializer. ExprResult Init; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -16637,6 +16637,11 @@ ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, LambdaContextDecl, ExprContext); + assert( + !(ExprEvalContexts.back().Context == + ExpressionEvaluationContext::PotentiallyEvaluated && + ExprEvalContexts[ExprEvalContexts.size() - 2].isConstantEvaluated()) && + "Can't have an evaluated context within an unevaluated context!"); // Discarded statements and immediate contexts nested in other // discarded statements or immediate context are themselves
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits