Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix lazy loading of template specializations #13139

Merged
merged 6 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions interpreter/cling/lib/Interpreter/DeclUnloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -941,8 +941,8 @@ bool DeclUnloader::VisitRedeclarable(clang::Redeclarable<T>* R, DeclContext* DC)
bool Successful = true;

// Remove specializations:
for (FunctionTemplateDecl::spec_iterator I = FTD->spec_begin(),
E = FTD->spec_end(); I != E; ++I)
for (FunctionTemplateDecl::spec_iterator I = FTD->loaded_spec_begin(),
E = FTD->loaded_spec_end(); I != E; ++I)
Successful &= Visit(*I);

Successful &= VisitRedeclarableTemplateDecl(FTD);
Expand All @@ -954,8 +954,8 @@ bool DeclUnloader::VisitRedeclarable(clang::Redeclarable<T>* R, DeclContext* DC)
// ClassTemplateDecl: TemplateDecl, Redeclarable
bool Successful = true;
// Remove specializations:
for (ClassTemplateDecl::spec_iterator I = CTD->spec_begin(),
E = CTD->spec_end(); I != E; ++I)
for (ClassTemplateDecl::spec_iterator I = CTD->loaded_spec_begin(),
E = CTD->loaded_spec_end(); I != E; ++I)
Successful &= Visit(*I);

Successful &= VisitRedeclarableTemplateDecl(CTD);
Expand Down
2 changes: 2 additions & 0 deletions interpreter/cling/lib/Interpreter/LookupHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,8 @@ namespace cling {
llvm::StringRef("func.prototype.file"),
diagOnOff);

// ParseTypeName might trigger deserialization.
Interpreter::PushTransactionRAII TforDeser(Interp);
unsigned int nargs = 0;
while (P.getCurToken().isNot(tok::eof)) {
TypeResult Res(P.ParseTypeName());
Expand Down
45 changes: 43 additions & 2 deletions interpreter/llvm-project/clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -828,8 +828,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,

void loadLazySpecializationsImpl(bool OnlyPartial = false) const;

///\returns true if any lazy specialization was loaded.
bool loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args,
void loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args,
TemplateParameterList *TPL = nullptr) const;

Decl *loadLazySpecializationImpl(LazySpecializationInfo &LazySpecInfo) const;
Expand Down Expand Up @@ -1119,6 +1118,20 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
return makeSpecIterator(getSpecializations(), true);
}

/// All specializations that that have already been loaded, ie avoiding
/// deserialization of lazily registered specializations.
spec_range loaded_specializations() const {
return spec_range(loaded_spec_begin(), loaded_spec_end());
}

spec_iterator loaded_spec_begin() const {
return makeSpecIterator(getCommonPtr()->Specializations, false);
}

spec_iterator loaded_spec_end() const {
return makeSpecIterator(getCommonPtr()->Specializations, true);
}

/// Retrieve the "injected" template arguments that correspond to the
/// template parameters of this function template.
///
Expand Down Expand Up @@ -2448,6 +2461,20 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
return makeSpecIterator(getSpecializations(), true);
}

/// All specializations that that have already been loaded, ie avoiding
/// deserialization of lazily registered specializations.
spec_range loaded_specializations() const {
return spec_range(loaded_spec_begin(), loaded_spec_end());
}

spec_iterator loaded_spec_begin() const {
return makeSpecIterator(getCommonPtr()->Specializations, false);
}

spec_iterator loaded_spec_end() const {
return makeSpecIterator(getCommonPtr()->Specializations, true);
}

// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ClassTemplate; }
Expand Down Expand Up @@ -3251,6 +3278,20 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
return makeSpecIterator(getSpecializations(), true);
}

/// All specializations that that have already been loaded, ie avoiding
/// deserialization of lazily registered specializations.
spec_range loaded_specializations() const {
return spec_range(loaded_spec_begin(), loaded_spec_end());
}

spec_iterator loaded_spec_begin() const {
return makeSpecIterator(getCommonPtr()->Specializations, false);
}

spec_iterator loaded_spec_end() const {
return makeSpecIterator(getCommonPtr()->Specializations, true);
}

// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == VarTemplate; }
Expand Down
21 changes: 12 additions & 9 deletions interpreter/llvm-project/clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,19 +309,17 @@ Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl(
return getASTContext().getExternalSource()->GetExternalDecl(ID);
}

bool
void
RedeclarableTemplateDecl::loadLazySpecializationsImpl(ArrayRef<TemplateArgument>
Args,
TemplateParameterList *TPL) const {
bool LoadedSpecialization = false;
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
if (auto *Specs = CommonBasePtr->LazySpecializations) {
unsigned Hash = TemplateArgumentList::ComputeODRHash(Args);
for (uint32_t I = 0, N = Specs[0].DeclID; I != N; ++I)
if (Specs[I+1].ODRHash && Specs[I+1].ODRHash == Hash)
LoadedSpecialization |= (bool)loadLazySpecializationImpl(Specs[I+1]);
(void)loadLazySpecializationImpl(Specs[I+1]);
}
return LoadedSpecialization;
}

template<class EntryType, typename... ProfileArguments>
Expand All @@ -331,7 +329,7 @@ RedeclarableTemplateDecl::findSpecializationImpl(
ProfileArguments&&... ProfileArgs) {
using SETraits = SpecEntryTraits<EntryType>;

(void)loadLazySpecializationsImpl(std::forward<ProfileArguments>(ProfileArgs)...);
loadLazySpecializationsImpl(std::forward<ProfileArguments>(ProfileArgs)...);

llvm::FoldingSetNodeID ID;
EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)...,
Expand All @@ -349,8 +347,11 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
if (InsertPos) {
#ifndef NDEBUG
auto Args = SETraits::getTemplateArgs(Entry);
assert(!loadLazySpecializationsImpl(Args) &&
"Specialization is already registered as lazy");
// Due to hash collisions, it can happen that we load another template
// specialization with the same hash. This is fine, as long as the next
// call to findSpecializationImpl does not find a matching Decl for the
// template arguments.
loadLazySpecializationsImpl(Args);
void *CorrectInsertPos;
assert(!findSpecializationImpl(Specializations, CorrectInsertPos, Args) &&
InsertPos == CorrectInsertPos &&
Expand Down Expand Up @@ -518,7 +519,8 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {
ClassTemplateSpecializationDecl *
ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void *&InsertPos) {
return findSpecializationImpl(getSpecializations(), InsertPos, Args);
auto *Common = getCommonPtr();
return findSpecializationImpl(Common->Specializations, InsertPos, Args);
}

void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
Expand Down Expand Up @@ -1235,7 +1237,8 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
VarTemplateSpecializationDecl *
VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void *&InsertPos) {
return findSpecializationImpl(getSpecializations(), InsertPos, Args);
auto *Common = getCommonPtr();
return findSpecializationImpl(Common->Specializations, InsertPos, Args);
}

void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
Expand Down
18 changes: 2 additions & 16 deletions interpreter/llvm-project/clang/lib/AST/ODRHash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,22 +136,8 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
}

void ODRHash::AddTemplateName(TemplateName Name) {
auto Kind = Name.getKind();
ID.AddInteger(Kind);

switch (Kind) {
case TemplateName::Template:
AddDecl(Name.getAsTemplateDecl());
break;
// TODO: Support these cases.
case TemplateName::OverloadedTemplate:
case TemplateName::AssumedTemplate:
case TemplateName::QualifiedTemplate:
case TemplateName::DependentTemplate:
case TemplateName::SubstTemplateTemplateParm:
case TemplateName::SubstTemplateTemplateParmPack:
break;
}
if (auto *TD = Name.getAsTemplateDecl())
AddDecl(TD);
}

void ODRHash::AddTemplateArgument(TemplateArgument TA) {
Expand Down
2 changes: 1 addition & 1 deletion interpreter/llvm-project/llvm-project.tag
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ROOT-llvm13-20230703-01
ROOT-llvm13-20230704-01