From: Douglas Gregor Date: Wed, 2 Mar 2011 17:09:35 +0000 (+0000) Subject: Push nested-name-specifier source location information into template X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b6744efecba58792cce20d2d7b9ee39927c5422e;p=clang Push nested-name-specifier source location information into template template arguments. I believe that this is the last place in the AST where we were storing a source range for a nested-name-specifier rather than a proper nested-name-specifier location structure. (Yay!) There is still a lot of cleanup to do in the TreeTransform, which doesn't take advantage of nested-name-specifiers with source-location information everywhere it could. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126844 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 9abb78bbf3..daa61c93d6 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -606,6 +606,9 @@ bool RecursiveASTVisitor::TraverseTemplateArgumentLoc( case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: + if (ArgLoc.getTemplateQualifierLoc()) + TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( + ArgLoc.getTemplateQualifierLoc())); return getDerived().TraverseTemplateName( Arg.getAsTemplateOrTemplatePattern()); diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index a4e074e083..821b4fcbb1 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -362,7 +362,10 @@ private: Expr *Expression; TypeSourceInfo *Declarator; struct { - unsigned QualifierRange[2]; + // FIXME: We'd like to just use the qualifier in the TemplateName, + // but template arguments get canonicalized too quickly. + NestedNameSpecifier *Qualifier; + void *QualifierLocData; unsigned TemplateNameLoc; unsigned EllipsisLoc; } Template; @@ -375,12 +378,12 @@ public: TemplateArgumentLocInfo(Expr *E) : Expression(E) {} - TemplateArgumentLocInfo(SourceRange QualifierRange, + TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { - Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); - Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); + Template.QualifierLocData = QualifierLoc.getOpaqueData(); Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); } @@ -393,10 +396,9 @@ public: return Expression; } - SourceRange getTemplateQualifierRange() const { - return SourceRange( - SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), - SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + NestedNameSpecifierLoc getTemplateQualifierLoc() const { + return NestedNameSpecifierLoc(Template.Qualifier, + Template.QualifierLocData); } SourceLocation getTemplateNameLoc() const { @@ -433,11 +435,10 @@ public: } TemplateArgumentLoc(const TemplateArgument &Argument, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc = SourceLocation()) - : Argument(Argument), - LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) { + : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); } @@ -477,10 +478,10 @@ public: return LocInfo.getAsExpr(); } - SourceRange getTemplateQualifierRange() const { + NestedNameSpecifierLoc getTemplateQualifierLoc() const { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); - return LocInfo.getTemplateQualifierRange(); + return LocInfo.getTemplateQualifierLoc(); } SourceLocation getTemplateNameLoc() const { diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 1764f4ab1f..b57f10b0c6 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -356,14 +356,14 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { return SourceRange(); case TemplateArgument::Template: - if (getTemplateQualifierRange().isValid()) - return SourceRange(getTemplateQualifierRange().getBegin(), + if (getTemplateQualifierLoc()) + return SourceRange(getTemplateQualifierLoc().getBeginLoc(), getTemplateNameLoc()); return SourceRange(getTemplateNameLoc()); case TemplateArgument::TemplateExpansion: - if (getTemplateQualifierRange().isValid()) - return SourceRange(getTemplateQualifierRange().getBegin(), + if (getTemplateQualifierLoc()) + return SourceRange(getTemplateQualifierLoc().getBeginLoc(), getTemplateEllipsisLoc()); return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); @@ -425,7 +425,7 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, Ellipsis = getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); return TemplateArgumentLoc(Argument.getPackExpansionPattern(), - getTemplateQualifierRange(), + getTemplateQualifierLoc(), getTemplateNameLoc()); case TemplateArgument::Declaration: diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 4f066d2de2..d42f42ed15 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -291,13 +291,22 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, break; case TemplateArgument::Template: - ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, - SourceLocation()); - break; + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Args[i].getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); - case TemplateArgument::TemplateExpansion: - ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc); + ArgInfos[i] = TemplateArgumentLocInfo( + Builder.getWithLocInContext(Context), + Loc, + Args[i].getKind() == TemplateArgument::Template + ? SourceLocation() + : Loc); break; + } } } } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 0d290969db..90b0d7e29b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -469,7 +469,8 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, else TArg = Template; return TemplateArgumentLoc(TArg, - Arg.getScopeSpec().getRange(), + Arg.getScopeSpec().getWithLocInContext( + SemaRef.Context), Arg.getLocation(), Arg.getEllipsisLoc()); } @@ -2201,6 +2202,9 @@ SubstDefaultTemplateArgument(Sema &SemaRef, /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. /// +/// \param QualifierLoc The nested-name-specifier, with source-location +/// information, which will also be instantiated and updated. +/// /// \returns the substituted template argument, or NULL if an error occurred. static TemplateName SubstDefaultTemplateArgument(Sema &SemaRef, @@ -2208,7 +2212,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef, SourceLocation TemplateLoc, SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param, - llvm::SmallVectorImpl &Converted) { + llvm::SmallVectorImpl &Converted, + NestedNameSpecifierLoc &QualifierLoc) { TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted.data(), Converted.size()); @@ -2220,6 +2225,14 @@ SubstDefaultTemplateArgument(Sema &SemaRef, Converted.size(), SourceRange(TemplateLoc, RAngleLoc)); + // Substitute into the nested-name-specifier first, + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + AllTemplateArgs); + if (!QualifierLoc) + return TemplateName(); + } + return SemaRef.SubstTemplateName( Param->getDefaultArgument().getArgument().getAsTemplate(), Param->getDefaultArgument().getTemplateNameLoc(), @@ -2256,10 +2269,10 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, return TemplateArgumentLoc(); ExprResult Arg = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - NonTypeParm, - Converted); + TemplateLoc, + RAngleLoc, + NonTypeParm, + Converted); if (Arg.isInvalid()) return TemplateArgumentLoc(); @@ -2272,16 +2285,20 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (!TempTempParm->hasDefaultArgument()) return TemplateArgumentLoc(); + + NestedNameSpecifierLoc QualifierLoc + = TempTempParm->getDefaultArgument().getTemplateQualifierLoc(); TemplateName TName = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, TempTempParm, - Converted); + Converted, + QualifierLoc); if (TName.isNull()) return TemplateArgumentLoc(); return TemplateArgumentLoc(TemplateArgument(TName), - TempTempParm->getDefaultArgument().getTemplateQualifierRange(), + TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), TempTempParm->getDefaultArgument().getTemplateNameLoc()); } @@ -2392,11 +2409,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, DeclarationNameInfo NameInfo(DTN->getIdentifier(), Arg.getTemplateNameLoc()); - // FIXME: TemplateArgumentLoc should store a NestedNameSpecifierLoc - // for the template name. CXXScopeSpec SS; - SS.MakeTrivial(Context, DTN->getQualifier(), - Arg.getTemplateQualifierRange()); + SS.Adopt(Arg.getTemplateQualifierLoc()); Expr *E = DependentScopeDeclRefExpr::Create(Context, SS.getWithLocInContext(Context), NameInfo); @@ -2665,17 +2679,19 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, break; } + NestedNameSpecifierLoc QualifierLoc + = TempParm->getDefaultArgument().getTemplateQualifierLoc(); TemplateName Name = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, TempParm, - Converted); + Converted, + QualifierLoc); if (Name.isNull()) return true; - Arg = TemplateArgumentLoc(TemplateArgument(Name), - TempParm->getDefaultArgument().getTemplateQualifierRange(), - TempParm->getDefaultArgument().getTemplateNameLoc()); + Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc, + TempParm->getDefaultArgument().getTemplateNameLoc()); } // Introduce an instantiation record that describes where we are using diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 139fafb346..c3d4362a16 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1728,11 +1728,24 @@ getTrivialTemplateArgumentLoc(Sema &S, return TemplateArgumentLoc(TemplateArgument(E), E); } - case TemplateArgument::Template: - return TemplateArgumentLoc(Arg, SourceRange(), Loc); - - case TemplateArgument::TemplateExpansion: - return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc); + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + return TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(S.Context), + Loc); + + + return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context), + Loc, Loc); + } case TemplateArgument::Expression: return TemplateArgumentLoc(Arg, Arg.getAsExpr()); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index fe1e9aa9d2..ce633cde2a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2285,7 +2285,7 @@ public: return TemplateArgumentLoc(TemplateArgument( Pattern.getArgument().getAsTemplate(), NumExpansions), - Pattern.getTemplateQualifierRange(), + Pattern.getTemplateQualifierLoc(), Pattern.getTemplateNameLoc(), EllipsisLoc); @@ -2841,12 +2841,25 @@ void TreeTransform::InventTemplateArgumentLoc( break; case TemplateArgument::Template: - Output = TemplateArgumentLoc(Arg, SourceRange(), Loc); - break; - - case TemplateArgument::TemplateExpansion: - Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc); + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(SemaRef.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc); + else + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc, Loc); + break; + } case TemplateArgument::Expression: Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); @@ -2905,14 +2918,20 @@ bool TreeTransform::TransformTemplateArgument( } case TemplateArgument::Template: { + NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return true; + } + TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName()); TemplateName Template = getDerived().TransformTemplateName(Arg.getAsTemplate()); if (Template.isNull()) return true; - Output = TemplateArgumentLoc(TemplateArgument(Template), - Input.getTemplateQualifierRange(), + Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc, Input.getTemplateNameLoc()); return false; } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 8ac4c15bd3..98dd4c2fd6 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3678,16 +3678,18 @@ ASTReader::GetTemplateArgumentLocInfo(PerFileData &F, case TemplateArgument::Type: return GetTypeSourceInfo(F, Record, Index); case TemplateArgument::Template: { - SourceRange QualifierRange = ReadSourceRange(F, Record, Index); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, + Index); SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); - return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc, + return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, SourceLocation()); } case TemplateArgument::TemplateExpansion: { - SourceRange QualifierRange = ReadSourceRange(F, Record, Index); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, + Index); SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index); - return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc, + return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc); } case TemplateArgument::Null: diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index a8b203eb29..90849d77fa 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3246,11 +3246,11 @@ void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record); break; case TemplateArgument::Template: - AddSourceRange(Arg.getTemplateQualifierRange(), Record); + AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc(), Record); AddSourceLocation(Arg.getTemplateNameLoc(), Record); break; case TemplateArgument::TemplateExpansion: - AddSourceRange(Arg.getTemplateQualifierRange(), Record); + AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc(), Record); AddSourceLocation(Arg.getTemplateNameLoc(), Record); AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record); break; diff --git a/test/Index/annotate-nested-name-specifier.cpp b/test/Index/annotate-nested-name-specifier.cpp index 150a34af1b..b2f6a26e61 100644 --- a/test/Index/annotate-nested-name-specifier.cpp +++ b/test/Index/annotate-nested-name-specifier.cpp @@ -110,7 +110,23 @@ struct X6 { typedef class outer_alias::inner::vector::template rebind::other type4; }; -// RUN: c-index-test -test-annotate-tokens=%s:13:1:111:1 %s | FileCheck %s +namespace outer { + namespace inner { + template class TT> + struct apply_meta { + typedef typename TT::type type; + }; + } +} + +template +struct X7 { + typedef T T_type; + typedef U U_type; + typedef outer_alias::inner::apply_meta type; +}; + +// RUN: c-index-test -test-annotate-tokens=%s:13:1:128:1 %s | FileCheck %s // CHECK: Keyword: "using" [14:1 - 14:6] UsingDeclaration=vector[4:12] // CHECK: Identifier: "outer_alias" [14:7 - 14:18] NamespaceRef=outer_alias:10:11 @@ -404,3 +420,21 @@ struct X6 { // CHECK: Punctuation: "::" [110:72 - 110:74] TypedefDecl=type4:110:80 (Definition) // CHECK: Identifier: "other" [110:74 - 110:79] TypedefDecl=type4:110:80 (Definition) // CHECK: Identifier: "type4" [110:80 - 110:85] TypedefDecl=type4:110:80 (Definition) + +// Template template arguments +// CHECK: Keyword: "typedef" [126:3 - 126:10] ClassTemplate=X7:123:8 (Definition) +// CHECK: Identifier: "outer_alias" [126:11 - 126:22] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [126:22 - 126:24] TypedefDecl=type:126:74 (Definition) +// CHECK: Identifier: "inner" [126:24 - 126:29] NamespaceRef=inner:114:13 +// CHECK: Punctuation: "::" [126:29 - 126:31] TypedefDecl=type:126:74 (Definition) +// CHECK: Identifier: "apply_meta" [126:31 - 126:41] TemplateRef=apply_meta:116:12 +// CHECK: Punctuation: "<" [126:41 - 126:42] TypedefDecl=type:126:74 (Definition) +// CHECK: Identifier: "T_type" [126:42 - 126:48] TypeRef=T_type:124:13 +// CHECK: Punctuation: "," [126:48 - 126:49] TypedefDecl=type:126:74 (Definition) +// CHECK: Identifier: "U_type" [126:50 - 126:56] TypeRef=U_type:125:13 +// CHECK: Punctuation: "::" [126:56 - 126:58] TypedefDecl=type:126:74 (Definition) +// CHECK: Keyword: "template" [126:58 - 126:66] TypedefDecl=type:126:74 (Definition) +// CHECK: Identifier: "apply" [126:67 - 126:72] TypedefDecl=type:126:74 (Definition) +// CHECK: Punctuation: ">" [126:72 - 126:73] TypedefDecl=type:126:74 (Definition) +// CHECK: Identifier: "type" [126:74 - 126:78] TypedefDecl=type:126:74 (Definition) + diff --git a/test/SemaCXX/nested-name-spec-locations.cpp b/test/SemaCXX/nested-name-spec-locations.cpp index d543f335e7..6398e249a4 100644 --- a/test/SemaCXX/nested-name-spec-locations.cpp +++ b/test/SemaCXX/nested-name-spec-locations.cpp @@ -128,3 +128,21 @@ struct DependentTemplateSpecializationTypeTester4 { }; DependentTemplateSpecializationTypeTester4 DTSTCheck4; // expected-note{{in instantiation of template class}} + +template class TTP> +struct AcceptedTemplateTemplateParameter { +}; + +template +struct DependentTemplateTemplateArgumentTester { + typedef AcceptedTemplateTemplateParameter< + T:: + template apply< + typename add_reference::type + * // expected-error{{declared as a pointer to a reference of type}} + >:: + template X> + type; +}; + +DependentTemplateTemplateArgumentTester DTTACheck; // expected-note{{in instantiation of template class}} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 8a7dd4d7ea..ad3f1df105 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1319,6 +1319,9 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) { case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: + if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc())) + return true; + return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(), TAL.getTemplateNameLoc()); }