Hide FunctionTemplateDecl's specializations folding set as implementation detail and introduce
FunctionTemplateDecl::findSpecialization. Redeclarations of specializations will not cause the previous decl to be removed from the set, the set will keep the canonical decl. findSpecialization will return the most recent redeclaration. llvm-svn: 108834
This commit is contained in:
parent
c1624e9eda
commit
dde5790562
|
@ -522,6 +522,20 @@ protected:
|
||||||
/// may implicitly allocate memory for the common pointer.
|
/// may implicitly allocate memory for the common pointer.
|
||||||
Common *getCommonPtr();
|
Common *getCommonPtr();
|
||||||
|
|
||||||
|
/// \brief Retrieve the set of function template specializations of this
|
||||||
|
/// function template.
|
||||||
|
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
|
||||||
|
return getCommonPtr()->Specializations;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void FunctionDecl::setFunctionTemplateSpecialization(
|
||||||
|
FunctionTemplateDecl *Template,
|
||||||
|
const TemplateArgumentList *TemplateArgs,
|
||||||
|
void *InsertPos,
|
||||||
|
TemplateSpecializationKind TSK,
|
||||||
|
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||||
|
SourceLocation PointOfInstantiation);
|
||||||
|
|
||||||
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||||
TemplateParameterList *Params, NamedDecl *Decl)
|
TemplateParameterList *Params, NamedDecl *Decl)
|
||||||
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
|
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
|
||||||
|
@ -535,11 +549,10 @@ public:
|
||||||
return static_cast<FunctionDecl*>(TemplatedDecl);
|
return static_cast<FunctionDecl*>(TemplatedDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the set of function template specializations of this
|
/// \brief Return the specialization with the provided arguments if it exists,
|
||||||
/// function template.
|
/// otherwise return the insertion point.
|
||||||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
|
FunctionDecl *findSpecialization(const TemplateArgument *Args,
|
||||||
return getCommonPtr()->Specializations;
|
unsigned NumArgs, void *&InsertPos);
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this function template, or
|
/// \brief Retrieve the previous declaration of this function template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
|
|
|
@ -1400,14 +1400,15 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
|
||||||
if (InsertPos)
|
if (InsertPos)
|
||||||
Template->getSpecializations().InsertNode(Info, InsertPos);
|
Template->getSpecializations().InsertNode(Info, InsertPos);
|
||||||
else {
|
else {
|
||||||
// Try to insert the new node. If there is an existing node, remove it
|
// Try to insert the new node. If there is an existing node, leave it, the
|
||||||
// first.
|
// set will contain the canonical decls while
|
||||||
|
// FunctionTemplateDecl::findSpecialization will return
|
||||||
|
// the most recent redeclarations.
|
||||||
FunctionTemplateSpecializationInfo *Existing
|
FunctionTemplateSpecializationInfo *Existing
|
||||||
= Template->getSpecializations().GetOrInsertNode(Info);
|
= Template->getSpecializations().GetOrInsertNode(Info);
|
||||||
if (Existing) {
|
(void)Existing;
|
||||||
Template->getSpecializations().RemoveNode(Existing);
|
assert((!Existing || Existing->Function->isCanonicalDecl()) &&
|
||||||
Template->getSpecializations().GetOrInsertNode(Info);
|
"Set is supposed to only contain canonical decls");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,16 @@ void FunctionTemplateDecl::Destroy(ASTContext &C) {
|
||||||
Decl::Destroy(C);
|
Decl::Destroy(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctionDecl *
|
||||||
|
FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
|
||||||
|
unsigned NumArgs, void *&InsertPos) {
|
||||||
|
llvm::FoldingSetNodeID ID;
|
||||||
|
FunctionTemplateSpecializationInfo::Profile(ID,Args,NumArgs, getASTContext());
|
||||||
|
FunctionTemplateSpecializationInfo *Info
|
||||||
|
= getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
|
||||||
|
return Info ? Info->Function->getMostRecentDeclaration() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() {
|
FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() {
|
||||||
FunctionTemplateDecl *FunTmpl = this;
|
FunctionTemplateDecl *FunTmpl = this;
|
||||||
while (FunTmpl->getPreviousDeclaration())
|
while (FunTmpl->getPreviousDeclaration())
|
||||||
|
|
|
@ -254,11 +254,12 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||||
|
|
||||||
SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
|
SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
|
||||||
|
|
||||||
FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
|
if (FD->isCanonicalDecl()) // if canonical add to template's set.
|
||||||
TemplArgs.data(), TSK,
|
FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
|
||||||
TemplArgLocs.size(),
|
TemplArgs.data(), TSK,
|
||||||
TemplArgLocs.data(),
|
TemplArgLocs.size(),
|
||||||
LAngleLoc, RAngleLoc, POI);
|
TemplArgLocs.data(),
|
||||||
|
LAngleLoc, RAngleLoc, POI);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
|
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
|
||||||
|
|
|
@ -929,8 +929,11 @@ void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||||
Record.push_back(D->getSpecializations().size());
|
Record.push_back(D->getSpecializations().size());
|
||||||
for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
|
for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
|
||||||
I = D->getSpecializations().begin(),
|
I = D->getSpecializations().begin(),
|
||||||
E = D->getSpecializations().end() ; I != E; ++I)
|
E = D->getSpecializations().end() ; I != E; ++I) {
|
||||||
|
assert(I->Function->isCanonicalDecl() &&
|
||||||
|
"Expected only canonical decls in set");
|
||||||
Writer.AddDeclRef(I->Function, Record);
|
Writer.AddDeclRef(I->Function, Record);
|
||||||
|
}
|
||||||
|
|
||||||
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
|
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
|
||||||
if (D->getInstantiatedFromMemberTemplate())
|
if (D->getInstantiatedFromMemberTemplate())
|
||||||
|
|
|
@ -968,20 +968,16 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
||||||
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
|
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
|
||||||
void *InsertPos = 0;
|
void *InsertPos = 0;
|
||||||
if (FunctionTemplate && !TemplateParams) {
|
if (FunctionTemplate && !TemplateParams) {
|
||||||
llvm::FoldingSetNodeID ID;
|
|
||||||
std::pair<const TemplateArgument *, unsigned> Innermost
|
std::pair<const TemplateArgument *, unsigned> Innermost
|
||||||
= TemplateArgs.getInnermost();
|
= TemplateArgs.getInnermost();
|
||||||
FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
|
|
||||||
Innermost.second,
|
|
||||||
SemaRef.Context);
|
|
||||||
|
|
||||||
FunctionTemplateSpecializationInfo *Info
|
FunctionDecl *SpecFunc
|
||||||
= FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
|
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
|
||||||
InsertPos);
|
InsertPos);
|
||||||
|
|
||||||
// If we already have a function template specialization, return it.
|
// If we already have a function template specialization, return it.
|
||||||
if (Info)
|
if (SpecFunc)
|
||||||
return Info->Function;
|
return SpecFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFriend;
|
bool isFriend;
|
||||||
|
@ -1222,20 +1218,16 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
||||||
// We are creating a function template specialization from a function
|
// We are creating a function template specialization from a function
|
||||||
// template. Check whether there is already a function template
|
// template. Check whether there is already a function template
|
||||||
// specialization for this particular set of template arguments.
|
// specialization for this particular set of template arguments.
|
||||||
llvm::FoldingSetNodeID ID;
|
|
||||||
std::pair<const TemplateArgument *, unsigned> Innermost
|
std::pair<const TemplateArgument *, unsigned> Innermost
|
||||||
= TemplateArgs.getInnermost();
|
= TemplateArgs.getInnermost();
|
||||||
FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
|
|
||||||
Innermost.second,
|
|
||||||
SemaRef.Context);
|
|
||||||
|
|
||||||
FunctionTemplateSpecializationInfo *Info
|
FunctionDecl *SpecFunc
|
||||||
= FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
|
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
|
||||||
InsertPos);
|
InsertPos);
|
||||||
|
|
||||||
// If we already have a function template specialization, return it.
|
// If we already have a function template specialization, return it.
|
||||||
if (Info)
|
if (SpecFunc)
|
||||||
return Info->Function;
|
return SpecFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFriend;
|
bool isFriend;
|
||||||
|
|
Loading…
Reference in New Issue