aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Serialization/ASTWriterDecl.cpp
diff options
context:
space:
mode:
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>2025-03-13 14:17:13 +0800
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>2025-03-13 14:20:30 +0800
commit34f4ee7c0d98cfbee2bfc5cfee72b8090da68dc2 (patch)
treef12dda2f46f6eb56ab487675ad812df17a000a7e /clang/lib/Serialization/ASTWriterDecl.cpp
parent1d1f2e8c5be319c91fa696e19a6394fca4e16bea (diff)
downloadllvm-34f4ee7c0d98cfbee2bfc5cfee72b8090da68dc2.zip
llvm-34f4ee7c0d98cfbee2bfc5cfee72b8090da68dc2.tar.gz
llvm-34f4ee7c0d98cfbee2bfc5cfee72b8090da68dc2.tar.bz2
[C++20] [Modules] Merge codes to decide if we should generate decl
There are two piece of codes in ASTWriterDecl to decide whether or not we should generate a function or a variable in current module unit (or PCH with object file extension, which is rarely used). One is in Visit*Decl and One is in `CanElideDef`. Since they are similar it should be better to merge them. This was meant to be a NFC patch. But it seems it helped me to find an existing bug.
Diffstat (limited to 'clang/lib/Serialization/ASTWriterDecl.cpp')
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp119
1 files changed, 68 insertions, 51 deletions
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 0cb9c4d..7014d7d 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -330,28 +330,82 @@ namespace clang {
};
}
+// When building a C++20 module interface unit or a partition unit, a
+// strong definition in the module interface is provided by the
+// compilation of that unit, not by its users. (Inline variables are still
+// emitted in module users.)
+static bool shouldVarGenerateHereOnly(const VarDecl *VD) {
+ if (VD->getStorageDuration() != SD_Static)
+ return false;
+
+ if (VD->getDescribedVarTemplate())
+ return false;
+
+ Module *M = VD->getOwningModule();
+ if (!M)
+ return false;
+
+ M = M->getTopLevelModule();
+ ASTContext &Ctx = VD->getASTContext();
+ if (!M->isInterfaceOrPartition() &&
+ (!VD->hasAttr<DLLExportAttr>() ||
+ !Ctx.getLangOpts().BuildingPCHWithObjectFile))
+ return false;
+
+ return Ctx.GetGVALinkageForVariable(VD) >= GVA_StrongExternal;
+}
+
+static bool shouldFunctionGenerateHereOnly(const FunctionDecl *FD) {
+ if (FD->isDependentContext())
+ return false;
+
+ ASTContext &Ctx = FD->getASTContext();
+ auto Linkage = Ctx.GetGVALinkageForFunction(FD);
+ if (Ctx.getLangOpts().ModulesCodegen ||
+ (FD->hasAttr<DLLExportAttr>() &&
+ Ctx.getLangOpts().BuildingPCHWithObjectFile))
+ // Under -fmodules-codegen, codegen is performed for all non-internal,
+ // non-always_inline functions, unless they are available elsewhere.
+ if (!FD->hasAttr<AlwaysInlineAttr>() && Linkage != GVA_Internal &&
+ Linkage != GVA_AvailableExternally)
+ return true;
+
+ Module *M = FD->getOwningModule();
+ if (!M)
+ return false;
+
+ M = M->getTopLevelModule();
+ if (M->isInterfaceOrPartition())
+ if (Linkage >= GVA_StrongExternal)
+ return true;
+
+ return false;
+}
+
bool clang::CanElideDeclDef(const Decl *D) {
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isInlined() || FD->isConstexpr())
- return false;
-
- if (FD->isDependentContext())
+ if (FD->isInlined() || FD->isConstexpr() || FD->isConsteval())
return false;
- if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ // If the function should be generated somewhere else, we shouldn't elide
+ // it.
+ if (!shouldFunctionGenerateHereOnly(FD))
return false;
}
if (auto *VD = dyn_cast<VarDecl>(D)) {
- if (!VD->getDeclContext()->getRedeclContext()->isFileContext() ||
- VD->isInline() || VD->isConstexpr() || isa<ParmVarDecl>(VD) ||
- // Constant initialized variable may not affect the ABI, but they
- // may be used in constant evaluation in the frontend, so we have
- // to remain them.
- VD->hasConstantInitialization())
+ if (VD->getDeclContext()->isDependentContext())
return false;
- if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ // Constant initialized variable may not affect the ABI, but they
+ // may be used in constant evaluation in the frontend, so we have
+ // to remain them.
+ if (VD->hasConstantInitialization() || VD->isConstexpr())
+ return false;
+
+ // If the variable should be generated somewhere else, we shouldn't elide
+ // it.
+ if (!shouldVarGenerateHereOnly(VD))
return false;
}
@@ -1183,19 +1237,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
VarDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()),
/*BitWidth=*/3);
- bool ModulesCodegen = false;
- if (Writer.WritingModule && D->getStorageDuration() == SD_Static &&
- !D->getDescribedVarTemplate()) {
- // When building a C++20 module interface unit or a partition unit, a
- // strong definition in the module interface is provided by the
- // compilation of that unit, not by its users. (Inline variables are still
- // emitted in module users.)
- ModulesCodegen = (Writer.WritingModule->isInterfaceOrPartition() ||
- (D->hasAttr<DLLExportAttr>() &&
- Writer.getLangOpts().BuildingPCHWithObjectFile)) &&
- Record.getASTContext().GetGVALinkageForVariable(D) >=
- GVA_StrongExternal;
- }
+ bool ModulesCodegen = shouldVarGenerateHereOnly(D);
VarDeclBits.addBit(ModulesCodegen);
VarDeclBits.addBits(D->getStorageClass(), /*BitWidth=*/3);
@@ -3012,32 +3054,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
Writer->ClearSwitchCaseIDs();
assert(FD->doesThisDeclarationHaveABody());
- bool ModulesCodegen = false;
- if (!FD->isDependentContext()) {
- std::optional<GVALinkage> Linkage;
- if (Writer->WritingModule &&
- Writer->WritingModule->isInterfaceOrPartition()) {
- // When building a C++20 module interface unit or a partition unit, a
- // strong definition in the module interface is provided by the
- // compilation of that unit, not by its users. (Inline functions are still
- // emitted in module users.)
- Linkage = getASTContext().GetGVALinkageForFunction(FD);
- ModulesCodegen = *Linkage >= GVA_StrongExternal;
- }
- if (Writer->getLangOpts().ModulesCodegen ||
- (FD->hasAttr<DLLExportAttr>() &&
- Writer->getLangOpts().BuildingPCHWithObjectFile)) {
-
- // Under -fmodules-codegen, codegen is performed for all non-internal,
- // non-always_inline functions, unless they are available elsewhere.
- if (!FD->hasAttr<AlwaysInlineAttr>()) {
- if (!Linkage)
- Linkage = getASTContext().GetGVALinkageForFunction(FD);
- ModulesCodegen =
- *Linkage != GVA_Internal && *Linkage != GVA_AvailableExternally;
- }
- }
- }
+ bool ModulesCodegen = shouldFunctionGenerateHereOnly(FD);
Record->push_back(ModulesCodegen);
if (ModulesCodegen)
Writer->AddDeclRef(FD, Writer->ModularCodegenDecls);