summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-07-11 09:39:23 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-07-11 09:39:23 +0000
commit9c171406c63c4b60cf0cbae9949ce0b712d057ec (patch)
treeeedd8ee188195d57cc0cd27942bc11835122a9f1
parentc1ace40bf9ed6a8972c28828444d58d16d960e07 (diff)
downloadbcm5719-llvm-9c171406c63c4b60cf0cbae9949ce0b712d057ec.tar.gz
bcm5719-llvm-9c171406c63c4b60cf0cbae9949ce0b712d057ec.zip
RecursiveASTVisitor should visit the nested name qualifiers in
a template specialisation rdar://33123354 Differential Revision: https://reviews.llvm.org/D34981 llvm-svn: 307638
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h1
-rw-r--r--clang/unittests/Tooling/RecursiveASTVisitorTest.cpp58
2 files changed, 59 insertions, 0 deletions
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 152e05bca74..917b240428e 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1799,6 +1799,7 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
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 \
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp
index 74c9c3db34d..63dbd147545 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -244,4 +244,62 @@ TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) {
InitListExprPostOrderNoQueueVisitor::Lang_C));
}
+// Check to ensure that nested name specifiers are visited.
+class NestedNameSpecifiersVisitor
+ : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
+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,
+ NestedNameSpecifiersForTemplateSpecializationsAreVisited) {
+ StringRef Source = R"(
+namespace ns {
+struct Outer {
+ template<typename T, typename U>
+ struct Nested { };
+
+ template<typename T>
+ static T x;
+};
+}
+
+template<>
+struct ns::Outer::Nested<int, int>;
+
+template<>
+struct ns::Outer::Nested<int, int> { };
+
+template<typename T>
+struct ns::Outer::Nested<int, T> { };
+
+template<>
+int ns::Outer::x<int> = 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
OpenPOWER on IntegriCloud