From e861bac059d598cba212b4ca447339af11fbc44e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 25 Aug 2009 22:51:20 +0000 Subject: Improve support for out-of-line definitions of nested templates and their members, including member class template, member function templates, and member classes and functions of member templates. To actually parse the nested-name-specifiers that qualify the name of an out-of-line definition of a member template, e.g., template template X Outer::Inner1::foo(Y) { return X(); } we need to look for the template names (e.g., "Inner1") as a member of the current instantiation (Outer), even before we have entered the scope of the current instantiation. Since we can't do this in general (i.e., we should not be looking into all dependent nested-name-specifiers as if they were the current instantiation), we rely on the parser to tell us when it is parsing a declaration specifier sequence, and, therefore, when we should consider the current scope specifier to be a current instantiation. Printing of complicated, dependent nested-name-specifiers may be somewhat broken by this commit; I'll add tests for this issue and fix the problem (if it still exists) in a subsequent commit. llvm-svn: 80044 --- clang/lib/AST/ASTContext.cpp | 8 +--- clang/lib/Parse/MinimalAction.cpp | 5 ++- clang/lib/Parse/ParseDecl.cpp | 10 ++--- clang/lib/Parse/ParseDeclCXX.cpp | 4 +- clang/lib/Parse/ParseExprCXX.cpp | 14 ++++--- clang/lib/Parse/ParseTentative.cpp | 2 +- clang/lib/Parse/Parser.cpp | 12 +++--- clang/lib/Sema/Sema.h | 11 ++++-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 30 ++++++++------- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaLookup.cpp | 73 ++++++++++++++++++++----------------- clang/lib/Sema/SemaTemplate.cpp | 19 +++++++--- clang/lib/Sema/TreeTransform.h | 5 ++- 13 files changed, 108 insertions(+), 87 deletions(-) (limited to 'clang/lib') diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0cfb05b12ce..f5276576263 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2235,13 +2235,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { QualType T = getCanonicalType(QualType(NNS->getAsType(), 0)); - NestedNameSpecifier *Prefix = 0; - - // FIXME: This isn't the right check! - if (T->isDependentType()) - Prefix = getCanonicalNestedNameSpecifier(NNS->getPrefix()); - - return NestedNameSpecifier::Create(*this, Prefix, + return NestedNameSpecifier::Create(*this, 0, NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate, T.getTypePtr()); } diff --git a/clang/lib/Parse/MinimalAction.cpp b/clang/lib/Parse/MinimalAction.cpp index 648e2da54bf..6c8d75c2d6d 100644 --- a/clang/lib/Parse/MinimalAction.cpp +++ b/clang/lib/Parse/MinimalAction.cpp @@ -159,8 +159,9 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *, TemplateNameKind MinimalAction::isTemplateName(const IdentifierInfo &II, Scope *S, - TemplateTy &TemplateDecl, - const CXXScopeSpec *SS) { + const CXXScopeSpec *SS, + bool EnteringScope, + TemplateTy &TemplateDecl) { return TNK_Non_template; } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 597d43fb1b2..8cb8ffdd054 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -728,7 +728,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::coloncolon: // ::foo::bar // Annotate C++ scope specifiers. If we get one, loop. - if (TryAnnotateCXXScopeToken()) + if (TryAnnotateCXXScopeToken(true)) continue; goto DoneWithDeclSpec; @@ -743,7 +743,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ->Kind == TNK_Type_template) { // We have a qualified template-id, e.g., N::A CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS); + ParseOptionalCXXScopeSpecifier(SS, true); assert(Tok.is(tok::annot_template_id) && "ParseOptionalCXXScopeSpecifier not working"); AnnotateTemplateIdTokenAsType(&SS); @@ -820,7 +820,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::identifier: { // In C++, check to see if this is a scope specifier like foo::bar::, if // so handle it as such. This is important for ctor parsing. - if (getLang().CPlusPlus && TryAnnotateCXXScopeToken()) + if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true)) continue; // This identifier can only be a typedef name if we haven't already seen @@ -2023,7 +2023,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope))) { CXXScopeSpec SS; - if (ParseOptionalCXXScopeSpecifier(SS)) { + if (ParseOptionalCXXScopeSpecifier(SS, true)) { if(Tok.isNot(tok::star)) { // The scope spec really belongs to the direct-declarator. D.getCXXScopeSpec() = SS; @@ -2180,7 +2180,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (D.mayHaveIdentifier()) { // ParseDeclaratorInternal might already have parsed the scope. bool afterCXXScope = D.getCXXScopeSpec().isSet() || - ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec()); + ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), true); if (afterCXXScope) { // Change the declaration context for name lookup, until this function // is exited (and the declarator has been parsed). diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index af4f83a5059..3a82868d5ac 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -534,7 +534,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Parse the (optional) nested-name-specifier. CXXScopeSpec SS; - if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS)) + if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, true)) if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) Diag(Tok, diag::err_expected_ident); @@ -809,7 +809,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) { // Parse optional '::' and optional nested-name-specifier. CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS); + ParseOptionalCXXScopeSpecifier(SS, true); // The location of the base class itself. SourceLocation BaseLoc = Tok.getLocation(); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 46526e47dd8..d97bc2d0288 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -30,10 +30,11 @@ using namespace clang; /// nested-name-specifier identifier '::' /// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] /// -bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { +bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, + bool EnteringContext) { assert(getLang().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); - + if (Tok.is(tok::annot_cxxscope)) { SS.setScopeRep(Tok.getAnnotationValue()); SS.setRange(Tok.getAnnotationRange()); @@ -106,7 +107,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { if (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name) { AnnotateTemplateIdTokenAsType(&SS); - SS.setScopeRep(0); assert(Tok.is(tok::annot_typename) && "AnnotateTemplateIdTokenAsType isn't working"); @@ -164,7 +164,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { continue; SS.setScopeRep( - Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II)); + Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II, + EnteringContext)); SS.setEndLoc(CCLoc); continue; } @@ -173,8 +174,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { // type-name '<' if (Next.is(tok::less)) { TemplateTy Template; - if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope, - Template, &SS)) { + if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope, &SS, + EnteringContext, + Template)) { // We have found a template name, so annotate this this token // with a template-id annotation. We do not permit the // template-id to be translated into a type annotation, diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 8b0d400b5b8..89c3db74152 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -409,7 +409,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, while (1) { if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) - TryAnnotateCXXScopeToken(); + TryAnnotateCXXScopeToken(true); if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 380df7f0e0b..4d37ac7202a 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -870,7 +870,7 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. -bool Parser::TryAnnotateTypeOrScopeToken() { +bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || Tok.is(tok::kw_typename)) && "Cannot be a type or scope token!"); @@ -884,7 +884,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { // simple-template-id SourceLocation TypenameLoc = ConsumeToken(); CXXScopeSpec SS; - bool HadNestedNameSpecifier = ParseOptionalCXXScopeSpecifier(SS); + bool HadNestedNameSpecifier = ParseOptionalCXXScopeSpecifier(SS, false); if (!HadNestedNameSpecifier) { Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); return false; @@ -928,7 +928,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { CXXScopeSpec SS; if (getLang().CPlusPlus) - ParseOptionalCXXScopeSpecifier(SS); + ParseOptionalCXXScopeSpecifier(SS, EnteringContext); if (Tok.is(tok::identifier)) { // Determine whether the identifier is a type name. @@ -960,7 +960,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { TemplateTy Template; if (TemplateNameKind TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(), - CurScope, Template, &SS)) + CurScope, &SS, EnteringContext, Template)) if (AnnotateTemplateIdToken(Template, TNK, &SS)) { // If an unrecoverable error occurred, we need to return true here, // because the token stream is in a damaged state. We may not return @@ -1015,14 +1015,14 @@ bool Parser::TryAnnotateTypeOrScopeToken() { /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. -bool Parser::TryAnnotateCXXScopeToken() { +bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { assert(getLang().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) && "Cannot be a type or scope token!"); CXXScopeSpec SS; - if (!ParseOptionalCXXScopeSpecifier(SS)) + if (!ParseOptionalCXXScopeSpecifier(SS, EnteringContext)) return Tok.is(tok::annot_template_id); // Push the current token back into the token stream (or revert it if it is diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 03e641780db..9db3fae036a 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1265,7 +1265,8 @@ public: LookupNameKind NameKind, bool RedeclarationOnly = false, bool AllowBuiltinCreation = false, - SourceLocation Loc = SourceLocation()); + SourceLocation Loc = SourceLocation(), + bool EnteringContext = false); ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II); ObjCCategoryImplDecl *LookupObjCCategoryImpl(IdentifierInfo *II); @@ -1951,7 +1952,8 @@ public: const CXXScopeSpec &SS, SourceLocation IdLoc, SourceLocation CCLoc, - IdentifierInfo &II); + IdentifierInfo &II, + bool EnteringContext); /// ActOnCXXNestedNameSpecifier - Called during parsing of a /// nested-name-specifier that involves a template-id, e.g., @@ -2205,8 +2207,9 @@ public: // C++ Templates [C++ 14] // virtual TemplateNameKind isTemplateName(const IdentifierInfo &II, Scope *S, - TemplateTy &Template, - const CXXScopeSpec *SS = 0); + const CXXScopeSpec *SS, + bool EnteringContext, + TemplateTy &Template); bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 188957176b6..9c9bff8a085 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -48,11 +48,11 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, return Record; if (EnteringContext) { - // We are entering the context of the nested name specifier, so try to - // match the nested name specifier to either a primary class template - // or a class template partial specialization. if (const TemplateSpecializationType *SpecType = dyn_cast_or_null(NNS->getAsType())) { + // We are entering the context of the nested name specifier, so try to + // match the nested name specifier to either a primary class template + // or a class template partial specialization. if (ClassTemplateDecl *ClassTemplate = dyn_cast_or_null( SpecType->getTemplateName().getAsTemplateDecl())) { @@ -74,6 +74,10 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, = ClassTemplate->findPartialSpecialization(ContextType)) return PartialSpec; } + } else if (const RecordType *RecordT + = dyn_cast_or_null(NNS->getAsType())) { + // The nested name specifier refers to a member of a class template. + return RecordT->getDecl(); } std::string NNSString; @@ -260,17 +264,14 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, const CXXScopeSpec &SS, SourceLocation IdLoc, SourceLocation CCLoc, - IdentifierInfo &II) { + IdentifierInfo &II, + bool EnteringContext) { NestedNameSpecifier *Prefix = static_cast(SS.getScopeRep()); - // If the prefix already refers to an unknown specialization, there - // is no name lookup to perform. Just build the resulting - // nested-name-specifier. - if (Prefix && isUnknownSpecialization(SS)) - return NestedNameSpecifier::Create(Context, Prefix, &II); - - NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName); + NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName, + false, false, SourceLocation(), + EnteringContext); if (SD) { if (NamespaceDecl *Namespace = dyn_cast(SD)) @@ -303,13 +304,16 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, // Fall through to produce an error: we found something that isn't // a class or a namespace. - } + } else if (SS.isSet() && isDependentScopeSpecifier(SS)) + return NestedNameSpecifier::Create(Context, Prefix, &II); // If we didn't find anything during our lookup, try again with // ordinary name lookup, which can help us produce better error // messages. if (!SD) - SD = LookupParsedName(S, &SS, &II, LookupOrdinaryName); + SD = LookupParsedName(S, &SS, &II, LookupOrdinaryName, + false, false, SourceLocation(), + EnteringContext); unsigned DiagID; if (SD) DiagID = diag::err_expected_class_or_namespace; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 61f0ce808a7..d478c048b8a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -72,7 +72,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // refer to a member of an unknown specialization. if (SS && isUnknownSpecialization(*SS)) return 0; - + LookupResult Result = LookupParsedName(S, SS, &II, LookupOrdinaryName, false, false); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 1d583cc3914..6627499d12d 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1116,7 +1116,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, /// @param S The scope from which unqualified name lookup will /// begin. /// -/// @param SS An optional C++ scope-specified, e.g., "::N::M". +/// @param SS An optional C++ scope-specifier, e.g., "::N::M". /// /// @param Name The name of the entity that name lookup will /// search for. @@ -1125,49 +1125,56 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, /// name lookup. At present, this is only used to produce diagnostics when /// C library functions (like "malloc") are implicitly declared. /// +/// @param EnteringContext Indicates whether we are going to enter the +/// context of the scope-specifier SS (if present). +/// /// @returns The result of qualified or unqualified name lookup. Sema::LookupResult Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, DeclarationName Name, LookupNameKind NameKind, bool RedeclarationOnly, bool AllowBuiltinCreation, - SourceLocation Loc) { - if (SS && (SS->isSet() || SS->isInvalid())) { - // If the scope specifier is invalid, don't even look for + SourceLocation Loc, + bool EnteringContext) { + if (SS && SS->isInvalid()) { + // When the scope specifier is invalid, don't even look for // anything. - if (SS->isInvalid()) - return LookupResult::CreateLookupResult(Context, 0); - - assert(!isUnknownSpecialization(*SS) && "Can't lookup dependent types"); - - if (isDependentScopeSpecifier(*SS)) { - // Determine whether we are looking into the current - // instantiation. - NestedNameSpecifier *NNS - = static_cast(SS->getScopeRep()); - CXXRecordDecl *Current = getCurrentInstantiationOf(NNS); - assert(Current && "Bad dependent scope specifier"); + return LookupResult::CreateLookupResult(Context, 0); + } + + if (SS && SS->isSet()) { + if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) { + // We have resolved the scope specifier to a particular declaration + // contex, and will perform name lookup in that context. - // We nested name specifier refers to the current instantiation, - // so now we will look for a member of the current instantiation - // (C++0x [temp.dep.type]). - unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, true); - DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = Current->lookup(Name); I != E; ++I) - if (isAcceptableLookupResult(*I, NameKind, IDNS)) - return LookupResult::CreateLookupResult(Context, I, E); + if (DC->isDependentContext()) { + // If this is a dependent context, then we are looking for a member of + // the current instantiation. This is a narrow search that looks into + // just the described declaration context (C++0x [temp.dep.type]). + unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, + true); + DeclContext::lookup_iterator I, E; + for (llvm::tie(I, E) = DC->lookup(Name); I != E; ++I) + if (isAcceptableLookupResult(*I, NameKind, IDNS)) + return LookupResult::CreateLookupResult(Context, I, E); + } + + // Qualified name lookup into the named declaration context. + // The declaration context must be complete. + if (RequireCompleteDeclContext(*SS)) + return LookupResult::CreateLookupResult(Context, 0); + + return LookupQualifiedName(DC, Name, NameKind, RedeclarationOnly); } - if (RequireCompleteDeclContext(*SS)) - return LookupResult::CreateLookupResult(Context, 0); - - return LookupQualifiedName(computeDeclContext(*SS), - Name, NameKind, RedeclarationOnly); + // We could not resolve the scope specified to a specific declaration + // context, which means that SS refers to an unknown specialization. + // Name lookup can't find anything in this case. + return LookupResult::CreateLookupResult(Context, 0); } - LookupResult result(LookupName(S, Name, NameKind, RedeclarationOnly, - AllowBuiltinCreation, Loc)); - - return(result); + // Perform unqualified name lookup starting in the given scope. + return LookupName(S, Name, NameKind, RedeclarationOnly, AllowBuiltinCreation, + Loc); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9dfa96288cc..e0798f685ba 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -27,10 +27,19 @@ using namespace clang; /// passed to indicate the C++ scope in which the identifier will be /// found. TemplateNameKind Sema::isTemplateName(const IdentifierInfo &II, Scope *S, - TemplateTy &TemplateResult, - const CXXScopeSpec *SS) { - NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName); - + const CXXScopeSpec *SS, + bool EnteringContext, + TemplateTy &TemplateResult) { + LookupResult Found = LookupParsedName(S, SS, &II, LookupOrdinaryName, + false, false, SourceLocation(), + EnteringContext); + + // FIXME: Cope with ambiguous name-lookup results. + assert(!Found.isAmbiguous() && + "Cannot handle template name-lookup ambiguities"); + + NamedDecl *IIDecl = Found; + TemplateNameKind TNK = TNK_Non_template; TemplateDecl *Template = 0; @@ -1116,7 +1125,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, // "template" keyword is now permitted). We follow the C++0x // rules, even in C++03 mode, retroactively applying the DR. TemplateTy Template; - TemplateNameKind TNK = isTemplateName(Name, 0, Template, &SS); + TemplateNameKind TNK = isTemplateName(Name, 0, &SS, false, Template); if (TNK == TNK_Non_template) { Diag(NameLoc, diag::err_template_kw_refers_to_non_template) << &Name; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8220ec33c2b..5d34e07303d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4378,7 +4378,8 @@ TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, SS.setScopeRep(Prefix); return static_cast( SemaRef.ActOnCXXNestedNameSpecifier(0, SS, Range.getEnd(), - Range.getEnd(), II)); + Range.getEnd(), II, + false)); } template @@ -4435,7 +4436,7 @@ TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, SS.setRange(SourceRange(getDerived().getBaseLocation())); SS.setScopeRep(Qualifier); Sema::TemplateTy Template; - TemplateNameKind TNK = SemaRef.isTemplateName(II, 0, Template, &SS); + TemplateNameKind TNK = SemaRef.isTemplateName(II, 0, &SS, false, Template); if (TNK == TNK_Non_template) { SemaRef.Diag(getDerived().getBaseLocation(), diag::err_template_kw_refers_to_non_template) -- cgit v1.2.3