https://github.com/jiixyj updated https://github.com/llvm/llvm-project/pull/179035
From 72d814fb6d05ae529538d5b673277e6c065bbbb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Sat, 31 Jan 2026 14:26:59 +0100 Subject: [PATCH 1/9] Don't use VarDecl of local variables as ManglingContextDecl for lambdas --- clang/lib/Sema/SemaLambda.cpp | 8 ++++++++ clang/test/Modules/pr178893.cppm | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 clang/test/Modules/pr178893.cppm diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index e74fe02bd0cf5..24426259bf01c 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -294,6 +294,14 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { bool IsInNonspecializedTemplate = inTemplateInstantiation() || CurContext->isDependentContext(); + // If we must allocate mangling numbers but the `ManglingContextDecl` + // is a local variable, use the `DeclContext` containing the lambda expression + // instead. + if (ManglingContextDecl) + if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl); + Var && Var->isLocalVarDecl()) + ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC)); + // Default arguments of member function parameters that appear in a class // definition, as well as the initializers of data members, receive special // treatment. Identify them. diff --git a/clang/test/Modules/pr178893.cppm b/clang/test/Modules/pr178893.cppm new file mode 100644 index 0000000000000..6d2a599588667 --- /dev/null +++ b/clang/test/Modules/pr178893.cppm @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-apple-macosx10.7.0 -fmodules -xc++ -emit-llvm -o - %s -w | FileCheck %s + +// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE_clEv +// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE0_clEv + +export module mod; + +namespace PR178893 { + struct format { + static inline int parse(int* i) + { + int number; + number = [&]() -> int { return i[0]; }(); + + volatile bool b = true; + if (b) { + auto identifier = [&]() -> int { return i[1]; }(); + return identifier; + } + + return number; + } + }; + + int test_format() { + int n[2] = {1, 0}; + return format::parse(n); + } +} From d5dbb1738f1d2c90850d27ba5e3e7245e6f325ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Sun, 1 Feb 2026 10:45:25 +0100 Subject: [PATCH 2/9] Use `dyn_cast_or_null` instead of null check plus `dyn_cast` Co-authored-by: Corentin Jabot <[email protected]> --- clang/lib/Sema/SemaLambda.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 24426259bf01c..cdefd60508164 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -297,8 +297,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // If we must allocate mangling numbers but the `ManglingContextDecl` // is a local variable, use the `DeclContext` containing the lambda expression // instead. - if (ManglingContextDecl) - if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl); + if (VarDecl *Var = dyn_cast_or_null<VarDecl>(ManglingContextDecl); Var && Var->isLocalVarDecl()) ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC)); From 42bb683d0d44e008408f542b01e192a4d192e273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Sun, 1 Feb 2026 10:56:51 +0100 Subject: [PATCH 3/9] Autoformat --- clang/lib/Sema/SemaLambda.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index cdefd60508164..1066333722bd8 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -298,8 +298,8 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // is a local variable, use the `DeclContext` containing the lambda expression // instead. if (VarDecl *Var = dyn_cast_or_null<VarDecl>(ManglingContextDecl); - Var && Var->isLocalVarDecl()) - ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC)); + Var && Var->isLocalVarDecl()) + ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC)); // Default arguments of member function parameters that appear in a class // definition, as well as the initializers of data members, receive special From 4be67cb8356bf53bfe074663dc47792cb66fecf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Mon, 2 Feb 2026 13:10:49 +0100 Subject: [PATCH 4/9] Refactor so that fallback only applies to module case --- clang/lib/Sema/SemaLambda.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 1066333722bd8..f7fd1d1831500 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -294,13 +294,6 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { bool IsInNonspecializedTemplate = inTemplateInstantiation() || CurContext->isDependentContext(); - // If we must allocate mangling numbers but the `ManglingContextDecl` - // is a local variable, use the `DeclContext` containing the lambda expression - // instead. - if (VarDecl *Var = dyn_cast_or_null<VarDecl>(ManglingContextDecl); - Var && Var->isLocalVarDecl()) - ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC)); - // Default arguments of member function parameters that appear in a class // definition, as well as the initializers of data members, receive special // treatment. Identify them. @@ -311,12 +304,24 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // Yeah, I think the only cases left where lambdas don't need a // mangling are when they have (effectively) internal linkage or appear // in a non-inline function in a non-module translation unit. - if (auto *ND = dyn_cast<NamedDecl>(ManglingContextDecl ? ManglingContextDecl - : cast<Decl>(DC)); + + Decl *ManglingContextDeclForModule = [&]() { + if (!ManglingContextDecl || [&]() { + // If we must allocate mangling numbers but the + // `ManglingContextDecl` is a local variable, use the `DeclContext` + // containing the lambda expression instead. + VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl); + return Var && Var->isLocalVarDecl(); + }()) + return const_cast<Decl *>(cast<Decl>(DC)); + + return ManglingContextDecl; + }(); + + if (auto *ND = dyn_cast<NamedDecl>(ManglingContextDeclForModule); ND && (ND->isInNamedModule() || ND->isFromGlobalModule()) && ND->isExternallyVisible()) { - if (!ManglingContextDecl) - ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC)); + ManglingContextDecl = ND; return NonInlineInModulePurview; } From 8b7701621926ec2e1acbf50fed35973227523ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Tue, 3 Feb 2026 16:49:40 +0100 Subject: [PATCH 5/9] Remove unneeded '-fmodules' flag --- clang/test/Modules/pr178893.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Modules/pr178893.cppm b/clang/test/Modules/pr178893.cppm index 6d2a599588667..eb4041c330cb3 100644 --- a/clang/test/Modules/pr178893.cppm +++ b/clang/test/Modules/pr178893.cppm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-apple-macosx10.7.0 -fmodules -xc++ -emit-llvm -o - %s -w | FileCheck %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-apple-macosx10.7.0 -xc++ -emit-llvm -o - %s -w | FileCheck %s // CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE_clEv // CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE0_clEv From 49338edb86222be0354114c4d4f19ff596c81750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Tue, 3 Feb 2026 16:50:32 +0100 Subject: [PATCH 6/9] Make test a bit more robust Co-authored-by: Chuanqi Xu <[email protected]> --- clang/test/Modules/pr178893.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Modules/pr178893.cppm b/clang/test/Modules/pr178893.cppm index eb4041c330cb3..81f29ac087712 100644 --- a/clang/test/Modules/pr178893.cppm +++ b/clang/test/Modules/pr178893.cppm @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-apple-macosx10.7.0 -xc++ -emit-llvm -o - %s -w | FileCheck %s -// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE_clEv +// CHECK-LABEL: define {{.*}}@_ZZN8PR178893W3mod6format5parseEPiENKUlvE_clEv // CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE0_clEv export module mod; From 691f4ed6ee9fa27c09d843206fc74b107277932a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Tue, 3 Feb 2026 16:51:20 +0100 Subject: [PATCH 7/9] Make test a bit more robust, part 2 --- clang/test/Modules/pr178893.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Modules/pr178893.cppm b/clang/test/Modules/pr178893.cppm index 81f29ac087712..70bb681f4235d 100644 --- a/clang/test/Modules/pr178893.cppm +++ b/clang/test/Modules/pr178893.cppm @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-apple-macosx10.7.0 -xc++ -emit-llvm -o - %s -w | FileCheck %s // CHECK-LABEL: define {{.*}}@_ZZN8PR178893W3mod6format5parseEPiENKUlvE_clEv -// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE0_clEv +// CHECK-LABEL: define {{.*}}@_ZZN8PR178893W3mod6format5parseEPiENKUlvE0_clEv export module mod; From 4de014b1a13557e4296b1e0c7fe78733de241ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Tue, 3 Feb 2026 16:52:43 +0100 Subject: [PATCH 8/9] Use %itanium_abi_triple as triple for the test --- clang/test/Modules/pr178893.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Modules/pr178893.cppm b/clang/test/Modules/pr178893.cppm index 70bb681f4235d..e58e183d82aba 100644 --- a/clang/test/Modules/pr178893.cppm +++ b/clang/test/Modules/pr178893.cppm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-apple-macosx10.7.0 -xc++ -emit-llvm -o - %s -w | FileCheck %s +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++ -emit-llvm -o - %s -w | FileCheck %s // CHECK-LABEL: define {{.*}}@_ZZN8PR178893W3mod6format5parseEPiENKUlvE_clEv // CHECK-LABEL: define {{.*}}@_ZZN8PR178893W3mod6format5parseEPiENKUlvE0_clEv From c09989925f901fbc9d7a073ad13e222e5b52f68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <[email protected]> Date: Fri, 6 Feb 2026 18:22:24 +0100 Subject: [PATCH 9/9] Check for modules in 'Normal' Kind using helper function, removing 'NonInlineInModulePurview' --- clang/lib/Sema/SemaLambda.cpp | 46 ++++++++++++----------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index f7fd1d1831500..772dc9f9d1287 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -275,6 +275,20 @@ static bool isInInlineFunction(const DeclContext *DC) { return false; } +// See discussion in https://github.com/itanium-cxx-abi/cxx-abi/issues/186 +// +// zygoloid: +// Yeah, I think the only cases left where lambdas don't need a +// mangling are when they have (effectively) internal linkage or +// appear in a non-inline function in a non-module translation unit. +static bool isNonInlineInModulePurview(const Decl *ManglingContextDecl, + const DeclContext *DC) { + auto *ND = dyn_cast<NamedDecl>(ManglingContextDecl ? ManglingContextDecl + : cast<Decl>(DC)); + return ND && ((ND->isInNamedModule() || ND->isFromGlobalModule()) && + ND->isExternallyVisible()); +} + std::tuple<MangleNumberingContext *, Decl *> Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // Compute the context for allocating mangling numbers in the current @@ -288,7 +302,6 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { InlineVariable, TemplatedVariable, Concept, - NonInlineInModulePurview } Kind = Normal; bool IsInNonspecializedTemplate = @@ -298,33 +311,6 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // definition, as well as the initializers of data members, receive special // treatment. Identify them. Kind = [&]() { - // See discussion in https://github.com/itanium-cxx-abi/cxx-abi/issues/186 - // - // zygoloid: - // Yeah, I think the only cases left where lambdas don't need a - // mangling are when they have (effectively) internal linkage or appear - // in a non-inline function in a non-module translation unit. - - Decl *ManglingContextDeclForModule = [&]() { - if (!ManglingContextDecl || [&]() { - // If we must allocate mangling numbers but the - // `ManglingContextDecl` is a local variable, use the `DeclContext` - // containing the lambda expression instead. - VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl); - return Var && Var->isLocalVarDecl(); - }()) - return const_cast<Decl *>(cast<Decl>(DC)); - - return ManglingContextDecl; - }(); - - if (auto *ND = dyn_cast<NamedDecl>(ManglingContextDeclForModule); - ND && (ND->isInNamedModule() || ND->isFromGlobalModule()) && - ND->isExternallyVisible()) { - ManglingContextDecl = ND; - return NonInlineInModulePurview; - } - if (!ManglingContextDecl) return Normal; @@ -364,7 +350,8 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // -- the bodies of inline or templated functions if ((IsInNonspecializedTemplate && !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) || - isInInlineFunction(CurContext)) { + isInInlineFunction(CurContext) || + isNonInlineInModulePurview(ManglingContextDecl, DC)) { while (auto *CD = dyn_cast<CapturedDecl>(DC)) DC = CD->getParent(); return std::make_tuple(&Context.getManglingNumberContext(DC), nullptr); @@ -373,7 +360,6 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { return std::make_tuple(nullptr, nullptr); } - case NonInlineInModulePurview: case Concept: // Concept definitions aren't code generated and thus aren't mangled, // however the ManglingContextDecl is important for the purposes of _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
