diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-31 18:38:02 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-31 18:38:02 +0000 |
commit | de650ae96b53eb6109f29fdb5ee51c514259e6e4 (patch) | |
tree | c8110a61def8698d6cda53263f62e0e61a7808c9 /lib/Sema/SemaTemplateInstantiate.cpp | |
parent | f8c4f5469d7db591eeacfc3381d91f773fb7af43 (diff) |
Implement template instantiation for template names, including both
template template parameters and dependent template names. For
example, the oft-mentioned
typename MetaFun::template apply<T1, T2>::type
can now be instantiated, with the appropriate name lookup for "apply".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68128 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 80 |
1 files changed, 76 insertions, 4 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 2eb874597e..c9f0d4fd79 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -472,10 +472,13 @@ InstantiateTemplateSpecializationType( // FIXME: We're missing the locations of the template name, '<', and // '>'. - // FIXME: Need to instantiate into the template name. - return SemaRef.CheckTemplateIdType(T->getTemplateName(), - Loc, - SourceLocation(), + + TemplateName Name = SemaRef.InstantiateTemplateName(T->getTemplateName(), + Loc, + TemplateArgs, + NumTemplateArgs); + + return SemaRef.CheckTemplateIdType(Name, Loc, SourceLocation(), &InstantiatedTemplateArgs[0], InstantiatedTemplateArgs.size(), SourceLocation()); @@ -839,3 +842,72 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS, // Required to silence a GCC warning return 0; } + +TemplateName +Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast_or_null<TemplateTemplateParmDecl>( + Name.getAsTemplateDecl())) { + assert(TTP->getDepth() == 0 && + "Cannot reduce depth of a template template parameter"); + assert(TTP->getPosition() < NumTemplateArgs && "Wrong # of template args"); + assert(dyn_cast_or_null<ClassTemplateDecl>( + TemplateArgs[TTP->getPosition()].getAsDecl()) && + "Wrong kind of template template argument"); + ClassTemplateDecl *ClassTemplate + = dyn_cast<ClassTemplateDecl>( + TemplateArgs[TTP->getPosition()].getAsDecl()); + + if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { + NestedNameSpecifier *NNS + = InstantiateNestedNameSpecifier(QTN->getQualifier(), + /*FIXME=*/SourceRange(Loc), + TemplateArgs, NumTemplateArgs); + if (NNS) + return Context.getQualifiedTemplateName(NNS, + QTN->hasTemplateKeyword(), + ClassTemplate); + } + + return TemplateName(ClassTemplate); + } else if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { + NestedNameSpecifier *NNS + = InstantiateNestedNameSpecifier(DTN->getQualifier(), + /*FIXME=*/SourceRange(Loc), + TemplateArgs, NumTemplateArgs); + + if (!NNS) // FIXME: Not the best recovery strategy. + return Name; + + if (NNS->isDependent()) + return Context.getDependentTemplateName(NNS, DTN->getName()); + + // Somewhat redundant with ActOnDependentTemplateName. + CXXScopeSpec SS; + SS.setRange(SourceRange(Loc)); + SS.setScopeRep(NNS); + TemplateTy Template; + TemplateNameKind TNK = isTemplateName(*DTN->getName(), 0, Template, &SS); + if (TNK == TNK_Non_template) { + Diag(Loc, diag::err_template_kw_refers_to_non_template) + << DTN->getName(); + return Name; + } else if (TNK == TNK_Function_template) { + Diag(Loc, diag::err_template_kw_refers_to_non_template) + << DTN->getName(); + return Name; + } + + return Template.getAsVal<TemplateName>(); + } + + + + // FIXME: Even if we're referring to a Decl that isn't a template + // template parameter, we may need to instantiate the outer contexts + // of that Decl. However, this won't be needed until we implement + // member templates. + return Name; +} |