/// 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),
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.
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");
}
}
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())
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: {
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())
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;
// 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;