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.
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,
TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
@ -535,11 +549,10 @@ public:
return static_cast<FunctionDecl*>(TemplatedDecl);
}
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
return getCommonPtr()->Specializations;
}
/// \brief Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
FunctionDecl *findSpecialization(const TemplateArgument *Args,
unsigned NumArgs, void *&InsertPos);
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.

View File

@ -1400,14 +1400,15 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
if (InsertPos)
Template->getSpecializations().InsertNode(Info, InsertPos);
else {
// Try to insert the new node. If there is an existing node, remove it
// first.
// Try to insert the new node. If there is an existing node, leave it, the
// set will contain the canonical decls while
// FunctionTemplateDecl::findSpecialization will return
// the most recent redeclarations.
FunctionTemplateSpecializationInfo *Existing
= Template->getSpecializations().GetOrInsertNode(Info);
if (Existing) {
Template->getSpecializations().RemoveNode(Existing);
Template->getSpecializations().GetOrInsertNode(Info);
}
(void)Existing;
assert((!Existing || Existing->Function->isCanonicalDecl()) &&
"Set is supposed to only contain canonical decls");
}
}

View File

@ -119,6 +119,16 @@ void FunctionTemplateDecl::Destroy(ASTContext &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 *FunTmpl = this;
while (FunTmpl->getPreviousDeclaration())

View File

@ -254,11 +254,12 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
TemplArgs.data(), TSK,
TemplArgLocs.size(),
TemplArgLocs.data(),
LAngleLoc, RAngleLoc, POI);
if (FD->isCanonicalDecl()) // if canonical add to template's set.
FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
TemplArgs.data(), TSK,
TemplArgLocs.size(),
TemplArgLocs.data(),
LAngleLoc, RAngleLoc, POI);
break;
}
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {

View File

@ -929,8 +929,11 @@ void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
Record.push_back(D->getSpecializations().size());
for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
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(D->getInstantiatedFromMemberTemplate(), Record);
if (D->getInstantiatedFromMemberTemplate())

View File

@ -968,20 +968,16 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
void *InsertPos = 0;
if (FunctionTemplate && !TemplateParams) {
llvm::FoldingSetNodeID ID;
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
Innermost.second,
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
= FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
InsertPos);
FunctionDecl *SpecFunc
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
InsertPos);
// If we already have a function template specialization, return it.
if (Info)
return Info->Function;
if (SpecFunc)
return SpecFunc;
}
bool isFriend;
@ -1222,20 +1218,16 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// We are creating a function template specialization from a function
// template. Check whether there is already a function template
// specialization for this particular set of template arguments.
llvm::FoldingSetNodeID ID;
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
Innermost.second,
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
= FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
InsertPos);
FunctionDecl *SpecFunc
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
InsertPos);
// If we already have a function template specialization, return it.
if (Info)
return Info->Function;
if (SpecFunc)
return SpecFunc;
}
bool isFriend;