[Clang] Do not skip over RequiresExprBodyDecl when creating lambdas (#147764)

When we create a lambda, we would skip over declaration contexts
representing a require expression body, which would lead to wrong
lookup.

Note that I wasn't able to establish why the code
in `Sema::createLambdaClosureType` was there to begin with (it's not
exactly recent)

The changes to mangling only ensure the status quo is preserved and do
not attempt to address the known issues of
mangling lambdas in require clauses.

In particular the itanium mangling is consistent with Clang before this
patch but differs from GCC's.

Fixes #147650
This commit is contained in:
Corentin Jabot 2025-07-10 00:21:09 +03:00 committed by GitHub
parent 16f046281b
commit 6d00c4297f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 39 additions and 2 deletions

View File

@ -926,6 +926,7 @@ Bug Fixes to C++ Support
- Fix a bug where private access specifier of overloaded function not respected. (#GH107629)
- Correctly handle allocations in the condition of a ``if constexpr``.(#GH120197) (#GH134820)
- Fixed a crash when handling invalid member using-declaration in C++20+ mode. (#GH63254)
- Fix name lookup in lambda appearing in the body of a requires expression. (#GH147650)
- Fix a crash when trying to instantiate an ambiguous specialization. (#GH51866)
- Improved handling of variables with ``consteval`` constructors, to
consistently treat the initializer as manifestly constant-evaluated.

View File

@ -1088,6 +1088,9 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
return;
}
while (DC->isRequiresExprBody())
DC = DC->getParent();
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;

View File

@ -249,8 +249,6 @@ Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info,
unsigned LambdaDependencyKind,
LambdaCaptureDefault CaptureDefault) {
DeclContext *DC = CurContext;
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
bool IsGenericLambda =
Info && getGenericLambdaTemplateParameterList(getCurLambda(), *this);

View File

@ -32,3 +32,16 @@ template <typename T> void g(int n) requires requires (T m) {
} {}
// CHECK: define {{.*}}@_Z1gIiEviQrQT__XplfL0p_fp_E(
template void g<int>(int);
namespace GH147650 {
template <int> int b;
template <int b>
void f()
requires requires { [] { (void)b; }; } {}
void test() {
f<42>();
}
// CHECK-LABEL:define {{.*}} void @"_ZN8GH1476501fILi42EEEvvQrqXLNS_3$_0EEE"()
}

View File

@ -57,3 +57,15 @@ void m_fn2() {
} // namespace Regression2
}
namespace GH147650 {
template <int> int b;
template <int b>
void f()
requires requires { [] { (void)b; }; } {}
void test() {
f<42>();
}
// CHECK-LABEL:define {{.*}} void @"??$f@$0CK@@GH147650@@YAXXZ"()
}

View File

@ -340,3 +340,13 @@ void foo() {
}
}
namespace GH147650 {
template <int> int b;
template <int b>
void f()
requires requires { [] { (void)b; static_assert(b == 42); }; } {}
void test() {
f<42>();
}
}