diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/TemplateName.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 80 |
3 files changed, 91 insertions, 4 deletions
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index 4e54fe49559..3659e2350de 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/NestedNameSpecifier.h" #include "llvm/Support/raw_ostream.h" +#include <stdio.h> using namespace clang; @@ -52,3 +53,12 @@ void TemplateName::Print(llvm::raw_ostream &OS) const { OS << DTN->getName()->getName(); } } + +void TemplateName::Dump() const { + std::string Result; + { + llvm::raw_string_ostream OS(Result); + Print(OS); + } + fprintf(stderr, "%s", Result.c_str()); +} diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 634c90a36e2..3a18f9676b0 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1981,6 +1981,11 @@ public: const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); + TemplateName + InstantiateTemplateName(TemplateName Name, SourceLocation Loc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + // Simple function for cloning expressions. template<typename T> OwningExprResult Clone(T *E) { diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 2eb874597e4..c9f0d4fd799 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/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; +} |