@@ -330,28 +330,82 @@ namespace clang {
330
330
};
331
331
}
332
332
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
+
333
385
bool clang::CanElideDeclDef (const Decl *D) {
334
386
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 ())
339
388
return false ;
340
389
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))
342
393
return false ;
343
394
}
344
395
345
396
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 ())
352
398
return false ;
353
399
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))
355
409
return false ;
356
410
}
357
411
@@ -1183,19 +1237,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
1183
1237
VarDeclBits.addBits (llvm::to_underlying (D->getLinkageInternal ()),
1184
1238
/* BitWidth=*/ 3 );
1185
1239
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);
1199
1241
VarDeclBits.addBit (ModulesCodegen);
1200
1242
1201
1243
VarDeclBits.addBits (D->getStorageClass (), /* BitWidth=*/ 3 );
@@ -3012,32 +3054,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
3012
3054
Writer->ClearSwitchCaseIDs ();
3013
3055
3014
3056
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);
3041
3058
Record->push_back (ModulesCodegen);
3042
3059
if (ModulesCodegen)
3043
3060
Writer->AddDeclRef (FD, Writer->ModularCodegenDecls );
0 commit comments