@@ -330,28 +330,82 @@ namespace clang {
330330 };
331331}
332332
333+ // When building a C++20 module interface unit or a partition unit, a
334+ // strong definition in the module interface is provided by the
335+ // compilation of that unit, not by its users. (Inline variables are still
336+ // emitted in module users.)
337+ static bool shouldVarGenerateHereOnly (const VarDecl *VD) {
338+ if (VD->getStorageDuration () != SD_Static)
339+ return false ;
340+
341+ if (VD->getDescribedVarTemplate ())
342+ return false ;
343+
344+ Module *M = VD->getOwningModule ();
345+ if (!M)
346+ return false ;
347+
348+ M = M->getTopLevelModule ();
349+ ASTContext &Ctx = VD->getASTContext ();
350+ if (!M->isInterfaceOrPartition () &&
351+ (!VD->hasAttr <DLLExportAttr>() ||
352+ !Ctx.getLangOpts ().BuildingPCHWithObjectFile ))
353+ return false ;
354+
355+ return Ctx.GetGVALinkageForVariable (VD) >= GVA_StrongExternal;
356+ }
357+
358+ static bool shouldFunctionGenerateHereOnly (const FunctionDecl *FD) {
359+ if (FD->isDependentContext ())
360+ return false ;
361+
362+ ASTContext &Ctx = FD->getASTContext ();
363+ auto Linkage = Ctx.GetGVALinkageForFunction (FD);
364+ if (Ctx.getLangOpts ().ModulesCodegen ||
365+ (FD->hasAttr <DLLExportAttr>() &&
366+ Ctx.getLangOpts ().BuildingPCHWithObjectFile ))
367+ // Under -fmodules-codegen, codegen is performed for all non-internal,
368+ // non-always_inline functions, unless they are available elsewhere.
369+ if (!FD->hasAttr <AlwaysInlineAttr>() && Linkage != GVA_Internal &&
370+ Linkage != GVA_AvailableExternally)
371+ return true ;
372+
373+ Module *M = FD->getOwningModule ();
374+ if (!M)
375+ return false ;
376+
377+ M = M->getTopLevelModule ();
378+ if (M->isInterfaceOrPartition ())
379+ if (Linkage >= GVA_StrongExternal)
380+ return true ;
381+
382+ return false ;
383+ }
384+
333385bool clang::CanElideDeclDef (const Decl *D) {
334386 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
335- if (FD->isInlined () || FD->isConstexpr ())
336- return false ;
337-
338- if (FD->isDependentContext ())
387+ if (FD->isInlined () || FD->isConstexpr () || FD->isConsteval ())
339388 return false ;
340389
341- if (FD->getTemplateSpecializationKind () == TSK_ImplicitInstantiation)
390+ // If the function should be generated somewhere else, we shouldn't elide
391+ // it.
392+ if (!shouldFunctionGenerateHereOnly (FD))
342393 return false ;
343394 }
344395
345396 if (auto *VD = dyn_cast<VarDecl>(D)) {
346- if (!VD->getDeclContext ()->getRedeclContext ()->isFileContext () ||
347- VD->isInline () || VD->isConstexpr () || isa<ParmVarDecl>(VD) ||
348- // Constant initialized variable may not affect the ABI, but they
349- // may be used in constant evaluation in the frontend, so we have
350- // to remain them.
351- VD->hasConstantInitialization ())
397+ if (VD->getDeclContext ()->isDependentContext ())
352398 return false ;
353399
354- if (VD->getTemplateSpecializationKind () == TSK_ImplicitInstantiation)
400+ // Constant initialized variable may not affect the ABI, but they
401+ // may be used in constant evaluation in the frontend, so we have
402+ // to remain them.
403+ if (VD->hasConstantInitialization () || VD->isConstexpr ())
404+ return false ;
405+
406+ // If the variable should be generated somewhere else, we shouldn't elide
407+ // it.
408+ if (!shouldVarGenerateHereOnly (VD))
355409 return false ;
356410 }
357411
@@ -1183,19 +1237,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
11831237 VarDeclBits.addBits (llvm::to_underlying (D->getLinkageInternal ()),
11841238 /* BitWidth=*/ 3 );
11851239
1186- bool ModulesCodegen = false ;
1187- if (Writer.WritingModule && D->getStorageDuration () == SD_Static &&
1188- !D->getDescribedVarTemplate ()) {
1189- // When building a C++20 module interface unit or a partition unit, a
1190- // strong definition in the module interface is provided by the
1191- // compilation of that unit, not by its users. (Inline variables are still
1192- // emitted in module users.)
1193- ModulesCodegen = (Writer.WritingModule ->isInterfaceOrPartition () ||
1194- (D->hasAttr <DLLExportAttr>() &&
1195- Writer.getLangOpts ().BuildingPCHWithObjectFile )) &&
1196- Record.getASTContext ().GetGVALinkageForVariable (D) >=
1197- GVA_StrongExternal;
1198- }
1240+ bool ModulesCodegen = shouldVarGenerateHereOnly (D);
11991241 VarDeclBits.addBit (ModulesCodegen);
12001242
12011243 VarDeclBits.addBits (D->getStorageClass (), /* BitWidth=*/ 3 );
@@ -3012,32 +3054,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
30123054 Writer->ClearSwitchCaseIDs ();
30133055
30143056 assert (FD->doesThisDeclarationHaveABody ());
3015- bool ModulesCodegen = false ;
3016- if (!FD->isDependentContext ()) {
3017- std::optional<GVALinkage> Linkage;
3018- if (Writer->WritingModule &&
3019- Writer->WritingModule ->isInterfaceOrPartition ()) {
3020- // When building a C++20 module interface unit or a partition unit, a
3021- // strong definition in the module interface is provided by the
3022- // compilation of that unit, not by its users. (Inline functions are still
3023- // emitted in module users.)
3024- Linkage = getASTContext ().GetGVALinkageForFunction (FD);
3025- ModulesCodegen = *Linkage >= GVA_StrongExternal;
3026- }
3027- if (Writer->getLangOpts ().ModulesCodegen ||
3028- (FD->hasAttr <DLLExportAttr>() &&
3029- Writer->getLangOpts ().BuildingPCHWithObjectFile )) {
3030-
3031- // Under -fmodules-codegen, codegen is performed for all non-internal,
3032- // non-always_inline functions, unless they are available elsewhere.
3033- if (!FD->hasAttr <AlwaysInlineAttr>()) {
3034- if (!Linkage)
3035- Linkage = getASTContext ().GetGVALinkageForFunction (FD);
3036- ModulesCodegen =
3037- *Linkage != GVA_Internal && *Linkage != GVA_AvailableExternally;
3038- }
3039- }
3040- }
3057+ bool ModulesCodegen = shouldFunctionGenerateHereOnly (FD);
30413058 Record->push_back (ModulesCodegen);
30423059 if (ModulesCodegen)
30433060 Writer->AddDeclRef (FD, Writer->ModularCodegenDecls );
0 commit comments