diff options
-rw-r--r-- | include/clang/Parse/Action.h | 14 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 74 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 13 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 32 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 30 | ||||
-rw-r--r-- | test/SemaTemplate/nested-name-spec-template.cpp | 1 |
7 files changed, 99 insertions, 82 deletions
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index baca3fb502..d8bb8a5b61 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -2006,13 +2006,21 @@ public: /// /// \param EnteringContext whether we are entering the context of this /// template. - virtual TemplateTy ActOnDependentTemplateName(Scope *S, + /// + /// \param Template Will be set to the dependent template name, on success. + /// + /// \returns The kind of template name that was produced. Generally, this will + /// be \c TNK_Dependent_template_name. However, if the nested-name-specifier + /// is not dependent, or refers to the current instantiation, then we may + /// be able to resolve the template kind more specifically. + virtual TemplateNameKind ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc, CXXScopeSpec &SS, UnqualifiedId &Name, TypeTy *ObjectType, - bool EnteringContext) { - return TemplateTy(); + bool EnteringContext, + TemplateTy &Template) { + return TNK_Non_template; } /// \brief Process the declaration or definition of an explicit diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 843baa2fe7..dd74c4e998 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -164,14 +164,18 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Commit to parsing the template-id. TPA.Commit(); - TemplateTy Template - = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, - TemplateName, - ObjectType, EnteringContext); - if (!Template) - return true; - if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, - &SS, TemplateName, TemplateKWLoc, false)) + TemplateTy Template; + if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(CurScope, + TemplateKWLoc, + SS, + TemplateName, + ObjectType, + EnteringContext, + Template)) { + if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, + TemplateKWLoc, false)) + return true; + } else return true; continue; @@ -320,19 +324,20 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, << II.getName() << FixItHint::CreateInsertion(Tok.getLocation(), "template "); - Template = Actions.ActOnDependentTemplateName(CurScope, - Tok.getLocation(), SS, - TemplateName, ObjectType, - EnteringContext); - if (!Template.get()) + if (TemplateNameKind TNK + = Actions.ActOnDependentTemplateName(CurScope, + Tok.getLocation(), SS, + TemplateName, ObjectType, + EnteringContext, Template)) { + // Consume the identifier. + ConsumeToken(); + if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, + SourceLocation(), false)) + return true; + } + else return true; - - // Consume the identifier. - ConsumeToken(); - if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, &SS, - TemplateName, SourceLocation(), false)) - return true; - + continue; } } @@ -1013,12 +1018,11 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, case UnqualifiedId::IK_OperatorFunctionId: case UnqualifiedId::IK_LiteralOperatorId: if (AssumeTemplateId) { - Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, - Id, ObjectType, - EnteringContext); - TNK = TNK_Dependent_template_name; - if (!Template.get()) - return true; + TNK = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, + Id, ObjectType, EnteringContext, + Template); + if (TNK == TNK_Non_template) + return true; } else { bool MemberOfUnknownSpecialization; TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, @@ -1044,11 +1048,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword) << Name << FixItHint::CreateInsertion(Id.StartLocation, "template "); - Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, - SS, Id, ObjectType, - EnteringContext); - TNK = TNK_Dependent_template_name; - if (!Template.get()) + TNK = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, + SS, Id, ObjectType, + EnteringContext, Template); + if (TNK == TNK_Non_template) return true; } } @@ -1069,11 +1072,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, bool MemberOfUnknownSpecialization; TemplateName.setIdentifier(Name, NameLoc); if (ObjectType) { - Template = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, - TemplateName, ObjectType, - EnteringContext); - TNK = TNK_Dependent_template_name; - if (!Template.get()) + TNK = Actions.ActOnDependentTemplateName(CurScope, TemplateKWLoc, SS, + TemplateName, ObjectType, + EnteringContext, Template); + if (TNK == TNK_Non_template) return true; } else { TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index ec0e31e703..9e95ca9f11 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -914,15 +914,14 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { // If the next token signals the end of a template argument, // then we have a dependent template name that could be a template // template argument. - if (isEndOfTemplateArgument(Tok)) { - TemplateTy Template - = Actions.ActOnDependentTemplateName(CurScope, TemplateLoc, SS, Name, - /*ObjectType=*/0, - /*EnteringContext=*/false); - if (Template.get()) - return ParsedTemplateArgument(SS, Template, Name.StartLocation); - } - } + TemplateTy Template; + if (isEndOfTemplateArgument(Tok) && + Actions.ActOnDependentTemplateName(CurScope, TemplateLoc, SS, Name, + /*ObjectType=*/0, + /*EnteringContext=*/false, + Template)) + return ParsedTemplateArgument(SS, Template, Name.StartLocation); + } } else if (Tok.is(tok::identifier)) { // We may have a (non-dependent) template name. TemplateTy Template; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index c81c12bb86..e719cd7453 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2937,12 +2937,13 @@ public: SourceLocation NameLoc, const TemplateArgumentListInfo &TemplateArgs); - virtual TemplateTy ActOnDependentTemplateName(Scope *S, - SourceLocation TemplateKWLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext); + virtual TemplateNameKind ActOnDependentTemplateName(Scope *S, + SourceLocation TemplateKWLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + TypeTy *ObjectType, + bool EnteringContext, + TemplateTy &Template); bool CheckClassTemplatePartialSpecializationArgs( TemplateParameterList *TemplateParams, diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index b30d4e3e9c..735809f185 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1686,12 +1686,13 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, /// example, given "MetaFun::template apply", the scope specifier \p /// SS will be "MetaFun::", \p TemplateKWLoc contains the location /// of the "template" keyword, and "apply" is the \p Name. -Sema::TemplateTy -Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext) { +TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, + SourceLocation TemplateKWLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + TypeTy *ObjectType, + bool EnteringContext, + TemplateTy &Result) { if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() && !getLangOptions().CPlusPlus0x) Diag(TemplateKWLoc, diag::ext_template_outside_of_template) @@ -1719,25 +1720,24 @@ Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc, // dependent name. C++ DR468 relaxed this requirement (the // "template" keyword is now permitted). We follow the C++0x // rules, even in C++03 mode with a warning, retroactively applying the DR. - TemplateTy Template; bool MemberOfUnknownSpecialization; TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, - EnteringContext, Template, + EnteringContext, Result, MemberOfUnknownSpecialization); if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && isa<CXXRecordDecl>(LookupCtx) && cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) { - // This is a dependent template. + // This is a dependent template. Handle it below. } else if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), diag::err_template_kw_refers_to_non_template) << GetNameFromUnqualifiedId(Name) << Name.getSourceRange() << TemplateKWLoc; - return TemplateTy(); + return TNK_Non_template; } else { // We found something; return it. - return Template; + return TNK; } } @@ -1746,12 +1746,14 @@ Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc, switch (Name.getKind()) { case UnqualifiedId::IK_Identifier: - return TemplateTy::make(Context.getDependentTemplateName(Qualifier, - Name.Identifier)); + Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Name.Identifier)); + return TNK_Dependent_template_name; case UnqualifiedId::IK_OperatorFunctionId: - return TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, Name.OperatorFunctionId.Operator)); + return TNK_Dependent_template_name; case UnqualifiedId::IK_LiteralOperatorId: assert(false && "We don't support these; Parse shouldn't have allowed propagation"); @@ -1765,7 +1767,7 @@ Sema::ActOnDependentTemplateName(Scope *S, SourceLocation TemplateKWLoc, << GetNameFromUnqualifiedId(Name) << Name.getSourceRange() << TemplateKWLoc; - return TemplateTy(); + return TNK_Non_template; } bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 86e3a25ea2..d2995778fc 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6495,13 +6495,15 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, SS.setScopeRep(Qualifier); UnqualifiedId Name; Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation()); - return getSema().ActOnDependentTemplateName(/*Scope=*/0, - /*FIXME:*/getDerived().getBaseLocation(), - SS, - Name, - ObjectType.getAsOpaquePtr(), - /*EnteringContext=*/false) - .template getAsVal<TemplateName>(); + Sema::TemplateTy Template; + getSema().ActOnDependentTemplateName(/*Scope=*/0, + /*FIXME:*/getDerived().getBaseLocation(), + SS, + Name, + ObjectType.getAsOpaquePtr(), + /*EnteringContext=*/false, + Template); + return Template.template getAsVal<TemplateName>(); } template<typename Derived> @@ -6516,13 +6518,15 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, SourceLocation SymbolLocations[3]; // FIXME: Bogus location information. Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(), Operator, SymbolLocations); - return getSema().ActOnDependentTemplateName(/*Scope=*/0, + Sema::TemplateTy Template; + getSema().ActOnDependentTemplateName(/*Scope=*/0, /*FIXME:*/getDerived().getBaseLocation(), - SS, - Name, - ObjectType.getAsOpaquePtr(), - /*EnteringContext=*/false) - .template getAsVal<TemplateName>(); + SS, + Name, + ObjectType.getAsOpaquePtr(), + /*EnteringContext=*/false, + Template); + return Template.template getAsVal<TemplateName>(); } template<typename Derived> diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp index 0251894f35..e1e7246bd7 100644 --- a/test/SemaTemplate/nested-name-spec-template.cpp +++ b/test/SemaTemplate/nested-name-spec-template.cpp @@ -22,6 +22,7 @@ namespace N { M::Promote<int>::type *ret_intptr3(int* ip) { return ip; } M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' keyword outside of a template}} + M::template Promote<int> pi; // expected-warning{{'template' keyword outside of a template}} } N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; } |