1d488daa0SDavid Zarzycki //===- unittest/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp -===//
2d488daa0SDavid Zarzycki //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d488daa0SDavid Zarzycki //
7d488daa0SDavid Zarzycki //===----------------------------------------------------------------------===//
8d488daa0SDavid Zarzycki
9d488daa0SDavid Zarzycki #include "TestVisitor.h"
10d488daa0SDavid Zarzycki
11d488daa0SDavid Zarzycki using namespace clang;
12d488daa0SDavid Zarzycki
13d488daa0SDavid Zarzycki namespace {
14d488daa0SDavid Zarzycki
15d488daa0SDavid Zarzycki // Check to ensure that nested name specifiers are visited.
16d488daa0SDavid Zarzycki class NestedNameSpecifiersVisitor
17d488daa0SDavid Zarzycki : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
18d488daa0SDavid Zarzycki public:
VisitRecordTypeLoc(RecordTypeLoc RTL)19d488daa0SDavid Zarzycki bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
20d488daa0SDavid Zarzycki if (!RTL)
21d488daa0SDavid Zarzycki return true;
22d488daa0SDavid Zarzycki Match(RTL.getDecl()->getName(), RTL.getNameLoc());
23d488daa0SDavid Zarzycki return true;
24d488daa0SDavid Zarzycki }
25d488daa0SDavid Zarzycki
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)26d488daa0SDavid Zarzycki bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
27d488daa0SDavid Zarzycki if (!NNS)
28d488daa0SDavid Zarzycki return true;
29d488daa0SDavid Zarzycki if (const NamespaceDecl *ND =
30d488daa0SDavid Zarzycki NNS.getNestedNameSpecifier()->getAsNamespace())
31d488daa0SDavid Zarzycki Match(ND->getName(), NNS.getLocalBeginLoc());
32d488daa0SDavid Zarzycki return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS);
33d488daa0SDavid Zarzycki }
34d488daa0SDavid Zarzycki };
35d488daa0SDavid Zarzycki
TEST(RecursiveASTVisitor,NestedNameSpecifiersForTemplateSpecializationsAreVisited)36d488daa0SDavid Zarzycki TEST(RecursiveASTVisitor,
37d488daa0SDavid Zarzycki NestedNameSpecifiersForTemplateSpecializationsAreVisited) {
38d488daa0SDavid Zarzycki StringRef Source = R"(
39d488daa0SDavid Zarzycki namespace ns {
40d488daa0SDavid Zarzycki struct Outer {
41d488daa0SDavid Zarzycki template<typename T, typename U>
42d488daa0SDavid Zarzycki struct Nested { };
43d488daa0SDavid Zarzycki
44d488daa0SDavid Zarzycki template<typename T>
45d488daa0SDavid Zarzycki static T x;
46d488daa0SDavid Zarzycki };
47d488daa0SDavid Zarzycki }
48d488daa0SDavid Zarzycki
49d488daa0SDavid Zarzycki template<>
50d488daa0SDavid Zarzycki struct ns::Outer::Nested<int, int>;
51d488daa0SDavid Zarzycki
52d488daa0SDavid Zarzycki template<>
53d488daa0SDavid Zarzycki struct ns::Outer::Nested<int, int> { };
54d488daa0SDavid Zarzycki
55d488daa0SDavid Zarzycki template<typename T>
56d488daa0SDavid Zarzycki struct ns::Outer::Nested<int, T> { };
57d488daa0SDavid Zarzycki
58d488daa0SDavid Zarzycki template<>
59d488daa0SDavid Zarzycki int ns::Outer::x<int> = 0;
60d488daa0SDavid Zarzycki )";
61d488daa0SDavid Zarzycki NestedNameSpecifiersVisitor Visitor;
62d488daa0SDavid Zarzycki Visitor.ExpectMatch("ns", 13, 8);
63d488daa0SDavid Zarzycki Visitor.ExpectMatch("ns", 16, 8);
64d488daa0SDavid Zarzycki Visitor.ExpectMatch("ns", 19, 8);
65d488daa0SDavid Zarzycki Visitor.ExpectMatch("ns", 22, 5);
66d488daa0SDavid Zarzycki Visitor.ExpectMatch("Outer", 13, 12);
67d488daa0SDavid Zarzycki Visitor.ExpectMatch("Outer", 16, 12);
68d488daa0SDavid Zarzycki Visitor.ExpectMatch("Outer", 19, 12);
69d488daa0SDavid Zarzycki Visitor.ExpectMatch("Outer", 22, 9);
70d488daa0SDavid Zarzycki EXPECT_TRUE(Visitor.runOver(Source, NestedNameSpecifiersVisitor::Lang_CXX14));
71d488daa0SDavid Zarzycki }
72d488daa0SDavid Zarzycki
73d488daa0SDavid Zarzycki } // end anonymous namespace
74