https://github.com/StefanPaulet updated 
https://github.com/llvm/llvm-project/pull/211811

>From 9bb556e0041bad23057343ff227aac711871463e Mon Sep 17 00:00:00 2001
From: StefanPaulet <[email protected]>
Date: Mon, 20 Jul 2026 17:38:02 +0300
Subject: [PATCH 1/4] Fixed predefined expressions after lambda parameters

---
 clang/include/clang/Sema/ScopeInfo.h |  2 ++
 clang/lib/Sema/SemaExpr.cpp          | 12 +++++--
 clang/lib/Sema/SemaLambda.cpp        |  2 ++
 clang/lib/Sema/TreeTransform.h       |  2 ++
 clang/test/SemaCXX/GH122657.cpp      | 49 ++++++++++++++++++++++++++++
 5 files changed, 64 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/SemaCXX/GH122657.cpp

diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 7e4d3f2e0d1cb..a7a98e56b25ec 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -874,6 +874,8 @@ class LambdaScopeInfo final :
   /// is known.
   bool AfterParameterList = true;
 
+  bool BeforeCompoundStatement = false;
+
   ParmVarDecl *ExplicitObjectParameter = nullptr;
 
   /// Source range covering the lambda introducer [...].
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 592cb1d588370..0a9b02af8a8dd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2114,7 +2114,13 @@ static PredefinedIdentKind 
getPredefinedExprKind(tok::TokenKind Kind) {
 /// getPredefinedExprDecl - Returns Decl of a given DeclContext that can be 
used
 /// to determine the value of a PredefinedExpr. This can be either a
 /// block, lambda, captured statement, function, otherwise a nullptr.
-static Decl *getPredefinedExprDecl(DeclContext *DC) {
+static Decl *getPredefinedExprDecl(Sema &S, DeclContext *DC) {
+  if (isLambdaCallOperator(DC)) {
+    LambdaScopeInfo *LSI = S.getCurLambda();
+    if (LSI->BeforeCompoundStatement) {
+      DC = DC->getParent();
+    }
+  }
   while (DC && !isa<BlockDecl, CapturedDecl, FunctionDecl, ObjCMethodDecl>(DC))
     DC = DC->getParent();
   return cast_or_null<Decl>(DC);
@@ -2200,7 +2206,7 @@ Sema::ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> 
Toks) {
   // Note: Although function local macros are defined only inside functions,
   // we ensure a valid `CurrentDecl` even outside of a function. This allows
   // expansion of macros into empty string literals without additional checks.
-  Decl *CurrentDecl = getPredefinedExprDecl(CurContext);
+  Decl *CurrentDecl = getPredefinedExprDecl(*this, CurContext);
   if (!CurrentDecl)
     CurrentDecl = Context.getTranslationUnitDecl();
 
@@ -3627,7 +3633,7 @@ static void ConvertUTF8ToWideString(unsigned 
CharByteWidth, StringRef Source,
 
 ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
                                      PredefinedIdentKind IK) {
-  Decl *currentDecl = getPredefinedExprDecl(CurContext);
+  Decl *currentDecl = getPredefinedExprDecl(*this, CurContext);
   if (!currentDecl) {
     Diag(Loc, diag::ext_predef_outside_function);
     currentDecl = Context.getTranslationUnitDecl();
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 8572e3a742a6c..0fb4e1fa92d99 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1436,6 +1436,7 @@ void Sema::ActOnLambdaClosureParameters(
         TemplateParams->containsUnexpandedParameterPack();
   }
   LSI->AfterParameterList = true;
+  LSI->BeforeCompoundStatement = true;
 }
 
 void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
@@ -1444,6 +1445,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer 
&Intro,
 
   LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
   LSI->CallOperator->setConstexprKind(DS.getConstexprSpecifier());
+  LSI->BeforeCompoundStatement = false;
 
   SmallVector<ParmVarDecl *, 8> Params;
   bool ExplicitResultType;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 3c8fcbe582b43..df2c0429ef7e0 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -16077,6 +16077,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr 
*E) {
         TPL->containsUnexpandedParameterPack();
   }
 
+  LSI->BeforeCompoundStatement = true;
   TypeLocBuilder NewCallOpTLBuilder;
   TypeLoc OldCallOpTypeLoc =
       E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
@@ -16101,6 +16102,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr 
*E) {
       !TRC.ArgPackSubstIndex)
     TRC.ArgPackSubstIndex = SemaRef.ArgPackSubstIndex;
 
+  LSI->BeforeCompoundStatement = false;
   getSema().CompleteLambdaCallOperator(
       NewCallOperator, E->getCallOperator()->getLocation(),
       E->getCallOperator()->getInnerLocStart(), TRC, NewCallOpTSI,
diff --git a/clang/test/SemaCXX/GH122657.cpp b/clang/test/SemaCXX/GH122657.cpp
new file mode 100644
index 0000000000000..1faca88bf3a77
--- /dev/null
+++ b/clang/test/SemaCXX/GH122657.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -fblocks -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template <unsigned long long n>
+struct Sized {
+  char data[n];
+};
+
+template <typename T>
+int baz() {
+  static constexpr auto funcSize = sizeof(__func__);
+  static constexpr auto functionSize = sizeof(__FUNCTION__);
+  static constexpr auto prettySize = sizeof(__PRETTY_FUNCTION__);
+
+  auto lfunc = []() noexcept(sizeof(__func__) == funcSize) -> 
Sized<sizeof(__func__)> { return {}; };
+  auto lfunction = []() noexcept(sizeof(__FUNCTION__) == functionSize) -> 
Sized<sizeof(__FUNCTION__)> { return {}; };
+  auto lpretty = []() noexcept(sizeof(__PRETTY_FUNCTION__) == prettySize) -> 
Sized<sizeof(__PRETTY_FUNCTION__)> { return {}; };
+
+  static_assert(sizeof(lfunc()) == 5, "baz");
+  static_assert(noexcept(lfunc()) == true, "noexcept");
+
+  static_assert(sizeof(lfunction()) == 5, "baz");
+  static_assert(noexcept(lfunction()) == true, "noexcept");
+
+  static_assert(sizeof(lpretty()) == 33, "int baz() [T = int]_block_invoke");
+  static_assert(noexcept(lpretty()) == true, "noexcept");
+
+  return 0;
+}
+
+int main() {
+  static constexpr auto funcSize = sizeof(__func__);
+  static constexpr auto functionSize = sizeof(__FUNCTION__);
+  static constexpr auto prettySize = sizeof(__PRETTY_FUNCTION__);
+
+  auto lfunc = []() noexcept(sizeof(__func__) == funcSize) -> 
Sized<sizeof(__func__)> { return {}; };
+  auto lfunction = []() noexcept(sizeof(__FUNCTION__) == functionSize) -> 
Sized<sizeof(__FUNCTION__)> { return {}; };
+  auto lpretty = []() noexcept(sizeof(__PRETTY_FUNCTION__) == prettySize) -> 
Sized<sizeof(__PRETTY_FUNCTION__)> { return {}; };
+
+  static_assert(sizeof(lfunc()) == 5, "main");
+  static_assert(noexcept(lfunc()) == true, "noexcept");
+
+  static_assert(sizeof(lfunction()) == 5, "main");
+  static_assert(noexcept(lfunction()) == true, "noexcept");
+
+  static_assert(sizeof(lpretty()) == 11, "int main()");
+  static_assert(noexcept(lpretty()) == true, "noexcept");
+}
+

>From aa5f7c86cecfef9e4ea967426e978b26fbcc7eb2 Mon Sep 17 00:00:00 2001
From: StefanPaulet <[email protected]>
Date: Fri, 24 Jul 2026 17:45:42 +0300
Subject: [PATCH 2/4] Added release note

---
 clang/docs/ReleaseNotes.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 83a2b10d96046..8840286927a68 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -338,6 +338,7 @@ features cannot lower the translation-unit ABI level;
 
 - Fixed a constraint comparison bug in partial ordering. (#GH182671)
 - Fixed a rejected-valid case that used an explicit object parameter in an 
out-of-line definition of a nested class member. (#GH136472)
+- Fixed a bug where `__func__`, `__PRETTY_FUNCTION__` and `__FUNCTION__` were 
not resolving to the proper function when inside a lambda return type 
(#GH211811)
 
 #### Bug Fixes to Compiler Builtins
 

>From 69f3bc776864f88c938f0fbce7da9d2837a7f36f Mon Sep 17 00:00:00 2001
From: StefanPaulet <[email protected]>
Date: Sat, 25 Jul 2026 17:00:19 +0300
Subject: [PATCH 3/4] Addressed review comment

---
 clang/include/clang/Sema/ScopeInfo.h | 2 +-
 clang/lib/Sema/SemaLambda.cpp        | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 8fccad70eb9dd..8dc40a5bc58bd 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -879,7 +879,7 @@ class LambdaScopeInfo final :
   /// is known.
   bool AfterParameterList = true;
 
-  bool BeforeCompoundStatement = false;
+  bool BeforeCompoundStatement = true;
 
   ParmVarDecl *ExplicitObjectParameter = nullptr;
 
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index a580fbbd33cf1..bbe93f6ab8a40 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1436,7 +1436,6 @@ void Sema::ActOnLambdaClosureParameters(
         TemplateParams->containsUnexpandedParameterPack();
   }
   LSI->AfterParameterList = true;
-  LSI->BeforeCompoundStatement = true;
 }
 
 void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,

>From c93c24dcbc721017e0e4d9c9068182de642fe80f Mon Sep 17 00:00:00 2001
From: StefanPaulet <[email protected]>
Date: Sat, 25 Jul 2026 18:18:10 +0300
Subject: [PATCH 4/4] Addressed review comment

---
 clang/lib/Sema/SemaExpr.cpp | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e936fdf1f8fc0..1066a337f2012 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2117,14 +2117,28 @@ static PredefinedIdentKind 
getPredefinedExprKind(tok::TokenKind Kind) {
 /// to determine the value of a PredefinedExpr. This can be either a
 /// block, lambda, captured statement, function, otherwise a nullptr.
 static Decl *getPredefinedExprDecl(Sema &S, DeclContext *DC) {
-  if (isLambdaCallOperator(DC)) {
-    LambdaScopeInfo *LSI = S.getCurLambda();
-    if (LSI->BeforeCompoundStatement) {
-      DC = DC->getParent();
+  auto LSI = S.FunctionScopes.rbegin();
+
+  auto tryAdjustLambdaContext = [&S, &LSI](DeclContext *&DC) {
+    if (isLambdaCallOperator(DC)) {
+      auto E = S.FunctionScopes.rend();
+      while (LSI != E && isa<CapturingScopeInfo>(*LSI) &&
+             !isa<LambdaScopeInfo>(*LSI))
+        ++LSI;
+      assert(LSI != E && "Should be in a lambda scope info");
+      if (dyn_cast<LambdaScopeInfo>(*LSI)->BeforeCompoundStatement)
+        DC = DC->getParent();
+      ++LSI;
     }
-  }
-  while (DC && !isa<BlockDecl, CapturedDecl, FunctionDecl, ObjCMethodDecl>(DC))
+  };
+
+  tryAdjustLambdaContext(DC);
+  while (DC &&
+         !isa<BlockDecl, CapturedDecl, FunctionDecl, ObjCMethodDecl>(DC)) {
     DC = DC->getParent();
+    tryAdjustLambdaContext(DC);
+  }
+
   return cast_or_null<Decl>(DC);
 }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to