llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Mihai Zegheru (mihaizegheru) <details> <summary>Changes</summary> Fix lambda mangling collisions in function templates in named modules. The `D == RD` branch of `mangleLocalName()` omitted closure prefixes, allowing lambdas with the same mangling number in different contexts to produce identical names. Use `mangleNestedNameWithClosurePrefix()` to preserve the prefix without repeating the enclosing function’s encoding. Add regression coverage for ordinary and generic lambdas, including mixed static/non-static locals and two static locals. Fixes #<!-- -->234701. --- Full diff: https://github.com/llvm/llvm-project/pull/235458.diff 2 Files Affected: - (modified) clang/lib/AST/ItaniumMangle.cpp (+5-1) - (added) clang/test/CodeGenCXX/mangle-lambda-static-local-module.cpp (+46) ``````````diff diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 93ba1519518d2c..95ab08ddb6931a 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1949,7 +1949,11 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, // Mangle the name relative to the closest enclosing function. // equality ok because RD derived from ND above if (D == RD) { - mangleUnqualifiedName(RD, DC, AdditionalAbiTags); + const NamedDecl *PrefixND = getClosurePrefix(RD); + if (PrefixND && !isCompatibleWith(LangOptions::ClangABI::Ver18)) + mangleNestedNameWithClosurePrefix(GD, PrefixND, AdditionalAbiTags, /*NoFunction=*/true); + else + mangleUnqualifiedName(RD, DC, AdditionalAbiTags); } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { if (const NamedDecl *PrefixND = getClosurePrefix(BD)) mangleClosurePrefix(PrefixND, true /*NoFunction*/); diff --git a/clang/test/CodeGenCXX/mangle-lambda-static-local-module.cpp b/clang/test/CodeGenCXX/mangle-lambda-static-local-module.cpp new file mode 100644 index 00000000000000..5885a62f0593e2 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-lambda-static-local-module.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +export module mod; + +template <class F> struct Iterator { + F fn; + + decltype(auto) operator*() { + return fn(char{}); + } +}; + +template <typename> void bad_function() { + auto lam1 = [](char n) { return 0; }; + static auto lam2 = [](char n) { return n; }; + + *Iterator{lam1}; + *Iterator{lam2}; +} + +template <typename> int both_static() { + static auto lam1 = [](char) { return 1; }; + static auto lam2 = [](char) { return 2; }; + + return *Iterator{lam1} + *Iterator{lam2}; +} + +template <typename> int both_generic() { + static constexpr auto lam1 = [](auto n) { return 0; }; + static constexpr auto lam2 = [](auto n) { return n; }; + + return *Iterator{lam1} + *Iterator{lam2}; +} + +int repro() { + bad_function<int>(); + return both_static<int>() + both_generic<int>(); +} + +// CHECK-DAG: define{{.*}} i32 @_ZNW3mod8IteratorIZS_12bad_functionIiEvvEUlcE_EdeEv( +// CHECK-DAG: define{{.*}} i8 @_ZNW3mod8IteratorIZS_12bad_functionIiEvvEN4lam2MUlcE_EEdeEv( +// CHECK-DAG: define{{.*}} i32 @_ZNW3mod8IteratorIZS_11both_staticIiEivEN4lam1MUlcE_EEdeEv( +// CHECK-DAG: define{{.*}} i32 @_ZNW3mod8IteratorIZS_11both_staticIiEivEN4lam2MUlcE_EEdeEv( +// CHECK-DAG: define{{.*}} i32 @_ZNW3mod8IteratorIZS_12both_genericIiEivEN4lam1MUlT_E_EEdeEv( +// CHECK-DAG: define{{.*}} i8 @_ZNW3mod8IteratorIZS_12both_genericIiEivEN4lam2MUlT_E_EEdeEv( \ No newline at end of file `````````` </details> https://github.com/llvm/llvm-project/pull/235458 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
