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:
Argyrios Kyrtzidis 2010-07-20 13:59:58 +00:00
parent c1624e9eda
commit dde5790562
6 changed files with 55 additions and 35 deletions

View File

@ -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.

View File

@ -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");
}
} }
} }

View File

@ -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())

View File

@ -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: {

View File

@ -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())

View File

@ -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;