Skip to content

Commit 1d288e7

Browse files
committed
[Serialization] Code cleanups and polish 83233
1 parent 03e7d56 commit 1d288e7

14 files changed

+87
-234
lines changed

clang/include/clang/AST/DeclTemplate.h

+9-31
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ class TemplateArgumentList final
256256
TemplateArgumentList(const TemplateArgumentList &) = delete;
257257
TemplateArgumentList &operator=(const TemplateArgumentList &) = delete;
258258

259-
/// Create hash for the given arguments.
260-
static unsigned ComputeODRHash(ArrayRef<TemplateArgument> Args);
259+
/// Create stable hash for the given arguments across compiler invocations.
260+
static unsigned ComputeStableHash(ArrayRef<TemplateArgument> Args);
261261

262262
/// Create a new template argument list that copies the given set of
263263
/// template arguments.
@@ -733,25 +733,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
733733
}
734734

735735
void anchor() override;
736-
struct LazySpecializationInfo {
737-
uint32_t DeclID = ~0U;
738-
unsigned ODRHash = ~0U;
739-
bool IsPartial = false;
740-
LazySpecializationInfo(uint32_t ID, unsigned Hash = ~0U,
741-
bool Partial = false)
742-
: DeclID(ID), ODRHash(Hash), IsPartial(Partial) {}
743-
LazySpecializationInfo() {}
744-
bool operator<(const LazySpecializationInfo &Other) const {
745-
return DeclID < Other.DeclID;
746-
}
747-
bool operator==(const LazySpecializationInfo &Other) const {
748-
assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
749-
"Hashes differ!");
750-
assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
751-
"Both must be the same kinds!");
752-
return DeclID == Other.DeclID;
753-
}
754-
};
755736

756737
protected:
757738
template <typename EntryType> struct SpecEntryTraits {
@@ -795,16 +776,20 @@ class RedeclarableTemplateDecl : public TemplateDecl,
795776

796777
void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
797778

798-
void loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args,
779+
bool loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args,
799780
TemplateParameterList *TPL = nullptr) const;
800781

801-
Decl *loadLazySpecializationImpl(LazySpecializationInfo &LazySpecInfo) const;
802-
803782
template <class EntryType, typename ...ProfileArguments>
804783
typename SpecEntryTraits<EntryType>::DeclType*
805784
findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
806785
void *&InsertPos, ProfileArguments &&...ProfileArgs);
807786

787+
template <class EntryType, typename... ProfileArguments>
788+
typename SpecEntryTraits<EntryType>::DeclType *
789+
findSpecializationLocally(llvm::FoldingSetVector<EntryType> &Specs,
790+
void *&InsertPos,
791+
ProfileArguments &&...ProfileArgs);
792+
808793
template <class Derived, class EntryType>
809794
void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
810795
EntryType *Entry, void *InsertPos);
@@ -820,13 +805,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
820805
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
821806
InstantiatedFromMember;
822807

823-
/// If non-null, points to an array of specializations (including
824-
/// partial specializations) known only by their external declaration IDs.
825-
///
826-
/// The first value in the array is the number of specializations/partial
827-
/// specializations that follow.
828-
LazySpecializationInfo *LazySpecializations = nullptr;
829-
830808
/// The set of "injected" template arguments used within this
831809
/// template.
832810
///

clang/include/clang/AST/ExternalASTSource.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
157157

158158
/// Load all the specializations for the Decl \param D with the same template
159159
/// args specified by \param TemplateArgs.
160-
virtual void
160+
///
161+
/// Return true if any new specializations get loaded. Return false otherwise.
162+
virtual bool
161163
LoadExternalSpecializations(const Decl *D,
162164
ArrayRef<TemplateArgument> TemplateArgs);
163165

clang/include/clang/Sema/MultiplexExternalSemaSource.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
9999

100100
void LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;
101101

102-
void
102+
bool
103103
LoadExternalSpecializations(const Decl *D,
104104
ArrayRef<TemplateArgument> TemplateArgs) override;
105105

clang/include/clang/Serialization/ASTBitCodes.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ enum ASTRecordTypes {
699699
/// recorded in a preamble.
700700
PP_ASSUME_NONNULL_LOC = 67,
701701

702-
UPDATE_SPECIALIZATION = 68,
702+
CXX_ADDED_TEMPLATE_SPECIALIZATION = 68,
703703
};
704704

705705
/// Record types used within a source manager block.

clang/include/clang/Serialization/ASTReader.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -2006,7 +2006,7 @@ class ASTReader
20062006

20072007
void LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;
20082008

2009-
void
2009+
bool
20102010
LoadExternalSpecializations(const Decl *D,
20112011
ArrayRef<TemplateArgument> TemplateArgs) override;
20122012

clang/lib/AST/DeclTemplate.cpp

+40-45
Original file line numberDiff line numberDiff line change
@@ -342,60 +342,24 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
342342
ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
343343
OnlyPartial);
344344
return;
345-
346-
// Grab the most recent declaration to ensure we've loaded any lazy
347-
// redeclarations of this template.
348-
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
349-
if (auto *Specs = CommonBasePtr->LazySpecializations) {
350-
if (!OnlyPartial)
351-
CommonBasePtr->LazySpecializations = nullptr;
352-
for (uint32_t I = 0, N = Specs[0].DeclID; I != N; ++I) {
353-
// Skip over already loaded specializations.
354-
if (!Specs[I + 1].ODRHash)
355-
continue;
356-
if (!OnlyPartial || Specs[I + 1].IsPartial)
357-
(void)loadLazySpecializationImpl(Specs[I + 1]);
358-
}
359-
}
360-
}
361-
362-
Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl(
363-
LazySpecializationInfo &LazySpecInfo) const {
364-
llvm_unreachable("We don't use LazySpecializationInfo any more");
365-
366-
uint32_t ID = LazySpecInfo.DeclID;
367-
assert(ID && "Loading already loaded specialization!");
368-
// Note that we loaded the specialization.
369-
LazySpecInfo.DeclID = LazySpecInfo.ODRHash = LazySpecInfo.IsPartial = 0;
370-
return getASTContext().getExternalSource()->GetExternalDecl(ID);
371345
}
372346

373-
void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
347+
bool RedeclarableTemplateDecl::loadLazySpecializationsImpl(
374348
ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
375349
auto *ExternalSource = getASTContext().getExternalSource();
376350
if (!ExternalSource)
377-
return;
378-
379-
ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(), Args);
380-
return;
351+
return false;
381352

382-
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
383-
if (auto *Specs = CommonBasePtr->LazySpecializations) {
384-
unsigned Hash = TemplateArgumentList::ComputeODRHash(Args);
385-
for (uint32_t I = 0, N = Specs[0].DeclID; I != N; ++I)
386-
if (Specs[I + 1].ODRHash && Specs[I + 1].ODRHash == Hash)
387-
(void)loadLazySpecializationImpl(Specs[I + 1]);
388-
}
353+
return ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
354+
Args);
389355
}
390356

391-
template<class EntryType, typename... ProfileArguments>
357+
template <class EntryType, typename... ProfileArguments>
392358
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
393-
RedeclarableTemplateDecl::findSpecializationImpl(
359+
RedeclarableTemplateDecl::findSpecializationLocally(
394360
llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos,
395-
ProfileArguments&&... ProfileArgs) {
396-
using SETraits = SpecEntryTraits<EntryType>;
397-
398-
loadLazySpecializationsImpl(std::forward<ProfileArguments>(ProfileArgs)...);
361+
ProfileArguments &&...ProfileArgs) {
362+
using SETraits = RedeclarableTemplateDecl::SpecEntryTraits<EntryType>;
399363

400364
llvm::FoldingSetNodeID ID;
401365
EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)...,
@@ -404,6 +368,24 @@ RedeclarableTemplateDecl::findSpecializationImpl(
404368
return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
405369
}
406370

371+
template <class EntryType, typename... ProfileArguments>
372+
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
373+
RedeclarableTemplateDecl::findSpecializationImpl(
374+
llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos,
375+
ProfileArguments &&...ProfileArgs) {
376+
377+
if (auto *Found = findSpecializationLocally(
378+
Specs, InsertPos, std::forward<ProfileArguments>(ProfileArgs)...))
379+
return Found;
380+
381+
if (!loadLazySpecializationsImpl(
382+
std::forward<ProfileArguments>(ProfileArgs)...))
383+
return nullptr;
384+
385+
return findSpecializationLocally(
386+
Specs, InsertPos, std::forward<ProfileArguments>(ProfileArgs)...);
387+
}
388+
407389
template<class Derived, class EntryType>
408390
void RedeclarableTemplateDecl::addSpecializationImpl(
409391
llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
@@ -939,7 +921,20 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
939921
return new (Mem) TemplateArgumentList(Args);
940922
}
941923

942-
unsigned TemplateArgumentList::ComputeODRHash(ArrayRef<TemplateArgument> Args) {
924+
unsigned
925+
TemplateArgumentList::ComputeStableHash(ArrayRef<TemplateArgument> Args) {
926+
// FIXME: ODR hashing may not be the best mechanism to hash the template
927+
// arguments. ODR hashing is (or perhaps, should be) about determining whether
928+
// two things are spelled the same way and have the same meaning (as required
929+
// by the C++ ODR), whereas what we want here is whether they have the same
930+
// meaning regardless of spelling. Maybe we can get away with reusing ODR
931+
// hashing anyway, on the basis that any canonical, non-dependent template
932+
// argument should have the same (invented) spelling in every translation
933+
// unit, but it is not sure that's true in all cases. There may still be cases
934+
// where the canonical type includes some aspect of "whatever we saw first",
935+
// in which case the ODR hash can differ across translation units for
936+
// non-dependent, canonical template arguments that are spelled differently
937+
// but have the same meaning. But it is not easy to raise examples.
943938
ODRHash Hasher;
944939
for (TemplateArgument TA : Args)
945940
Hasher.AddTemplateArgument(TA);

clang/lib/AST/ExternalASTSource.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,10 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
102102

103103
void ExternalASTSource::LoadExternalSpecializations(const Decl *D, bool) {}
104104

105-
void ExternalASTSource::LoadExternalSpecializations(
106-
const Decl *D, ArrayRef<TemplateArgument>) {}
105+
bool ExternalASTSource::LoadExternalSpecializations(
106+
const Decl *D, ArrayRef<TemplateArgument>) {
107+
return false;
108+
}
107109

108110
void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {}
109111

clang/lib/Sema/MultiplexExternalSemaSource.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,13 @@ void MultiplexExternalSemaSource::LoadExternalSpecializations(
121121
Sources[i]->LoadExternalSpecializations(D, OnlyPartial);
122122
}
123123

124-
void MultiplexExternalSemaSource::LoadExternalSpecializations(
124+
bool MultiplexExternalSemaSource::LoadExternalSpecializations(
125125
const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) {
126+
bool AnyNewSpecsLoaded = false;
126127
for (size_t i = 0; i < Sources.size(); ++i)
127-
Sources[i]->LoadExternalSpecializations(D, TemplateArgs);
128+
AnyNewSpecsLoaded |=
129+
Sources[i]->LoadExternalSpecializations(D, TemplateArgs);
130+
return AnyNewSpecsLoaded;
128131
}
129132

130133
void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC){

clang/lib/Serialization/ASTCommon.h

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ namespace serialization {
2323

2424
enum DeclUpdateKind {
2525
UPD_CXX_ADDED_IMPLICIT_MEMBER,
26-
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
2726
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
2827
UPD_CXX_ADDED_FUNCTION_DEFINITION,
2928
UPD_CXX_ADDED_VAR_DEFINITION,

clang/lib/Serialization/ASTReader.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -3499,7 +3499,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
34993499
break;
35003500
}
35013501

3502-
case UPDATE_SPECIALIZATION: {
3502+
case CXX_ADDED_TEMPLATE_SPECIALIZATION: {
35033503
unsigned Idx = 0;
35043504
serialization::DeclID ID = ReadDeclID(F, Record, Idx);
35053505
auto *Data = (const unsigned char *)Blob.data();
@@ -7964,23 +7964,30 @@ void ASTReader::LoadExternalSpecializations(const Decl *D, bool OnlyPartial) {
79647964
GetDecl(Info.ID);
79657965
}
79667966

7967-
void ASTReader::LoadExternalSpecializations(
7967+
bool ASTReader::LoadExternalSpecializations(
79687968
const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) {
79697969
assert(D);
79707970

79717971
auto It = SpecializationsLookups.find(D);
79727972
if (It == SpecializationsLookups.end())
7973-
return;
7973+
return false;
79747974

79757975
Deserializing LookupResults(this);
7976-
auto HashValue = TemplateArgumentList::ComputeODRHash(TemplateArgs);
7976+
auto HashValue = TemplateArgumentList::ComputeStableHash(TemplateArgs);
79777977

79787978
// Get Decl may violate the iterator from SpecializationsLookups
79797979
llvm::SmallVector<serialization::reader::LazySpecializationInfo, 8> Infos =
79807980
It->second.Table.find(HashValue);
79817981

7982-
for (auto &Info : Infos)
7982+
bool NewSpecsFound = false;
7983+
for (auto &Info : Infos) {
7984+
if (GetExistingDecl(Info.ID))
7985+
continue;
7986+
NewSpecsFound = true;
79837987
GetDecl(Info.ID);
7988+
}
7989+
7990+
return NewSpecsFound;
79847991
}
79857992

79867993
void ASTReader::FindExternalLexicalDecls(

0 commit comments

Comments
 (0)