[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