[clang] [Clang] Fix conseval propagation in templated entities (PR #95233)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 12 05:17:06 PDT 2024
https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/95233
* Lambdas were not considered immediate escalating in a template
* Calls to an immediate function whose arguments were dependent were incorrectly treated as immediate escalating.
Fixes #94935
>From f567bbcafc211ecd3a76075ece26ea8eb1e8d803 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 12 Jun 2024 14:12:39 +0200
Subject: [PATCH] [Clang] Fix conseval propagation in templated entities
* Lambdas were not considered immediate escalating in a template
* Calls to an immediate function whose arguments were dependent was
incorrectly treated as immediate escalating.
Fixes #94935
---
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Sema/Sema.h | 6 +++
clang/lib/Sema/SemaExpr.cpp | 8 ++++
clang/lib/Sema/TreeTransform.h | 3 ++
clang/test/SemaCXX/cxx2a-consteval.cpp | 8 +++-
.../SemaCXX/cxx2b-consteval-propagate.cpp | 42 +++++++++++++++++++
6 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cf1ba02cbc4b2..c5e9363a12119 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -846,6 +846,7 @@ Bug Fixes to C++ Support
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
(#GH88081), (#GH89496), (#GH90669) and (#GH91633).
+- Fix immediate escalation bugs in the presence of dependent call arguments. (#GH94935)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9bf01417186c3..69ac2e804fa75 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5239,6 +5239,12 @@ class Sema final : public SemaBase {
return ExprEvalContexts.back();
};
+ ExpressionEvaluationContextRecord ¤tEvaluationContext() {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back();
+ };
+
ExpressionEvaluationContextRecord &parentEvaluationContext() {
assert(ExprEvalContexts.size() >= 2 &&
"Must be in an expression evaluation context");
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 44f886bf54e3a..2c221fd9c828a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6471,6 +6471,14 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (LangOpts.CPlusPlus) {
if (const auto *CE = dyn_cast<CallExpr>(Call.get()))
DiagnosedUnqualifiedCallsToStdFunctions(*this, CE);
+
+ // If we previously found that the id-expression of this call refers to a
+ // consteval function but the call is dependent, we should not treat is an
+ // an invalid immediate call.
+ if (auto *DRE = dyn_cast<DeclRefExpr>(Fn->IgnoreParens());
+ DRE && Call.get()->isValueDependent()) {
+ currentEvaluationContext().ReferenceToConsteval.erase(DRE);
+ }
}
return Call;
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index f117fe98d142b..cf4e80399632b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14550,6 +14550,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
E->getCallOperator()->isConsteval() ?
Sema::ExpressionEvaluationContext::ImmediateFunctionContext :
Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+ getSema().currentEvaluationContext().InImmediateEscalatingFunctionContext =
+ getSema().getLangOpts().CPlusPlus20 &&
+ E->getCallOperator()->isImmediateEscalating();
Sema::CodeSynthesisContext C;
C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution;
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 622ec31c459dd..fb8385eb02051 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -1195,14 +1195,18 @@ namespace GH66562 {
namespace ns
{
- consteval int foo(int x) { return 1; } // expected-note {{declared here}}
+ consteval int foo(int x) { return 1; } // expected-note {{declared here}} \
+ // expected-note {{passing argument to parameter 'x' here}}
}
template <class A>
struct T {
- static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}}
+ static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}} \
+ // expected-error {{cannot initialize a parameter of type 'int' with an rvalue of type 'char *'}}
};
+template class T<char*>; // expected-note {{in instantiation}}
+
}
namespace GH65520 {
diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index b70c02201ac3c..378414f136172 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -454,3 +454,45 @@ namespace GH91308 {
}
using R1 = decltype(&f<int>);
}
+
+namespace GH94935 {
+
+consteval void f(int) {}
+consteval void undef(int); // expected-note {{declared here}}
+
+template<typename T>
+struct G {
+ void g() {
+ GH94935::f(T::fn());
+ GH94935::f(T::undef2()); // expected-error {{call to consteval function 'GH94935::f' is not a constant expression}} \
+ // expected-note {{undefined function 'undef2' cannot be used in a constant expression}}
+ GH94935::undef(T::fn()); // expected-error {{call to consteval function 'GH94935::undef' is not a constant expression}} \
+ // expected-note {{undefined function 'undef' cannot be used in a constant expression}}
+ }
+};
+
+struct X {
+ static consteval int fn() { return 0; }
+ static consteval int undef2(); // expected-note {{declared here}}
+
+};
+
+void test() {
+ G<X>{}.g(); // expected-note {{instantiation}}
+}
+
+
+template<typename T>
+void g() {
+ auto l = []{
+ ::f(T::fn());
+ };
+}
+
+struct Y {
+ static int fn();
+};
+
+template void g<Y>();
+
+}
More information about the cfe-commits
mailing list