diff options
author | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2025-03-13 14:17:13 +0800 |
---|---|---|
committer | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2025-03-13 14:20:30 +0800 |
commit | 34f4ee7c0d98cfbee2bfc5cfee72b8090da68dc2 (patch) | |
tree | f12dda2f46f6eb56ab487675ad812df17a000a7e /clang/lib/Serialization/ASTWriterDecl.cpp | |
parent | 1d1f2e8c5be319c91fa696e19a6394fca4e16bea (diff) | |
download | llvm-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.cpp | 119 |
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); |