1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "TestVisitor.h" |
10 | |
11 | using namespace clang; |
12 | |
13 | namespace { |
14 | |
15 | |
16 | class NestedNameSpecifiersVisitor |
17 | : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> { |
18 | public: |
19 | bool VisitRecordTypeLoc(RecordTypeLoc RTL) { |
20 | if (!RTL) |
21 | return true; |
22 | Match(RTL.getDecl()->getName(), RTL.getNameLoc()); |
23 | return true; |
24 | } |
25 | |
26 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { |
27 | if (!NNS) |
28 | return true; |
29 | if (const NamespaceDecl *ND = |
30 | NNS.getNestedNameSpecifier()->getAsNamespace()) |
31 | Match(ND->getName(), NNS.getLocalBeginLoc()); |
32 | return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS); |
33 | } |
34 | }; |
35 | |
36 | TEST(RecursiveASTVisitor, |
37 | NestedNameSpecifiersForTemplateSpecializationsAreVisited) { |
38 | StringRef Source = R"( |
39 | namespace ns { |
40 | struct Outer { |
41 | template<typename T, typename U> |
42 | struct Nested { }; |
43 | |
44 | template<typename T> |
45 | static T x; |
46 | }; |
47 | } |
48 | |
49 | template<> |
50 | struct ns::Outer::Nested<int, int>; |
51 | |
52 | template<> |
53 | struct ns::Outer::Nested<int, int> { }; |
54 | |
55 | template<typename T> |
56 | struct ns::Outer::Nested<int, T> { }; |
57 | |
58 | template<> |
59 | int ns::Outer::x<int> = 0; |
60 | )"; |
61 | NestedNameSpecifiersVisitor Visitor; |
62 | Visitor.ExpectMatch("ns", 13, 8); |
63 | Visitor.ExpectMatch("ns", 16, 8); |
64 | Visitor.ExpectMatch("ns", 19, 8); |
65 | Visitor.ExpectMatch("ns", 22, 5); |
66 | Visitor.ExpectMatch("Outer", 13, 12); |
67 | Visitor.ExpectMatch("Outer", 16, 12); |
68 | Visitor.ExpectMatch("Outer", 19, 12); |
69 | Visitor.ExpectMatch("Outer", 22, 9); |
70 | EXPECT_TRUE(Visitor.runOver(Source, NestedNameSpecifiersVisitor::Lang_CXX14)); |
71 | } |
72 | |
73 | } |
74 | |