[libc++][Android] BuildKite CI: update Clang and sysroot versions (#116151)
[llvm-project.git] / clang / unittests / Tooling / LookupTest.cpp
blobacd1714a26e071ef8a783bf806ca86a78067d7fe
1 //===- unittest/Tooling/LookupTest.cpp ------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "clang/Tooling/Refactoring/Lookup.h"
10 #include "TestVisitor.h"
11 #include "clang/AST/TypeLoc.h"
12 #include "clang/Basic/SourceLocation.h"
13 using namespace clang;
15 namespace {
16 struct GetDeclsVisitor : TestVisitor {
17 std::function<void(CallExpr *)> OnCall;
18 std::function<void(RecordTypeLoc)> OnRecordTypeLoc;
19 std::function<void(UsingTypeLoc)> OnUsingTypeLoc;
20 SmallVector<Decl *, 4> DeclStack;
22 bool VisitCallExpr(CallExpr *Expr) override {
23 if (OnCall)
24 OnCall(Expr);
25 return true;
28 bool VisitRecordTypeLoc(RecordTypeLoc Loc) override {
29 if (OnRecordTypeLoc)
30 OnRecordTypeLoc(Loc);
31 return true;
34 bool VisitUsingTypeLoc(UsingTypeLoc Loc) override {
35 if (OnUsingTypeLoc)
36 OnUsingTypeLoc(Loc);
37 return true;
40 bool TraverseDecl(Decl *D) override {
41 DeclStack.push_back(D);
42 bool Ret = TestVisitor::TraverseDecl(D);
43 DeclStack.pop_back();
44 return Ret;
48 TEST(LookupTest, replaceNestedFunctionName) {
49 GetDeclsVisitor Visitor;
51 auto replaceCallExpr = [&](const CallExpr *Expr,
52 StringRef ReplacementString) {
53 const auto *Callee = cast<DeclRefExpr>(Expr->getCallee()->IgnoreImplicit());
54 const ValueDecl *FD = Callee->getDecl();
55 return tooling::replaceNestedName(
56 Callee->getQualifier(), Callee->getLocation(),
57 Visitor.DeclStack.back()->getDeclContext(), FD, ReplacementString);
60 Visitor.OnCall = [&](CallExpr *Expr) {
61 EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
63 Visitor.runOver("namespace a { void foo(); }\n"
64 "namespace a { void f() { foo(); } }\n");
66 Visitor.OnCall = [&](CallExpr *Expr) {
67 EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
69 Visitor.runOver("namespace a { void foo(); }\n"
70 "namespace a { void f() { foo(); } }\n");
72 Visitor.OnCall = [&](CallExpr *Expr) {
73 EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
75 Visitor.runOver("namespace a { void foo(); }\n"
76 "namespace b { void f() { a::foo(); } }\n");
78 Visitor.OnCall = [&](CallExpr *Expr) {
79 EXPECT_EQ("::a::bar", replaceCallExpr(Expr, "::a::bar"));
81 Visitor.runOver("namespace a { void foo(); }\n"
82 "namespace b { namespace a { void foo(); }\n"
83 "void f() { a::foo(); } }\n");
85 Visitor.OnCall = [&](CallExpr *Expr) {
86 EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
88 Visitor.runOver("namespace a { namespace b { void foo(); }\n"
89 "void f() { b::foo(); } }\n");
91 Visitor.OnCall = [&](CallExpr *Expr) {
92 EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
94 Visitor.runOver("namespace a { namespace b { void foo(); }\n"
95 "void f() { b::foo(); } }\n");
97 Visitor.OnCall = [&](CallExpr *Expr) {
98 EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
100 Visitor.runOver("void foo(); void f() { foo(); }\n");
102 Visitor.OnCall = [&](CallExpr *Expr) {
103 EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
105 Visitor.runOver("void foo(); void f() { ::foo(); }\n");
107 Visitor.OnCall = [&](CallExpr *Expr) {
108 EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
110 Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
112 Visitor.OnCall = [&](CallExpr *Expr) {
113 EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
115 Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
117 Visitor.OnCall = [&](CallExpr *Expr) {
118 EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
120 Visitor.runOver(
121 "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
123 Visitor.OnCall = [&](CallExpr *Expr) {
124 EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
126 Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
127 "namespace a { namespace b { namespace {"
128 "void f() { foo(); }"
129 "} } }\n");
131 Visitor.OnCall = [&](CallExpr *Expr) {
132 EXPECT_EQ("x::bar", replaceCallExpr(Expr, "::a::x::bar"));
134 Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
135 "namespace a { namespace b { namespace c {"
136 "void f() { foo(); }"
137 "} } }\n");
139 // If the shortest name is ambiguous, we need to add more qualifiers.
140 Visitor.OnCall = [&](CallExpr *Expr) {
141 EXPECT_EQ("a::y::bar", replaceCallExpr(Expr, "::a::y::bar"));
143 Visitor.runOver(R"(
144 namespace a {
145 namespace b {
146 namespace x { void foo() {} }
147 namespace y { void foo() {} }
151 namespace a {
152 namespace b {
153 void f() { x::foo(); }
155 })");
157 Visitor.OnCall = [&](CallExpr *Expr) {
158 // y::bar would be ambiguous due to "a::b::y".
159 EXPECT_EQ("::y::bar", replaceCallExpr(Expr, "::y::bar"));
161 Visitor.runOver(R"(
162 namespace a {
163 namespace b {
164 void foo() {}
165 namespace y { }
169 namespace a {
170 namespace b {
171 void f() { foo(); }
173 })");
175 Visitor.OnCall = [&](CallExpr *Expr) {
176 EXPECT_EQ("y::bar", replaceCallExpr(Expr, "::y::bar"));
178 Visitor.runOver(R"(
179 namespace a {
180 namespace b {
181 namespace x { void foo() {} }
182 namespace y { void foo() {} }
186 void f() { a::b::x::foo(); }
187 )");
190 TEST(LookupTest, replaceNestedClassName) {
191 GetDeclsVisitor Visitor;
193 auto replaceTypeLoc = [&](const NamedDecl *ND, SourceLocation Loc,
194 StringRef ReplacementString) {
195 return tooling::replaceNestedName(
196 nullptr, Loc, Visitor.DeclStack.back()->getDeclContext(), ND,
197 ReplacementString);
200 Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
201 // Filter Types by name since there are other `RecordTypeLoc` in the test
202 // file.
203 if (Type.getDecl()->getQualifiedNameAsString() == "a::b::Foo") {
204 EXPECT_EQ("x::Bar", replaceTypeLoc(Type.getDecl(), Type.getBeginLoc(),
205 "::a::x::Bar"));
208 Visitor.runOver("namespace a { namespace b {\n"
209 "class Foo;\n"
210 "namespace c { Foo f();; }\n"
211 "} }\n");
213 Visitor.OnUsingTypeLoc = [&](UsingTypeLoc Type) {
214 // Filter Types by name since there are other `RecordTypeLoc` in the test
215 // file.
216 // `a::b::Foo` in using shadow decl is not `TypeLoc`.
217 auto *TD = Type.getFoundDecl()->getTargetDecl();
218 if (TD->getQualifiedNameAsString() == "a::b::Foo") {
219 EXPECT_EQ("Bar", replaceTypeLoc(TD, Type.getBeginLoc(), "::a::x::Bar"));
222 Visitor.runOver("namespace a { namespace b { class Foo {}; } }\n"
223 "namespace c { using a::b::Foo; Foo f();; }\n");
225 // Rename TypeLoc `x::y::Old` to new name `x::Foo` at [0] and check that the
226 // type is replaced with "Foo" instead of "x::Foo". Although there is a symbol
227 // `x::y::Foo` in c.cc [1], it should not make "Foo" at [0] ambiguous because
228 // it's not visible at [0].
229 Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
230 if (Type.getDecl()->getQualifiedNameAsString() == "x::y::Old") {
231 EXPECT_EQ("Foo",
232 replaceTypeLoc(Type.getDecl(), Type.getBeginLoc(), "::x::Foo"));
235 Visitor.runOver(R"(
236 // a.h
237 namespace x {
238 namespace y {
239 class Old {};
240 class Other {};
244 // b.h
245 namespace x {
246 namespace y {
247 // This is to be renamed to x::Foo
248 // The expected replacement is "Foo".
249 Old f; // [0].
253 // c.cc
254 namespace x {
255 namespace y {
256 using Foo = ::x::y::Other; // [1]
259 )");
262 } // end anonymous namespace