Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -1537,6 +1537,25 @@ } } + // Handle modules specially to avoid breaking ABI. + // Otherwise it is possible to mangle two different lambda to the same name, + // See issue 52857 for example. + if (!TD->isExternallyVisible() || TD->getOwningModuleForLinkage()) { + // Get a unique id for the anonymous struct. If it is not a real output + // ID doesn't matter so use fake one. + unsigned AnonStructId = NullOut ? 0 : Context.getAnonymousStructId(TD); + + // Mangle it as a source name in the form + // [n] $_ + // where n is the length of the string. + SmallString<8> Str; + Str += "$_"; + Str += llvm::utostr(AnonStructId); + + Out << Str.size(); + Out << Str; + } + if (TD->isExternallyVisible()) { unsigned UnnamedMangle = getASTContext().getManglingNumber(TD); Out << "Ut"; @@ -1544,22 +1563,8 @@ Out << UnnamedMangle - 2; Out << '_'; writeAbiTags(TD, AdditionalAbiTags); - break; } - // Get a unique id for the anonymous struct. If it is not a real output - // ID doesn't matter so use fake one. - unsigned AnonStructId = NullOut ? 0 : Context.getAnonymousStructId(TD); - - // Mangle it as a source name in the form - // [n] $_ - // where n is the length of the string. - SmallString<8> Str; - Str += "$_"; - Str += llvm::utostr(AnonStructId); - - Out << Str.size(); - Out << Str; break; } Index: clang/test/CodeGenCXX/cxx20-lambda-modules.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-lambda-modules.cpp @@ -0,0 +1,18 @@ +// Tests that the lambda in modules would be mangled properly. + +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo "export module test;" >> %t/test.cppm +// RUN: echo "export namespace test {" >> %t/test.cppm +// RUN: echo "auto foo = [] {return 43;};" >> %t/test.cppm +// RUN: echo "auto bar = [] {return 'a';};" >> %t/test.cppm +// RUN: echo "}" >> %t/test.cppm +// RUN: %clang_cc1 -std=c++20 %t/test.cppm -emit-module-interface -o %t/test.pcm +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fprebuilt-module-path=%t -std=c++20 %s -emit-llvm -o - | FileCheck %s +import test; +void use() { + test::foo(); + test::bar(); +} +// CHECK: call noundef i32 @"_ZW4testENK4test3$_0Ut_clEv" +// CHECK: call noundef signext i8 @"_ZW4testENK4test3$_1Ut_clEv"