diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 25 | ||||
-rw-r--r-- | clang/lib/AST/DeclTemplate.cpp | 27 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 30 |
6 files changed, 93 insertions, 17 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 86b58177437..7683d5a1607 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1806,6 +1806,12 @@ Decl *ASTContext::getCanonicalDecl(Decl *D) { return const_cast<FunctionDecl *>(Function); } + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) { + while (FunTmpl->getPreviousDeclaration()) + FunTmpl = FunTmpl->getPreviousDeclaration(); + return FunTmpl; + } + if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { while (Var->getPreviousDeclaration()) Var = Var->getPreviousDeclaration(); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 725b06676e6..e25fe90b4df 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -372,11 +372,6 @@ void FunctionDecl::Destroy(ASTContext& C) { C.Deallocate(ParamInfo); - if (FunctionTemplateSpecializationInfo *Info - = TemplateOrSpecialization - .dyn_cast<FunctionTemplateSpecializationInfo*>()) - C.Deallocate(Info); - Decl::Destroy(C); } @@ -564,6 +559,18 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const { return false; } +void +FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { + PreviousDeclaration = PrevDecl; + + if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { + FunctionTemplateDecl *PrevFunTmpl + = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; + assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); + FunTmpl->setPreviousDeclaration(PrevFunTmpl); + } +} + /// getOverloadedOperator - Which C++ overloaded operator this /// function represents, if any. OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { @@ -595,15 +602,21 @@ FunctionDecl::getTemplateSpecializationArgs() const { void FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context, FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs) { + const TemplateArgumentList *TemplateArgs, + void *InsertPos) { FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); if (!Info) Info = new (Context) FunctionTemplateSpecializationInfo; + Info->Function = this; Info->Template = Template; Info->TemplateArguments = TemplateArgs; TemplateOrSpecialization = Info; + + // Insert this function template specialization into the set of known + // function template specialiations. + Template->getSpecializations().InsertNode(Info, InsertPos); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 165672d50f4..f1bd1b67d21 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -81,11 +81,36 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, + TemplateParameterList *Params, NamedDecl *Decl) { return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); } +void FunctionTemplateDecl::Destroy(ASTContext &C) { + if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) { + for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator + Spec = CommonPtr->Specializations.begin(), + SpecEnd = CommonPtr->Specializations.end(); + Spec != SpecEnd; ++Spec) + C.Deallocate(&*Spec); + } + + Decl::Destroy(C); +} + +FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() { + // Find the first declaration of this function template. + FunctionTemplateDecl *First = this; + while (First->getPreviousDeclaration()) + First = First->getPreviousDeclaration(); + + if (First->CommonOrPrev.isNull()) { + // FIXME: Allocate with the ASTContext + First->CommonOrPrev = new Common; + } + return First->CommonOrPrev.get<Common*>(); +} + //===----------------------------------------------------------------------===// // ClassTemplateDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index a82324834b8..acd90e26469 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1500,6 +1500,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; // No code generation needed. case Decl::Using: + case Decl::ClassTemplate: + case Decl::FunctionTemplate: break; case Decl::CXXConstructor: EmitCXXConstructors(cast<CXXConstructorDecl>(D)); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 3d909bb26a7..53003855404 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1036,14 +1036,22 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, InstantiateDecl(FunctionTemplate->getTemplatedDecl(), FunctionTemplate->getDeclContext(), *DeducedArgumentList)); + if (!Specialization) + return TDK_SubstitutionFailure; - if (!Specialization || Trap.hasErrorOccurred()) + // If the template argument list is owned by the function template + // specialization, release it. + if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList) + Info.take(); + + // There may have been an error that did not prevent us from constructing a + // declaration. Mark the declaration invalid and return with a substitution + // failure. + if (Trap.hasErrorOccurred()) { + Specialization->setInvalidDecl(true); return TDK_SubstitutionFailure; - - // Turn the specialization into an actual function template specialization. - Specialization->setFunctionTemplateSpecialization(Context, - FunctionTemplate, - Info.take()); + } + return TDK_Success; } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a05095fa57a..ac0f46efe9e 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -294,7 +294,24 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { } Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { - // FIXME: Look for existing specializations (explicit or otherwise). + // Check whether there is already a function template specialization for + // this declaration. + FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); + void *InsertPos = 0; + if (FunctionTemplate) { + llvm::FoldingSetNodeID ID; + FunctionTemplateSpecializationInfo::Profile(ID, + TemplateArgs.getFlatArgumentList(), + TemplateArgs.flat_size()); + + FunctionTemplateSpecializationInfo *Info + = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, + InsertPos); + + // If we already have a function template specialization, return it. + if (Info) + return Info->Function; + } Sema::LocalInstantiationScope Scope(SemaRef); @@ -325,10 +342,15 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { NamedDecl *PrevDecl = 0; SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration, /*FIXME:*/OverloadableAttrRequired); - - // FIXME: link this to the function template from which it was instantiated. - + if (FunctionTemplate) { + // Record this function template specialization. + Function->setFunctionTemplateSpecialization(SemaRef.Context, + FunctionTemplate, + &TemplateArgs, + InsertPos); + } + return Function; } |