From 94fdffa4a572fc14ac296f5f1aae9db3734c72f1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 1 Mar 2011 20:11:18 +0000 Subject: [PATCH] Push nested-name-specifier source-location information into dependent template specialization types. There are still a few rough edges to clean up with some of the parser actions dropping nested-name-specifiers too early. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126776 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/RecursiveASTVisitor.h | 5 +- include/clang/AST/TypeLoc.h | 44 ++++--- lib/AST/TypeLoc.cpp | 20 +++ lib/Sema/SemaCXXScopeSpec.cpp | 6 +- lib/Sema/SemaTemplate.cpp | 10 +- lib/Sema/SemaType.cpp | 3 +- lib/Sema/TreeTransform.h | 123 ++++++++++++++++-- lib/Serialization/ASTReader.cpp | 2 +- lib/Serialization/ASTWriter.cpp | 2 +- test/Index/annotate-nested-name-specifier.cpp | 46 ++++++- test/SemaCXX/nested-name-spec-locations.cpp | 25 ++++ tools/libclang/CIndex.cpp | 17 +++ 12 files changed, 260 insertions(+), 43 deletions(-) diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 972ff5c760..40acdab61c 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -999,7 +999,10 @@ DEF_TRAVERSE_TYPELOC(DependentNameType, { }) DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 591af2a02f..fe184bb6c8 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1501,10 +1501,8 @@ public: void initializeLocal(ASTContext &Context, SourceLocation Loc); }; -struct DependentTemplateSpecializationLocInfo { +struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { SourceLocation KeywordLoc; - SourceLocation NameLoc; - SourceRange QualifierRange; SourceLocation LAngleLoc; SourceLocation RAngleLoc; // followed by a TemplateArgumentLocInfo[] @@ -1523,11 +1521,28 @@ public: this->getLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + if (!getLocalData()->QualifierData) + return NestedNameSpecifierLoc(); + + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + if (!QualifierLoc) { + // Even if we have a nested-name-specifier in the dependent + // template specialization type, we won't record the nested-name-specifier + // location information when this type-source location information is + // part of a nested-name-specifier. + getLocalData()->QualifierData = 0; + return; + } + + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceLocation getNameLoc() const { @@ -1569,8 +1584,8 @@ public: SourceRange getLocalSourceRange() const { if (getKeywordLoc().isValid()) return SourceRange(getKeywordLoc(), getRAngleLoc()); - else if (getQualifierRange().isValid()) - return SourceRange(getQualifierRange().getBegin(), getRAngleLoc()); + else if (getQualifierLoc()) + return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); else return SourceRange(getNameLoc(), getRAngleLoc()); } @@ -1581,16 +1596,7 @@ public: memcpy(Data, Loc.Data, size); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - setNameLoc(Loc); - setLAngleLoc(Loc); - setRAngleLoc(Loc); - TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), - getTypePtr()->getArgs(), - getArgInfos(), Loc); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(TemplateArgumentLocInfo); diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 98c46621f0..ba7726b623 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -246,6 +246,26 @@ void DependentNameTypeLoc::initializeLocal(ASTContext &Context, setNameLoc(Loc); } +void +DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setKeywordLoc(Loc); + if (getTypePtr()->getQualifier()) { + NestedNameSpecifierLocBuilder Builder; + Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); + setQualifierLoc(Builder.getWithLocInContext(Context)); + } else { + setQualifierLoc(NestedNameSpecifierLoc()); + } + + setNameLoc(Loc); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), + getTypePtr()->getArgs(), + getArgInfos(), Loc); +} + void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, unsigned NumArgs, const TemplateArgument *Args, diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 6139aae555..d92f7599f2 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -663,8 +663,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, assert(DTN->getQualifier() == static_cast(SS.getScopeRep())); QualType T = Context.getDependentTemplateSpecializationType(ETK_None, - DTN->getQualifier(), - DTN->getIdentifier(), + DTN->getQualifier(), + DTN->getIdentifier(), TemplateArgs); // Create source-location information for this type. @@ -675,7 +675,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, SpecTL.setRAngleLoc(RAngleLoc); SpecTL.setKeywordLoc(SourceLocation()); SpecTL.setNameLoc(TemplateNameLoc); - SpecTL.setQualifierRange(SS.getRange()); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index a710f94436..16edbf76eb 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1767,7 +1767,11 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, SpecTL.setNameLoc(TemplateLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); - SpecTL.setQualifierRange(TemplateLoc); // FIXME: nested-name-specifier loc + + // FIXME: Poor nested-name-specifier source-location information. + CXXScopeSpec SS; + SS.MakeTrivial(Context, DTN->getQualifier(), TemplateLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); @@ -5967,12 +5971,10 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); SpecTL.setKeywordLoc(TypenameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); SpecTL.setNameLoc(TemplateNameLoc); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - - // FIXME: Nested-name-specifier source locations. - SpecTL.setQualifierRange(SS.getRange()); return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index afd118e2ca..a2f1a6b65a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2276,8 +2276,7 @@ namespace { ? DS.getTypeSpecTypeLoc() : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); - // FIXME: load appropriate source location. + TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(DS.getTypeSpecTypeLoc()); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 5485dfb7e4..bd1e67629a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -498,6 +498,11 @@ public: DependentTemplateSpecializationTypeLoc TL, NestedNameSpecifier *Prefix); + QualType + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc); + /// \brief Transforms the parameters of a function type into the /// given vectors. /// @@ -768,6 +773,48 @@ public: return SemaRef.Context.getElaboratedType(Keyword, Qualifier, T); } + /// \brief Build a new typename type that refers to a template-id. + /// + /// By default, builds a new DependentNameType type from the + /// nested-name-specifier and the given type. Subclasses may override + /// this routine to provide different behavior. + QualType RebuildDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo *Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &Args) { + // Rebuild the template name. + // TODO: avoid TemplateName abstraction + TemplateName InstName + = getDerived().RebuildTemplateName(QualifierLoc.getNestedNameSpecifier(), + QualifierLoc.getSourceRange(), *Name, + QualType(), 0); + + if (InstName.isNull()) + return QualType(); + + // If it's still dependent, make a dependent specialization. + if (InstName.getAsDependentTemplateName()) + return SemaRef.Context.getDependentTemplateSpecializationType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Name, + Args); + + // Otherwise, make an elaborated type wrapping a non-dependent + // specialization. + QualType T = + getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + if (T.isNull()) return QualType(); + + if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0) + return T; + + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + T); + } + /// \brief Build a new typename type that refers to an identifier. /// /// By default, performs semantic analysis when building the typename type @@ -4405,7 +4452,12 @@ QualType TreeTransform::TransformDependentTemplateSpecializationType( DependentTemplateSpecializationTypeLoc NewTL = TLB.push(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); + + // FIXME: Poor nested-name-specifier source-location information. + CXXScopeSpec SS; + SS.MakeTrivial(SemaRef.Context, + DTN->getQualifier(), TL.getQualifierLoc().getSourceRange()); + NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); NewTL.setNameLoc(TL.getNameLoc()); NewTL.setLAngleLoc(TL.getLAngleLoc()); NewTL.setRAngleLoc(TL.getRAngleLoc()); @@ -4567,18 +4619,16 @@ template QualType TreeTransform:: TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL) { - const DependentTemplateSpecializationType *T = TL.getTypePtr(); - - NestedNameSpecifier *NNS = 0; - if (T->getQualifier()) { - NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange()); - if (!NNS) + NestedNameSpecifierLoc QualifierLoc; + if (TL.getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) return QualType(); } return getDerived() - .TransformDependentTemplateSpecializationType(TLB, TL, NNS); + .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc); } template @@ -4586,6 +4636,7 @@ QualType TreeTransform:: TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL, NestedNameSpecifier *NNS) { + // FIXME: This routine needs to go away. const DependentTemplateSpecializationType *T = TL.getTypePtr(); TemplateArgumentListInfo NewTemplateArgs; @@ -4603,7 +4654,7 @@ QualType TreeTransform:: QualType Result = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(), NNS, - TL.getQualifierRange(), + TL.getQualifierLoc().getSourceRange(), T->getIdentifier(), TL.getNameLoc(), NewTemplateArgs); @@ -4628,7 +4679,8 @@ QualType TreeTransform:: // FIXME: DependentTemplateSpecializationType needs better source-location // info. NestedNameSpecifierLocBuilder Builder; - Builder.MakeTrivial(SemaRef.Context, NNS, TL.getQualifierRange()); + Builder.MakeTrivial(SemaRef.Context, + NNS, TL.getQualifierLoc().getSourceRange()); NewTL.setQualifierLoc(Builder.getWithLocInContext(SemaRef.Context)); } else { TypeLoc NewTL(Result, TL.getOpaqueData()); @@ -4637,6 +4689,55 @@ QualType TreeTransform:: return Result; } +template +QualType TreeTransform:: +TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc) { + const DependentTemplateSpecializationType *T = TL.getTypePtr(); + + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + + typedef TemplateArgumentLocContainerIterator< + DependentTemplateSpecializationTypeLoc> ArgIterator; + if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), + ArgIterator(TL, TL.getNumArgs()), + NewTemplateArgs)) + return QualType(); + + QualType Result + = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(), + QualifierLoc, + T->getIdentifier(), + TL.getNameLoc(), + NewTemplateArgs); + if (Result.isNull()) + return QualType(); + + if (const ElaboratedType *ElabT = dyn_cast(Result)) { + QualType NamedT = ElabT->getNamedType(); + + // Copy information relevant to the template specialization. + TemplateSpecializationTypeLoc NamedTL + = TLB.push(NamedT); + NamedTL.setLAngleLoc(TL.getLAngleLoc()); + NamedTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I)); + + // Copy information relevant to the elaborated type. + ElaboratedTypeLoc NewTL = TLB.push(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierLoc(QualifierLoc); + } else { + TypeLoc NewTL(Result, TL.getOpaqueData()); + TLB.pushFullCopy(NewTL); + } + return Result; +} + template QualType TreeTransform::TransformPackExpansionType(TypeLocBuilder &TLB, PackExpansionTypeLoc TL) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index aefc1d1b65..8ac4c15bd3 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3533,7 +3533,7 @@ void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); - TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx)); + TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); TL.setNameLoc(ReadSourceLocation(Record, Idx)); TL.setLAngleLoc(ReadSourceLocation(Record, Idx)); TL.setRAngleLoc(ReadSourceLocation(Record, Idx)); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index e9ad4a81b4..a8b203eb29 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -545,7 +545,7 @@ void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); Writer.AddSourceLocation(TL.getNameLoc(), Record); Writer.AddSourceLocation(TL.getLAngleLoc(), Record); Writer.AddSourceLocation(TL.getRAngleLoc(), Record); diff --git a/test/Index/annotate-nested-name-specifier.cpp b/test/Index/annotate-nested-name-specifier.cpp index beb0e40ac0..4b97f748db 100644 --- a/test/Index/annotate-nested-name-specifier.cpp +++ b/test/Index/annotate-nested-name-specifier.cpp @@ -101,7 +101,14 @@ struct X5 { typedef typename outer_alias::inner::vector::iterator int_ptr_type; }; -// RUN: c-index-test -test-annotate-tokens=%s:13:1:102:1 %s | FileCheck %s +template +struct X6 { + typedef T type; + typedef typename outer_alias::inner::vector::template rebind type1; + typedef typename outer_alias::inner::vector::template rebind::other type2; +}; + +// RUN: c-index-test -test-annotate-tokens=%s:13:1:109: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 @@ -321,3 +328,40 @@ struct X5 { // CHECK: Identifier: "iterator" [101:53 - 101:61] TypeRef=iterator:5:18 // CHECK: Identifier: "int_ptr_type" [101:62 - 101:74] TypedefDecl=int_ptr_type:101:62 (Definition) +// Dependent template specialization types +// CHECK: Keyword: "typename" [107:11 - 107:19] TypedefDecl=type1:107:76 (Definition) +// CHECK: Identifier: "outer_alias" [107:20 - 107:31] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [107:31 - 107:33] TypedefDecl=type1:107:76 (Definition) +// CHECK: Identifier: "inner" [107:33 - 107:38] NamespaceRef=inner:62:13 +// CHECK: Punctuation: "::" [107:38 - 107:40] TypedefDecl=type1:107:76 (Definition) +// CHECK: Identifier: "vector" [107:40 - 107:46] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [107:46 - 107:47] TypedefDecl=type1:107:76 (Definition) +// CHECK: Identifier: "type" [107:47 - 107:51] TypeRef=type:106:13 +// CHECK: Punctuation: ">" [107:51 - 107:52] TypedefDecl=type1:107:76 (Definition) +// CHECK: Punctuation: "::" [107:52 - 107:54] TypedefDecl=type1:107:76 (Definition) +// CHECK: Keyword: "template" [107:54 - 107:62] TypedefDecl=type1:107:76 (Definition) +// CHECK: Identifier: "rebind" [107:63 - 107:69] TypedefDecl=type1:107:76 (Definition) +// CHECK: Punctuation: "<" [107:69 - 107:70] TypedefDecl=type1:107:76 (Definition) +// CHECK: Identifier: "type" [107:70 - 107:74] TypeRef=type:106:13 +// CHECK: Punctuation: ">" [107:74 - 107:75] TypedefDecl=type1:107:76 (Definition) +// CHECK: Identifier: "type1" [107:76 - 107:81] TypedefDecl=type1:107:76 (Definition) + +// CHECK: Keyword: "typedef" [108:3 - 108:10] ClassTemplate=X6:105:8 (Definition) +// CHECK: Keyword: "typename" [108:11 - 108:19] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "outer_alias" [108:20 - 108:31] NamespaceRef=outer_alias:10:11 +// CHECK: Punctuation: "::" [108:31 - 108:33] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "inner" [108:33 - 108:38] NamespaceRef=inner:62:13 +// CHECK: Punctuation: "::" [108:38 - 108:40] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "vector" [108:40 - 108:46] TemplateRef=vector:4:12 +// CHECK: Punctuation: "<" [108:46 - 108:47] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "type" [108:47 - 108:51] TypeRef=type:106:13 +// CHECK: Punctuation: ">" [108:51 - 108:52] TypedefDecl=type2:108:83 (Definition) +// CHECK: Punctuation: "::" [108:52 - 108:54] TypedefDecl=type2:108:83 (Definition) +// CHECK: Keyword: "template" [108:54 - 108:62] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "rebind" [108:63 - 108:69] TypedefDecl=type2:108:83 (Definition) +// CHECK: Punctuation: "<" [108:69 - 108:70] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "type" [108:70 - 108:74] TypeRef=type:106:13 +// CHECK: Punctuation: ">" [108:74 - 108:75] TypedefDecl=type2:108:83 (Definition) +// CHECK: Punctuation: "::" [108:75 - 108:77] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "other" [108:77 - 108:82] TypedefDecl=type2:108:83 (Definition) +// CHECK: Identifier: "type2" [108:83 - 108:88] TypedefDecl=type2:108:83 (Definition) diff --git a/test/SemaCXX/nested-name-spec-locations.cpp b/test/SemaCXX/nested-name-spec-locations.cpp index 996b1cf50a..841937afc2 100644 --- a/test/SemaCXX/nested-name-spec-locations.cpp +++ b/test/SemaCXX/nested-name-spec-locations.cpp @@ -85,3 +85,28 @@ struct TypenameTypeTester { }; TypenameTypeTester TypenameTypeCheck; // expected-note{{in instantiation of template class}} + +template +struct DependentTemplateSpecializationTypeTester { + typedef typename T::template apply::type + * // expected-error{{declared as a pointer to a reference of type}} + >::type type; +}; + +struct HasApply { + template + struct apply { + typedef T type; + }; +}; + +DependentTemplateSpecializationTypeTester DTSTCheck; // expected-note{{in instantiation of template class}} + +template +struct DependentTemplateSpecializationTypeTester2 { + typedef typename T::template apply::type + * // expected-error{{declared as a pointer to a reference of type}} + > type; +}; + +DependentTemplateSpecializationTypeTester2 DTSTCheck2; // expected-note{{in instantiation of template class}} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 8c2111d4ad..8a7dd4d7ea 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -343,6 +343,8 @@ public: bool VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL); bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL); bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL); + bool VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL); bool VisitElaboratedTypeLoc(ElaboratedTypeLoc TL); // Data-recursive visitor functions. @@ -1512,6 +1514,21 @@ bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { return false; } +bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + // Visit the nested-name-specifier, if there is one. + if (TL.getQualifierLoc() && + VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) + return true; + + // Visit the template arguments. + for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I) + if (VisitTemplateArgumentLoc(TL.getArgLoc(I))) + return true; + + return false; +} + bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) return true; -- 2.40.0