[DebugInfo] Limit the number of values that may be referenced by a dbg.value
[llvm-project.git] / clang / unittests / Tooling / LookupTest.cpp
blob05494cb42d904ede0e1a28d6fa2dbd69819caad7
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 using namespace clang;
13 namespace {
14 struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
15 std::function<void(CallExpr *)> OnCall;
16 std::function<void(RecordTypeLoc)> OnRecordTypeLoc;
17 SmallVector<Decl *, 4> DeclStack;
19 bool VisitCallExpr(CallExpr *Expr) {
20 if (OnCall)
21 OnCall(Expr);
22 return true;
25 bool VisitRecordTypeLoc(RecordTypeLoc Loc) {
26 if (OnRecordTypeLoc)
27 OnRecordTypeLoc(Loc);
28 return true;
31 bool TraverseDecl(Decl *D) {
32 DeclStack.push_back(D);
33 bool Ret = TestVisitor::TraverseDecl(D);
34 DeclStack.pop_back();
35 return Ret;
39 TEST(LookupTest, replaceNestedFunctionName) {
40 GetDeclsVisitor Visitor;
42 auto replaceCallExpr = [&](const CallExpr *Expr,
43 StringRef ReplacementString) {
44 const auto *Callee = cast<DeclRefExpr>(Expr->getCallee()->IgnoreImplicit());
45 const ValueDecl *FD = Callee->getDecl();
46 return tooling::replaceNestedName(
47 Callee->getQualifier(), Callee->getLocation(),
48 Visitor.DeclStack.back()->getDeclContext(), FD, ReplacementString);
51 Visitor.OnCall = [&](CallExpr *Expr) {
52 EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
54 Visitor.runOver("namespace a { void foo(); }\n"
55 "namespace a { void f() { foo(); } }\n");
57 Visitor.OnCall = [&](CallExpr *Expr) {
58 EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
60 Visitor.runOver("namespace a { void foo(); }\n"
61 "namespace a { void f() { foo(); } }\n");
63 Visitor.OnCall = [&](CallExpr *Expr) {
64 EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
66 Visitor.runOver("namespace a { void foo(); }\n"
67 "namespace b { void f() { a::foo(); } }\n");
69 Visitor.OnCall = [&](CallExpr *Expr) {
70 EXPECT_EQ("::a::bar", replaceCallExpr(Expr, "::a::bar"));
72 Visitor.runOver("namespace a { void foo(); }\n"
73 "namespace b { namespace a { void foo(); }\n"
74 "void f() { a::foo(); } }\n");
76 Visitor.OnCall = [&](CallExpr *Expr) {
77 EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
79 Visitor.runOver("namespace a { namespace b { void foo(); }\n"
80 "void f() { b::foo(); } }\n");
82 Visitor.OnCall = [&](CallExpr *Expr) {
83 EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
85 Visitor.runOver("namespace a { namespace b { void foo(); }\n"
86 "void f() { b::foo(); } }\n");
88 Visitor.OnCall = [&](CallExpr *Expr) {
89 EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
91 Visitor.runOver("void foo(); void f() { foo(); }\n");
93 Visitor.OnCall = [&](CallExpr *Expr) {
94 EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
96 Visitor.runOver("void foo(); void f() { ::foo(); }\n");
98 Visitor.OnCall = [&](CallExpr *Expr) {
99 EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
101 Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
103 Visitor.OnCall = [&](CallExpr *Expr) {
104 EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
106 Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
108 Visitor.OnCall = [&](CallExpr *Expr) {
109 EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
111 Visitor.runOver(
112 "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
114 Visitor.OnCall = [&](CallExpr *Expr) {
115 EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
117 Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
118 "namespace a { namespace b { namespace {"
119 "void f() { foo(); }"
120 "} } }\n");
122 Visitor.OnCall = [&](CallExpr *Expr) {
123 EXPECT_EQ("x::bar", replaceCallExpr(Expr, "::a::x::bar"));
125 Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
126 "namespace a { namespace b { namespace c {"
127 "void f() { foo(); }"
128 "} } }\n");
130 // If the shortest name is ambiguous, we need to add more qualifiers.
131 Visitor.OnCall = [&](CallExpr *Expr) {
132 EXPECT_EQ("a::y::bar", replaceCallExpr(Expr, "::a::y::bar"));
134 Visitor.runOver(R"(
135 namespace a {
136 namespace b {
137 namespace x { void foo() {} }
138 namespace y { void foo() {} }
142 namespace a {
143 namespace b {
144 void f() { x::foo(); }
146 })");
148 Visitor.OnCall = [&](CallExpr *Expr) {
149 // y::bar would be ambiguous due to "a::b::y".
150 EXPECT_EQ("::y::bar", replaceCallExpr(Expr, "::y::bar"));
152 Visitor.runOver(R"(
153 namespace a {
154 namespace b {
155 void foo() {}
156 namespace y { }
160 namespace a {
161 namespace b {
162 void f() { foo(); }
164 })");
166 Visitor.OnCall = [&](CallExpr *Expr) {
167 EXPECT_EQ("y::bar", replaceCallExpr(Expr, "::y::bar"));
169 Visitor.runOver(R"(
170 namespace a {
171 namespace b {
172 namespace x { void foo() {} }
173 namespace y { void foo() {} }
177 void f() { a::b::x::foo(); }
178 )");
181 TEST(LookupTest, replaceNestedClassName) {
182 GetDeclsVisitor Visitor;
184 auto replaceRecordTypeLoc = [&](RecordTypeLoc TLoc,
185 StringRef ReplacementString) {
186 const auto *FD = cast<CXXRecordDecl>(TLoc.getDecl());
187 return tooling::replaceNestedName(
188 nullptr, TLoc.getBeginLoc(), Visitor.DeclStack.back()->getDeclContext(),
189 FD, ReplacementString);
192 Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
193 // Filter Types by name since there are other `RecordTypeLoc` in the test
194 // file.
195 if (Type.getDecl()->getQualifiedNameAsString() == "a::b::Foo") {
196 EXPECT_EQ("x::Bar", replaceRecordTypeLoc(Type, "::a::x::Bar"));
199 Visitor.runOver("namespace a { namespace b {\n"
200 "class Foo;\n"
201 "namespace c { Foo f();; }\n"
202 "} }\n");
204 Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
205 // Filter Types by name since there are other `RecordTypeLoc` in the test
206 // file.
207 // `a::b::Foo` in using shadow decl is not `TypeLoc`.
208 if (Type.getDecl()->getQualifiedNameAsString() == "a::b::Foo") {
209 EXPECT_EQ("Bar", replaceRecordTypeLoc(Type, "::a::x::Bar"));
212 Visitor.runOver("namespace a { namespace b { class Foo {}; } }\n"
213 "namespace c { using a::b::Foo; Foo f();; }\n");
215 // Rename TypeLoc `x::y::Old` to new name `x::Foo` at [0] and check that the
216 // type is replaced with "Foo" instead of "x::Foo". Although there is a symbol
217 // `x::y::Foo` in c.cc [1], it should not make "Foo" at [0] ambiguous because
218 // it's not visible at [0].
219 Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
220 if (Type.getDecl()->getQualifiedNameAsString() == "x::y::Old") {
221 EXPECT_EQ("Foo", replaceRecordTypeLoc(Type, "::x::Foo"));
224 Visitor.runOver(R"(
225 // a.h
226 namespace x {
227 namespace y {
228 class Old {};
229 class Other {};
233 // b.h
234 namespace x {
235 namespace y {
236 // This is to be renamed to x::Foo
237 // The expected replacement is "Foo".
238 Old f; // [0].
242 // c.cc
243 namespace x {
244 namespace y {
245 using Foo = ::x::y::Other; // [1]
248 )");
251 } // end anonymous namespace