[clang] 916cd55 - [Clang] Avoid an extra `FunctionPrototypeScope` for lambda trailing requires-clauses (#194068)

via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 27 09:46:47 PDT 2026


Author: eiytoq
Date: 2026-04-27T13:46:42-03:00
New Revision: 916cd558c10bf520dd0c1bdd3849fa6163b53795

URL: https://github.com/llvm/llvm-project/commit/916cd558c10bf520dd0c1bdd3849fa6163b53795
DIFF: https://github.com/llvm/llvm-project/commit/916cd558c10bf520dd0c1bdd3849fa6163b53795.diff

LOG: [Clang] Avoid an extra `FunctionPrototypeScope` for lambda trailing requires-clauses (#194068)

`ParseTrailingRequiresClause` currently always creates a synthetic
`FunctionPrototypeScope`. This is needed for ordinary function
declarators
whose prototype scope has already ended, but it is wrong for lambda
trailing
requires-clauses because they are parsed while the lambda prototype
scope is
still active.

The extra counted scope gives parameters in nested requires-expressions
an
incorrect function scope depth. Split the synthetic prototype-scope
setup from
the trailing requires-clause parser so the lambda path can parse the
clause in
the existing prototype scope.

Fixes: #123854
Fixes: #100774

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Parse/Parser.h
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Parse/ParseDeclCXX.cpp
    clang/test/CodeGenCXX/mangle-requires.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 760d91fd97914..0fc63e04bd374 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -554,6 +554,7 @@ Bug Fixes to C++ Support
 - We no longer consider conversion operators when copy-initializing from the same type. This was non
   conforming and could lead to recursive constraint satisfaction checking. (#GH149443)
 - Fixed a crash in Itanium C++ name mangling for a lambda in a local class field initializer inside a constructor/destructor. (#GH176395)
+- Fixed crashes in Itanium C++ name mangling for lambdas with trailing requires-clauses involving requires-expressions. (#GH100774) (#GH123854)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 1d07d8dbcfa01..2274ece3d1d0e 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2943,6 +2943,7 @@ class Parser : public CodeCompletionHandler {
                                      bool MayBeFollowedByDirectInit);
 
   /// Parse a requires-clause as part of a function declaration.
+  void ParseTrailingRequiresClauseWithScope(Declarator &D);
   void ParseTrailingRequiresClause(Declarator &D);
 
   void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 4f37e1471c29e..9ac016d211081 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2160,7 +2160,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
       ;
 
   if (Tok.is(tok::kw_requires))
-    ParseTrailingRequiresClause(D);
+    ParseTrailingRequiresClauseWithScope(D);
 
   // Save late-parsed attributes for now; they need to be parsed in the
   // appropriate function scope after the function Decl has been constructed.
@@ -2413,7 +2413,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
       //	      declarator initializer[opt]
       //        declarator requires-clause
       if (Tok.is(tok::kw_requires))
-        ParseTrailingRequiresClause(D);
+        ParseTrailingRequiresClauseWithScope(D);
       Decl *ThisDecl = ParseDeclarationAfterDeclarator(D, TemplateInfo);
       D.complete(ThisDecl);
       if (ThisDecl)

diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index c1fcde8f46c1c..c73ea46ee6d15 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2530,7 +2530,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
     if (BitfieldSize.isInvalid())
       SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
   } else if (Tok.is(tok::kw_requires)) {
-    ParseTrailingRequiresClause(DeclaratorInfo);
+    ParseTrailingRequiresClauseWithScope(DeclaratorInfo);
   } else {
     ParseOptionalCXX11VirtSpecifierSeq(
         VS, getCurrentClass().IsInterface,
@@ -4102,11 +4102,9 @@ TypeResult Parser::ParseTrailingReturnType(SourceRange &Range,
                                    : DeclaratorContext::TrailingReturn);
 }
 
-void Parser::ParseTrailingRequiresClause(Declarator &D) {
+void Parser::ParseTrailingRequiresClauseWithScope(Declarator &D) {
   assert(Tok.is(tok::kw_requires) && "expected requires");
 
-  SourceLocation RequiresKWLoc = ConsumeToken();
-
   // C++23 [basic.scope.namespace]p1:
   //   For each non-friend redeclaration or specialization whose target scope
   //   is or is contained by the scope, the portion after the declarator-id,
@@ -4125,11 +4123,22 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) {
   if (SS.isValid() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
     DeclScopeObj.EnterDeclaratorScope();
 
-  ExprResult TrailingRequiresClause;
   ParseScope ParamScope(this, Scope::DeclScope |
                                   Scope::FunctionDeclarationScope |
                                   Scope::FunctionPrototypeScope);
 
+  ParseTrailingRequiresClause(D);
+}
+
+void Parser::ParseTrailingRequiresClause(Declarator &D) {
+  assert(Tok.is(tok::kw_requires) && "expected requires");
+  assert(
+      getCurScope()->isFunctionPrototypeScope() &&
+      "trailing requires-clause must be parsed in a function prototype scope");
+
+  SourceLocation RequiresKWLoc = ConsumeToken();
+
+  ExprResult TrailingRequiresClause;
   Actions.ActOnStartTrailingRequiresClause(getCurScope(), D);
 
   std::optional<Sema::CXXThisScopeRAII> ThisScope;

diff  --git a/clang/test/CodeGenCXX/mangle-requires.cpp b/clang/test/CodeGenCXX/mangle-requires.cpp
index 506c5aaf43b9b..7f2d0e5d21991 100644
--- a/clang/test/CodeGenCXX/mangle-requires.cpp
+++ b/clang/test/CodeGenCXX/mangle-requires.cpp
@@ -45,3 +45,28 @@ void test() {
 }
 // CHECK-LABEL:define {{.*}} void @"_ZN8GH1476501fILi42EEEvvQrqXLNS_3$_0EEE"()
 }
+
+namespace GH123854
+{
+
+template <class T>
+constexpr auto f() {
+  return [] () requires requires (T x) { x; } {};
+}
+
+void test() {
+  f<int>()();
+}
+// CHECK-LABEL:define {{.*}} void @_ZZN8GH1238541fIiEEDavENKUlvE_clEvQrQT__Xfp_E
+}
+
+namespace GH100774 {
+
+void test_dependent() {
+  auto L = [](auto x) {
+    return [w = x](auto) requires requires { w; } {};
+  };
+  L(0)(1);
+}
+// CHECK-LABEL: define internal void @"_ZZZN8GH10077414test_dependentEvENK3$_0clIiEEDaT_ENKUlS2_E_clIiEEDaS2_QrqXL_ZZZNS_14test_dependentEvENKS0_clES2_E1wEE"
+}


        


More information about the cfe-commits mailing list