@@ -870,6 +870,7 @@ void ASTWriter::WriteBlockInfoBlock() {
870
870
RECORD (WEAK_UNDECLARED_IDENTIFIERS);
871
871
RECORD (PENDING_IMPLICIT_INSTANTIATIONS);
872
872
RECORD (UPDATE_VISIBLE);
873
+ RECORD (DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD);
873
874
RECORD (DECL_UPDATE_OFFSETS);
874
875
RECORD (DECL_UPDATES);
875
876
RECORD (CUDA_SPECIAL_DECL_REFS);
@@ -3029,10 +3030,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
3029
3030
Stream.EmitRecordWithBlob (ConfigMacroAbbrev, Record, CM);
3030
3031
}
3031
3032
3032
- // Emit the initializers, if any.
3033
+ // Emit the reachable initializers.
3034
+ // The initializer may only be unreachable in reduced BMI.
3033
3035
RecordData Inits;
3034
3036
for (Decl *D : Context->getModuleInitializers (Mod))
3035
- Inits.push_back (GetDeclRef (D));
3037
+ if (wasDeclEmitted (D))
3038
+ Inits.push_back (GetDeclRef (D));
3036
3039
if (!Inits.empty ())
3037
3040
Stream.EmitRecord (SUBMODULE_INITIALIZERS, Inits);
3038
3041
@@ -3211,6 +3214,9 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
3211
3214
uint64_t Offset = Stream.GetCurrentBitNo ();
3212
3215
SmallVector<uint32_t , 128 > KindDeclPairs;
3213
3216
for (const auto *D : DC->decls ()) {
3217
+ if (DoneWritingDeclsAndTypes && !wasDeclEmitted (D))
3218
+ continue ;
3219
+
3214
3220
KindDeclPairs.push_back (D->getKind ());
3215
3221
KindDeclPairs.push_back (GetDeclRef (D));
3216
3222
}
@@ -3865,8 +3871,14 @@ class ASTDeclContextNameLookupTrait {
3865
3871
data_type getData (const Coll &Decls) {
3866
3872
unsigned Start = DeclIDs.size ();
3867
3873
for (NamedDecl *D : Decls) {
3868
- DeclIDs.push_back (
3869
- Writer.GetDeclRef (getDeclForLocalLookup (Writer.getLangOpts (), D)));
3874
+ NamedDecl *DeclForLocalLookup =
3875
+ getDeclForLocalLookup (Writer.getLangOpts (), D);
3876
+
3877
+ if (Writer.getDoneWritingDeclsAndTypes () &&
3878
+ !Writer.wasDeclEmitted (DeclForLocalLookup))
3879
+ continue ;
3880
+
3881
+ DeclIDs.push_back (Writer.GetDeclRef (DeclForLocalLookup));
3870
3882
}
3871
3883
return std::make_pair (Start, DeclIDs.size ());
3872
3884
}
@@ -3975,11 +3987,20 @@ bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
3975
3987
DC->hasNeedToReconcileExternalVisibleStorage ();
3976
3988
}
3977
3989
3978
- bool ASTWriter::isLookupResultEntirelyExternal (StoredDeclsList &Result,
3979
- DeclContext *DC) {
3980
- for (auto *D : Result.getLookupResult ())
3981
- if (!getDeclForLocalLookup (getLangOpts (), D)->isFromASTFile ())
3982
- return false ;
3990
+ bool ASTWriter::isLookupResultEntirelyExternalOrUnreachable (
3991
+ StoredDeclsList &Result, DeclContext *DC) {
3992
+ for (auto *D : Result.getLookupResult ()) {
3993
+ auto *LocalD = getDeclForLocalLookup (getLangOpts (), D);
3994
+ if (LocalD->isFromASTFile ())
3995
+ continue ;
3996
+
3997
+ // We can only be sure whether the local declaration is reachable
3998
+ // after we done writing the declarations and types.
3999
+ if (DoneWritingDeclsAndTypes && !wasDeclEmitted (LocalD))
4000
+ continue ;
4001
+
4002
+ return false ;
4003
+ }
3983
4004
3984
4005
return true ;
3985
4006
}
@@ -4017,8 +4038,17 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
4017
4038
// don't need to write an entry for the name at all. If we can't
4018
4039
// write out a lookup set without performing more deserialization,
4019
4040
// just skip this entry.
4020
- if (isLookupResultExternal (Result, DC) &&
4021
- isLookupResultEntirelyExternal (Result, DC))
4041
+ //
4042
+ // Also in reduced BMI, we'd like to avoid writing unreachable
4043
+ // declarations in GMF, so we need to avoid writing declarations
4044
+ // that entirely external or unreachable.
4045
+ //
4046
+ // FIMXE: It looks sufficient to test
4047
+ // isLookupResultEntirelyExternalOrUnreachable here. But due to bug we have
4048
+ // to test isLookupResultExternal here. See
4049
+ // https://github.com/llvm/llvm-project/issues/61065 for details.
4050
+ if ((GeneratingReducedBMI || isLookupResultExternal (Result, DC)) &&
4051
+ isLookupResultEntirelyExternalOrUnreachable (Result, DC))
4022
4052
continue ;
4023
4053
4024
4054
// We also skip empty results. If any of the results could be external and
@@ -4209,9 +4239,15 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
4209
4239
continue ;
4210
4240
}
4211
4241
4212
- for (NamedDecl *ND : Result)
4213
- if (!ND->isFromASTFile ())
4214
- GetDeclRef (ND);
4242
+ for (NamedDecl *ND : Result) {
4243
+ if (ND->isFromASTFile ())
4244
+ continue ;
4245
+
4246
+ if (DoneWritingDeclsAndTypes && !wasDeclEmitted (ND))
4247
+ continue ;
4248
+
4249
+ GetDeclRef (ND);
4250
+ }
4215
4251
}
4216
4252
4217
4253
return 0 ;
@@ -4979,9 +5015,18 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4979
5015
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl ();
4980
5016
4981
5017
// Force all top level declarations to be emitted.
4982
- for (const auto *D : TU->noload_decls ())
4983
- if (!D->isFromASTFile ())
4984
- GetDeclRef (D);
5018
+ //
5019
+ // We start emitting top level declarations from the module purview to
5020
+ // implement the eliding unreachable declaration feature.
5021
+ for (const auto *D : TU->noload_decls ()) {
5022
+ if (D->isFromASTFile ())
5023
+ continue ;
5024
+
5025
+ if (GeneratingReducedBMI && D->isFromExplicitGlobalModule ())
5026
+ continue ;
5027
+
5028
+ GetDeclRef (D);
5029
+ }
4985
5030
4986
5031
// If the translation unit has an anonymous namespace, and we don't already
4987
5032
// have an update block for it, write it as an update block.
@@ -5291,24 +5336,59 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
5291
5336
WriteDecl (Context, DOT.getDecl ());
5292
5337
}
5293
5338
} while (!DeclUpdates.empty ());
5294
- Stream.ExitBlock ();
5295
5339
5296
5340
DoneWritingDeclsAndTypes = true ;
5297
5341
5342
+ // DelayedNamespace is only meaningful in reduced BMI.
5343
+ // See the comments of DelayedNamespace for details.
5344
+ assert (DelayedNamespace.empty () || GeneratingReducedBMI);
5345
+ RecordData DelayedNamespaceRecord;
5346
+ for (NamespaceDecl *NS : DelayedNamespace) {
5347
+ uint64_t LexicalOffset = WriteDeclContextLexicalBlock (Context, NS);
5348
+ uint64_t VisibleOffset = WriteDeclContextVisibleBlock (Context, NS);
5349
+
5350
+ // Write the offset relative to current block.
5351
+ if (LexicalOffset)
5352
+ LexicalOffset -= DeclTypesBlockStartOffset;
5353
+
5354
+ if (VisibleOffset)
5355
+ VisibleOffset -= DeclTypesBlockStartOffset;
5356
+
5357
+ DelayedNamespaceRecord.push_back (getDeclID (NS));
5358
+ DelayedNamespaceRecord.push_back (LexicalOffset);
5359
+ DelayedNamespaceRecord.push_back (VisibleOffset);
5360
+ }
5361
+
5362
+ // The process of writing lexical and visible block for delayed namespace
5363
+ // shouldn't introduce any new decls, types or update to emit.
5364
+ assert (DeclTypesToEmit.empty ());
5365
+ assert (DeclUpdates.empty ());
5366
+
5367
+ Stream.ExitBlock ();
5368
+
5298
5369
// These things can only be done once we've written out decls and types.
5299
5370
WriteTypeDeclOffsets ();
5300
5371
if (!DeclUpdatesOffsetsRecord.empty ())
5301
5372
Stream.EmitRecord (DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
5302
5373
5374
+ if (!DelayedNamespaceRecord.empty ())
5375
+ Stream.EmitRecord (DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD,
5376
+ DelayedNamespaceRecord);
5377
+
5303
5378
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl ();
5304
5379
// Create a lexical update block containing all of the declarations in the
5305
5380
// translation unit that do not come from other AST files.
5306
5381
SmallVector<uint32_t , 128 > NewGlobalKindDeclPairs;
5307
5382
for (const auto *D : TU->noload_decls ()) {
5308
- if (!D->isFromASTFile ()) {
5309
- NewGlobalKindDeclPairs.push_back (D->getKind ());
5310
- NewGlobalKindDeclPairs.push_back (GetDeclRef (D));
5311
- }
5383
+ if (D->isFromASTFile ())
5384
+ continue ;
5385
+
5386
+ // In reduced BMI, skip unreached declarations.
5387
+ if (!wasDeclEmitted (D))
5388
+ continue ;
5389
+
5390
+ NewGlobalKindDeclPairs.push_back (D->getKind ());
5391
+ NewGlobalKindDeclPairs.push_back (GetDeclRef (D));
5312
5392
}
5313
5393
5314
5394
auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
@@ -5817,6 +5897,21 @@ DeclID ASTWriter::getDeclID(const Decl *D) {
5817
5897
return DeclIDs[D];
5818
5898
}
5819
5899
5900
+ bool ASTWriter::wasDeclEmitted (const Decl *D) const {
5901
+ assert (D);
5902
+
5903
+ assert (DoneWritingDeclsAndTypes &&
5904
+ " wasDeclEmitted should only be called after writing declarations" );
5905
+
5906
+ if (D->isFromASTFile ())
5907
+ return true ;
5908
+
5909
+ bool Emitted = DeclIDs.contains (D);
5910
+ assert ((Emitted || GeneratingReducedBMI) &&
5911
+ " The declaration can only be omitted in reduced BMI." );
5912
+ return Emitted;
5913
+ }
5914
+
5820
5915
void ASTWriter::associateDeclWithFile (const Decl *D, DeclID ID) {
5821
5916
assert (ID);
5822
5917
assert (D);
0 commit comments