[clang] [Clang] Fixed getPredefinedExprDecl Assert When No Lambda Scope (PR #221713)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 7 05:05:12 PDT 2026
https://github.com/tadeuszjt created https://github.com/llvm/llvm-project/pull/221713
**Problem**
`getPredefinedExprDecl` searches through the chain of `DecContext`s for the appropriate context. It has to skip the current context when in a lambda scope but before the compound statement. The code expects a `LambdaScopeInfo` to be available in this case but it is possible for there not to be if parsing an `operator()` definition on a lambda type.
**Solution**
Just don't perform the skip if no lambda scope is present instead of asserting.
>From e5daa4b7c0a60cacd1c6935d6d706011d0ad45c6 Mon Sep 17 00:00:00 2001
From: Tadeusz Tomoszek <tadeuszjt at protonmail.com>
Date: Mon, 7 Sep 2026 13:57:25 +0200
Subject: [PATCH] [Clang] Fixed getPredefinedExprDecl Assert When No Lambda
Scope
---
clang/lib/Sema/SemaExpr.cpp | 27 ++++++++++++++------------
clang/test/Sema/ms_predefined_expr.cpp | 6 ++++++
2 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c93efeb928c56..9236600fb7a43 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2119,24 +2119,27 @@ static PredefinedIdentKind getPredefinedExprKind(tok::TokenKind Kind) {
/// block, lambda, captured statement, function, otherwise a nullptr.
static Decl *getPredefinedExprDecl(Sema &S, DeclContext *DC) {
auto LSI = S.FunctionScopes.rbegin();
+ auto E = S.FunctionScopes.rend();
- auto tryAdjustLambdaContext = [&S, &LSI](DeclContext *&DC) {
+ for (; DC; DC = DC->getParent()) {
+ // Skip this DC if we are in a lambda declaration context but not yet in
+ // the compound statement.
if (isLambdaCallOperator(DC)) {
- auto E = S.FunctionScopes.rend();
while (LSI != E && !isa<LambdaScopeInfo>(*LSI))
++LSI;
- assert(LSI != E && "Should be in a lambda scope info");
- if (dyn_cast<LambdaScopeInfo>(*LSI)->BeforeCompoundStatement)
- DC = DC->getParent();
- ++LSI;
+
+ // It's possible that a lambda scope isn't being parsed here, such as an
+ // operator() definition on a lambda type.
+ if (LSI != E) {
+ bool Before = cast<LambdaScopeInfo>(*LSI)->BeforeCompoundStatement;
+ ++LSI;
+ if (Before)
+ continue;
+ }
}
- };
- tryAdjustLambdaContext(DC);
- while (DC &&
- !isa<BlockDecl, CapturedDecl, FunctionDecl, ObjCMethodDecl>(DC)) {
- DC = DC->getParent();
- tryAdjustLambdaContext(DC);
+ if (isa<BlockDecl, CapturedDecl, FunctionDecl, ObjCMethodDecl>(DC))
+ break;
}
return cast_or_null<Decl>(DC);
diff --git a/clang/test/Sema/ms_predefined_expr.cpp b/clang/test/Sema/ms_predefined_expr.cpp
index b42a494beef98..e79b9baed710e 100644
--- a/clang/test/Sema/ms_predefined_expr.cpp
+++ b/clang/test/Sema/ms_predefined_expr.cpp
@@ -206,3 +206,9 @@ void test_in_constexpr_struct_init() {
} constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
}
+
+namespace GH221564 {
+ auto l = [](auto a) { return 42; }; // expected-note{{defined here}}
+ using L = decltype(l);
+ auto L::operator()() const { return {"<="}; } // expected-error{{out-of-line definition of 'operator()' does not match any declaration}}
+}
More information about the cfe-commits
mailing list