aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>2025-03-13 15:00:30 +0800
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>2025-03-13 15:04:06 +0800
commit6345b009c3e58a6cd0eca835d5a935f8784cfda6 (patch)
tree4cefac9c385deee3cf98a4a1fe08adc5a630efe6
parent9e91725fd4d4ee30e98ab2682f93b423590a4ade (diff)
downloadllvm-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.cpp49
-rw-r--r--clang/test/Modules/lambda-in-module-purview-2.cppm22
-rw-r--r--clang/test/Modules/lambda-in-module-purview.cppm17
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;