[clang] [Clang][Sema] Fix lambdas mistakenly inheriting InImmediateFunctionContext (PR #232458)
Ferdinand Bachmann via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 16 05:19:24 PDT 2026
https://github.com/Ferdi265 updated https://github.com/llvm/llvm-project/pull/232458
>From d1c540ad942a4eb7c0da7622361bb3a606a1fa00 Mon Sep 17 00:00:00 2001
From: Ferdinand Bachmann <ferdinand.bachmann at yrlf.at>
Date: Thu, 15 Oct 2026 20:39:08 +0200
Subject: [PATCH] [Clang][Sema] Fix lambdas mistakenly inheriting
InImmediateFunctionContext
As per [expr.const]/p14.1, only the innermost enclosing function
parameter scope matters for determining whether a function or lambda is
in an immediate function context. It does not matter whether the parent
is an immediate function or not.
However, synthesized functions such as Lambda conversion operators and
constructors do need to inherit immediate function context from the
parent. Fix this by explicitly exempting the lambda call operator from
this inheritance.
This fixes assertions on valid programs and miscompilations related to
immediate functions being callable from non-immediate contexts due to
missed escalation of lambdas to immediate functions.
Fixes #183415.
Signed-off-by: Ferdinand Bachmann <ferdinand.bachmann at yrlf.at>
---
clang/lib/Sema/SemaExpr.cpp | 9 ++--
.../SemaCXX/cxx2b-consteval-propagate.cpp | 50 +++++++++++++++++++
2 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e29caaab8e3f30..2e9a3b73e5c658 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18546,11 +18546,10 @@ void Sema::PushExpressionEvaluationContextForFunction(
Current.InImmediateEscalatingFunctionContext =
getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
- if (isLambdaMethod(FD))
- Current.InImmediateFunctionContext =
- FD->isConsteval() ||
- (isLambdaMethod(FD) && (Parent.isConstantEvaluated() ||
- Parent.isImmediateFunctionContext()));
+ if (isLambdaMethod(FD) && !isLambdaCallOperator(FD))
+ Current.InImmediateFunctionContext = FD->isConsteval() ||
+ Parent.isConstantEvaluated() ||
+ Parent.isImmediateFunctionContext();
else
Current.InImmediateFunctionContext = FD->isConsteval();
}
diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index 39097d17441f7c..19b66d4cb94e33 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -659,3 +659,53 @@ scope_exit guard( // expected-note {{in instantiation of member function}}
);
}
+
+namespace GH183415 {
+consteval void f(int) {}
+
+void test1() {
+ auto g = []() consteval {
+ return [](int x) {
+ f(x);
+ };
+ }();
+
+ int x = 42; // expected-note {{declared here}}
+ g(x); // expected-error at -1 {{call to immediate function 'GH183415::test1()::(lambda)::operator()::(lambda)::operator()' is not a constant expression}} \
+ // expected-note {{read of non-const variable 'x' is not allowed in a constant expression}}
+}
+
+struct F {
+ consteval F(int) {}
+};
+
+void test2() {
+ auto g = []() consteval {
+ return [](int x) {
+ return F(x);
+ };
+ }();
+
+ int x = 42; // expected-note {{declared here}}
+ g(x); // expected-error at -1 {{call to immediate function 'GH183415::test2()::(lambda)::operator()::(lambda)::operator()' is not a constant expression}} \
+ // expected-note {{read of non-const variable 'x' is not allowed in a constant expression}}
+}
+
+consteval void f() {}
+
+template <auto a>
+auto id = a;
+
+void test3() {
+ id<[]{ f(); }>(); // ok, lambda is escalated to an immediate function
+}
+
+void test4(int a) { // expected-note {{declared here}}
+ auto g = id<[](int i){ f(i); }>;
+ g(a); // expected-error at -1 {{call to immediate function 'GH183415::test4(int)::(lambda)::operator()' is not a constant expression}} \
+ // expected-note {{function parameter 'a' with unknown value cannot be used in a constant expression}}
+}
+
+static_assert(+[]{}); // ok, static_assert is manifestly-constant-evaluated, which should allow taking the address of lambda call operator
+
+}
More information about the cfe-commits
mailing list