[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