diff options
author | John McCall <rjmccall@apple.com> | 2009-08-20 01:44:21 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-08-20 01:44:21 +0000 |
commit | e29ba20148e9b7835ad463b39cd4ee9223eafbbf (patch) | |
tree | 44ca1980c3f24bd369f292437f96d1fc06690cae /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | fafd3834754d2093e0ad7a1c005860fd527ecb7f (diff) |
Basic nested-template implementation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79504 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 30d7b6acd6..23256a853c 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -53,6 +53,8 @@ namespace { Decl *VisitCXXConversionDecl(CXXConversionDecl *D); ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D); Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D); + Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); + Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); // Base case. FIXME: Remove once we can instantiate everything. Decl *VisitDecl(Decl *) { @@ -69,6 +71,9 @@ namespace { llvm::SmallVectorImpl<ParmVarDecl *> &Params); bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl); bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl); + + TemplateParameterList * + InstantiateTemplateParams(TemplateParameterList *List); }; } @@ -322,6 +327,28 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { return 0; } +Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams = InstantiateTemplateParams(TempParams); + if (!InstParams) return NULL; + + CXXRecordDecl *Pattern = D->getTemplatedDecl(); + CXXRecordDecl *RecordInst + = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), Owner, + Pattern->getLocation(), Pattern->getIdentifier(), + Pattern->getTagKeywordLoc(), /*PrevDecl=*/ NULL); + + ClassTemplateDecl *Inst + = ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier(), InstParams, RecordInst, 0); + RecordInst->setDescribedClassTemplate(Inst); + Inst->setAccess(D->getAccess()); + Inst->setInstantiatedFromMemberTemplate(D); + + Owner->addDecl(Inst); + return Inst; +} + Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *PrevDecl = 0; if (D->isInjectedClassName()) @@ -639,12 +666,79 @@ TemplateDeclInstantiator::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) { return VisitParmVarDecl(D); } +Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( + TemplateTypeParmDecl *D) { + // TODO: don't always clone when decls are refcounted. + const Type* T = D->getTypeForDecl(); + assert(T->isTemplateTypeParmType()); + const TemplateTypeParmType *TTPT = T->getAs<TemplateTypeParmType>(); + + TemplateTypeParmDecl *Inst = + TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), + TTPT->getDepth(), TTPT->getIndex(), + TTPT->getName(), + D->wasDeclaredWithTypename(), + D->isParameterPack()); + + if (D->hasDefaultArgument()) { + QualType DefaultPattern = D->getDefaultArgument(); + QualType DefaultInst + = SemaRef.InstantiateType(DefaultPattern, TemplateArgs, + D->getDefaultArgumentLoc(), + D->getDeclName()); + + Inst->setDefaultArgument(DefaultInst, + D->getDefaultArgumentLoc(), + D->defaultArgumentWasInherited() /* preserve? */); + } + + return Inst; +} + Decl *Sema::InstantiateDecl(Decl *D, DeclContext *Owner, const TemplateArgumentList &TemplateArgs) { TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); return Instantiator.Visit(D); } +/// \brief Instantiates a nested template parameter list in the current +/// instantiation context. +/// +/// \param L The parameter list to instantiate +/// +/// \returns NULL if there was an error +TemplateParameterList * +TemplateDeclInstantiator::InstantiateTemplateParams(TemplateParameterList *L) { + // Get errors for all the parameters before bailing out. + bool Invalid = false; + + unsigned N = L->size(); + typedef llvm::SmallVector<Decl*,8> ParamVector; + ParamVector Params; + Params.reserve(N); + for (TemplateParameterList::iterator PI = L->begin(), PE = L->end(); + PI != PE; ++PI) { + Decl *D = Visit(*PI); + Params.push_back(D); + Invalid = Invalid || !D; + } + + // Clean up if we had an error. + if (Invalid) { + for (ParamVector::iterator PI = Params.begin(), PE = Params.end(); + PI != PE; ++PI) + if (*PI) + (*PI)->Destroy(SemaRef.Context); + return NULL; + } + + TemplateParameterList *InstL + = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(), + L->getLAngleLoc(), &Params.front(), N, + L->getRAngleLoc()); + return InstL; +} + /// \brief Instantiates the type of the given function, including /// instantiating all of the function parameters. /// |