diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 5f378993a2..8f877a8b56 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -324,9 +324,6 @@ namespace { /// this declaration. Decl *TransformDecl(Decl *D); - /// \brief Transform the given template name by instantiating it. - TemplateName TransformTemplateName(TemplateName Template); - /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T); @@ -338,15 +335,22 @@ Sema::OwningExprResult TemplateInstantiator::TransformExpr(Expr *E) { } Decl *TemplateInstantiator::TransformDecl(Decl *D) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast_or_null(D)) { + // FIXME: Depth reduction + assert(TTP->getDepth() == 0 && + "Cannot reduce depth of a template template parameter"); + assert(TemplateArgs[TTP->getPosition()].getAsDecl() && + "Wrong kind of template template argument"); + TemplateDecl *Template + = dyn_cast(TemplateArgs[TTP->getPosition()].getAsDecl()); + assert(Template && "Expected a template"); + return Template; + } + return SemaRef.InstantiateCurrentDeclRef(cast_or_null(D)); } -TemplateName -TemplateInstantiator::TransformTemplateName(TemplateName Template) { - return getSema().InstantiateTemplateName(Template, /*FIXME*/Loc, - TemplateArgs); -} - QualType TemplateInstantiator::TransformTemplateTypeParmType( const TemplateTypeParmType *T) { @@ -720,66 +724,9 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS, TemplateName Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc, const TemplateArgumentList &TemplateArgs) { - if (TemplateTemplateParmDecl *TTP - = dyn_cast_or_null( - Name.getAsTemplateDecl())) { - assert(TTP->getDepth() == 0 && - "Cannot reduce depth of a template template parameter"); - assert(TemplateArgs[TTP->getPosition()].getAsDecl() && - "Wrong kind of template template argument"); - ClassTemplateDecl *ClassTemplate - = dyn_cast( - TemplateArgs[TTP->getPosition()].getAsDecl()); - assert(ClassTemplate && "Expected a class template"); - if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { - NestedNameSpecifier *NNS - = InstantiateNestedNameSpecifier(QTN->getQualifier(), - /*FIXME=*/SourceRange(Loc), - TemplateArgs); - 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); - - 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(); - } - - - - // 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; + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, + DeclarationName()); + return Instantiator.TransformTemplateName(Name); } TemplateArgument Sema::Instantiate(TemplateArgument Arg, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 70ad317924..24deb4bbd5 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -171,8 +171,10 @@ public: /// \brief Transform the given template name. /// - /// FIXME: At the moment, subclasses must override this. - TemplateName TransformTemplateName(TemplateName Template); + /// By default, transforms the template name by transforming the declarations + /// and nested-name-specifiers that occur within the template name. + /// Subclasses may override this function to provide alternate behavior. + TemplateName TransformTemplateName(TemplateName Name); /// \brief Transform the given template argument. /// @@ -433,6 +435,36 @@ public: SourceRange Range, bool TemplateKW, QualType T); + + /// \brief Build a new template name given a nested name specifier, a flag + /// indicating whether the "template" keyword was provided, and the template + /// that the template name refers to. + /// + /// By default, builds the new template name directly. Subclasses may override + /// this routine to provide different behavior. + TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + bool TemplateKW, + TemplateDecl *Template); + + /// \brief Build a new template name given a nested name specifier, a flag + /// indicating whether the "template" keyword was provided, and a set of + /// overloaded function templates. + /// + /// By default, builds the new template name directly. Subclasses may override + /// this routine to provide different behavior. + TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + bool TemplateKW, + OverloadedFunctionDecl *Ovl); + + /// \brief Build a new template name given a nested name specifier and the + /// name that is referred to as a template. + /// + /// By default, performs semantic analysis to determine whether the name can + /// be resolved to a specific template, then builds the appropriate kind of + /// template name. Subclasses may override this routine to provide different + /// behavior. + TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo &II); }; template @@ -477,6 +509,9 @@ TreeTransform::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: { QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0)); + if (T.isNull()) + return 0; + if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix() && T == QualType(NNS->getAsType(), 0)) @@ -492,6 +527,88 @@ TreeTransform::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, return 0; } +template +TemplateName +TreeTransform::TransformTemplateName(TemplateName Name) { + if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { + NestedNameSpecifier *NNS + = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(), + /*FIXME:*/SourceRange(getDerived().getBaseLocation())); + if (!NNS) + return TemplateName(); + + if (TemplateDecl *Template = QTN->getTemplateDecl()) { + TemplateDecl *TransTemplate + = cast_or_null(getDerived().TransformDecl(Template)); + if (!TransTemplate) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + NNS == QTN->getQualifier() && + TransTemplate == Template) + return Name; + + return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(), + TransTemplate); + } + + OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl(); + assert(Ovl && "Not a template name or an overload set?"); + OverloadedFunctionDecl *TransOvl + = cast_or_null(getDerived().TransformDecl(Ovl)); + if (!TransOvl) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + NNS == QTN->getQualifier() && + TransOvl == Ovl) + return Name; + + return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(), + TransOvl); + } + + if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { + NestedNameSpecifier *NNS + = getDerived().TransformNestedNameSpecifier(DTN->getQualifier(), + /*FIXME:*/SourceRange(getDerived().getBaseLocation())); + if (!NNS) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + NNS == DTN->getQualifier()) + return Name; + + return getDerived().RebuildTemplateName(NNS, *DTN->getName()); + } + + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + TemplateDecl *TransTemplate + = cast_or_null(getDerived().TransformDecl(Template)); + if (!TransTemplate) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + TransTemplate == Template) + return Name; + + return TemplateName(TransTemplate); + } + + OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl(); + assert(Ovl && "Not a template name or an overload set?"); + OverloadedFunctionDecl *TransOvl + = cast_or_null(getDerived().TransformDecl(Ovl)); + if (!TransOvl) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + TransOvl == Ovl) + return Name; + + return TemplateName(TransOvl); +} + template TemplateArgument TreeTransform::TransformTemplateArgument(const TemplateArgument &Arg) { @@ -1343,6 +1460,51 @@ TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, return 0; } +template +TemplateName +TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, + bool TemplateKW, + TemplateDecl *Template) { + return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, + Template); +} + +template +TemplateName +TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, + bool TemplateKW, + OverloadedFunctionDecl *Ovl) { + return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl); +} + +template +TemplateName +TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo &II) { + if (Qualifier->isDependent()) + return SemaRef.Context.getDependentTemplateName(Qualifier, &II); + + // Somewhat redundant with ActOnDependentTemplateName. + CXXScopeSpec SS; + SS.setRange(SourceRange(getDerived().getBaseLocation())); + SS.setScopeRep(Qualifier); + Sema::TemplateTy Template; + TemplateNameKind TNK = SemaRef.isTemplateName(II, 0, Template, &SS); + if (TNK == TNK_Non_template) { + SemaRef.Diag(getDerived().getBaseLocation(), + diag::err_template_kw_refers_to_non_template) + << &II; + return TemplateName(); + } else if (TNK == TNK_Function_template) { + SemaRef.Diag(getDerived().getBaseLocation(), + diag::err_template_kw_refers_to_non_template) + << &II; + return TemplateName(); + } + + return Template.getAsVal(); +} + } // end namespace clang #endif // LLVM_CLANG_SEMA_TREETRANSFORM_H diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp index 9261ed6a6c..471b2ad3fa 100644 --- a/test/SemaTemplate/metafun-apply.cpp +++ b/test/SemaTemplate/metafun-apply.cpp @@ -35,7 +35,8 @@ void test() { apply1::type t; // expected-note{{in instantiation of template class 'struct apply1' requested here}} \ // FIXME: expected-error{{unexpected type name 'type': expected expression}} - apply1::type t2; // expected-note{{in instantiation of template class 'struct apply1' requested here}} + apply1::type t2; // expected-note{{in instantiation of template class 'struct apply1' requested here}} \ + // FIXME: expected-error{{unexpected type name 'type': expected expression}} }