Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -1799,6 +1799,7 @@ if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ \ + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ if (!getDerived().shouldVisitTemplateInstantiations() && \ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ /* Returning from here skips traversing the \ Index: unittests/Tooling/RecursiveASTVisitorTest.cpp =================================================================== --- unittests/Tooling/RecursiveASTVisitorTest.cpp +++ unittests/Tooling/RecursiveASTVisitorTest.cpp @@ -244,4 +244,62 @@ InitListExprPostOrderNoQueueVisitor::Lang_C)); } +// Check to ensure that nested name specifiers are visited. +class NestedNameSpecifiersVisitor + : public ExpectedLocationVisitor { +public: + bool VisitRecordTypeLoc(RecordTypeLoc RTL) { + if (!RTL) + return true; + Match(RTL.getDecl()->getName(), RTL.getNameLoc()); + return true; + } + + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + if (!NNS) + return true; + if (const NamespaceDecl *ND = + NNS.getNestedNameSpecifier()->getAsNamespace()) + Match(ND->getName(), NNS.getLocalBeginLoc()); + return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS); + } +}; + +TEST(RecursiveASTVisitor, + NestedNameSpecifiersForTemplateSpecializatoinsAreVisited) { + StringRef Source = R"( +namespace ns { +struct Outer { + template + struct Nested { }; + + template + static T x; +}; +} + +template<> +struct ns::Outer::Nested; + +template<> +struct ns::Outer::Nested { }; + +template +struct ns::Outer::Nested { }; + +template<> +int ns::Outer::x = 0; +)"; + NestedNameSpecifiersVisitor Visitor; + Visitor.ExpectMatch("ns", 13, 8); + Visitor.ExpectMatch("ns", 16, 8); + Visitor.ExpectMatch("ns", 19, 8); + Visitor.ExpectMatch("ns", 22, 5); + Visitor.ExpectMatch("Outer", 13, 12); + Visitor.ExpectMatch("Outer", 16, 12); + Visitor.ExpectMatch("Outer", 19, 12); + Visitor.ExpectMatch("Outer", 22, 9); + EXPECT_TRUE(Visitor.runOver(Source, NestedNameSpecifiersVisitor::Lang_CXX14)); +} + } // end anonymous namespace