diff options
author | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2025-03-13 15:00:30 +0800 |
---|---|---|
committer | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2025-03-13 15:04:06 +0800 |
commit | 6345b009c3e58a6cd0eca835d5a935f8784cfda6 (patch) | |
tree | 4cefac9c385deee3cf98a4a1fe08adc5a630efe6 | |
parent | 9e91725fd4d4ee30e98ab2682f93b423590a4ade (diff) | |
download | llvm-6345b009c3e58a6cd0eca835d5a935f8784cfda6.zip llvm-6345b009c3e58a6cd0eca835d5a935f8784cfda6.tar.gz llvm-6345b009c3e58a6cd0eca835d5a935f8784cfda6.tar.bz2 |
[C++20] [Modules] Add mangling number for lambda in non-internal module unit context
Close https://github.com/llvm/llvm-project/issues/59513
Close https://github.com/llvm/llvm-project/issues/110146
As we discussed, this is related to ABI:
https://github.com/itanium-cxx-abi/cxx-abi/issues/186
I was intending to fix this after it gets merged into the ItaniumC++ABI
formally. But it looks like ItaniumC++ABI doesn't update it yet and
there are more issue reports for it.
Luckily Richard had a clear direction guide here though. So I think it
should be good to do this without a formal ItaniumC++ABI wording.
The diff of the patch is slightly larger than it was by a simple
refacoration to simple the control flow a little bit.
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 49 | ||||
-rw-r--r-- | clang/test/Modules/lambda-in-module-purview-2.cppm | 22 | ||||
-rw-r--r-- | clang/test/Modules/lambda-in-module-purview.cppm | 17 |
3 files changed, 75 insertions, 13 deletions
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index ceb32ee..292406f 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -292,7 +292,8 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { DataMember, InlineVariable, TemplatedVariable, - Concept + Concept, + NonInlineInModulePurview } Kind = Normal; bool IsInNonspecializedTemplate = @@ -301,29 +302,50 @@ Sema::getCurrentMangleNumberContext(const DeclContext *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. - if (ManglingContextDecl) { + Kind = [&]() { + if (!ManglingContextDecl) + return Normal; + + if (auto *ND = dyn_cast<NamedDecl>(ManglingContextDecl)) { + // 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. + Module *M = ManglingContextDecl->getOwningModule(); + if (M && M->getTopLevelModule()->isNamedModuleUnit() && + ND->isExternallyVisible()) + return NonInlineInModulePurview; + } + if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) { if (const DeclContext *LexicalDC = Param->getDeclContext()->getLexicalParent()) if (LexicalDC->isRecord()) - Kind = DefaultArgument; + return DefaultArgument; } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) { if (Var->getMostRecentDecl()->isInline()) - Kind = InlineVariable; - else if (Var->getDeclContext()->isRecord() && IsInNonspecializedTemplate) - Kind = TemplatedVariable; - else if (Var->getDescribedVarTemplate()) - Kind = TemplatedVariable; - else if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) { + return InlineVariable; + + if (Var->getDeclContext()->isRecord() && IsInNonspecializedTemplate) + return TemplatedVariable; + + if (Var->getDescribedVarTemplate()) + return TemplatedVariable; + + if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) { if (!VTS->isExplicitSpecialization()) - Kind = TemplatedVariable; + return TemplatedVariable; } } else if (isa<FieldDecl>(ManglingContextDecl)) { - Kind = DataMember; + return DataMember; } else if (isa<ImplicitConceptSpecializationDecl>(ManglingContextDecl)) { - Kind = Concept; + return Concept; } - } + + return Normal; + }(); // Itanium ABI [5.1.7]: // In the following contexts [...] the one-definition rule requires closure @@ -342,6 +364,7 @@ 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 diff --git a/clang/test/Modules/lambda-in-module-purview-2.cppm b/clang/test/Modules/lambda-in-module-purview-2.cppm new file mode 100644 index 0000000..7c971ff --- /dev/null +++ b/clang/test/Modules/lambda-in-module-purview-2.cppm @@ -0,0 +1,22 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify + +//--- lambda.h +auto cmp = [](auto l, auto r) { + return l < r; +}; + +//--- a.cppm +module; +#include "lambda.h" +export module a; +export using ::cmp; + +//--- use.cpp +// expected-no-diagnostics +import a; +auto x = cmp; diff --git a/clang/test/Modules/lambda-in-module-purview.cppm b/clang/test/Modules/lambda-in-module-purview.cppm new file mode 100644 index 0000000..4f76543 --- /dev/null +++ b/clang/test/Modules/lambda-in-module-purview.cppm @@ -0,0 +1,17 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify + +//--- a.cppm +export module a; +export auto cmp = [](auto l, auto r) { + return l < r; +}; + +//--- use.cpp +// expected-no-diagnostics +import a; +auto x = cmp; |