summaryrefslogtreecommitdiffstats
path: root/clang/unittests/Tooling
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2015-10-22 15:04:10 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2015-10-22 15:04:10 +0000
commit9bccaa158a8424b7f74e75d7cb1878f2a4b6826a (patch)
tree147810be8d24191ee0d3df68c339cfb63700fb3f /clang/unittests/Tooling
parent8f9e44406165c1f57e0b28ba159cace972220921 (diff)
downloadbcm5719-llvm-9bccaa158a8424b7f74e75d7cb1878f2a4b6826a.tar.gz
bcm5719-llvm-9bccaa158a8424b7f74e75d7cb1878f2a4b6826a.zip
[Tooling] Add a utility function to replace one nested name with another.
One problem in clang-tidy and other clang tools face is that there is no way to lookup an arbitrary name in the AST, that's buried deep inside Sema and might not even be what the user wants as the new name may be freshly inserted and not available in the AST. A common use case for lookups is replacing one nested name with another while minimizing namespace qualifications, so replacing 'ns::foo' with 'ns::bar' will use just 'bar' if we happen to be inside the namespace 'ns'. This adds a little helper utility for exactly that use case. Differential Revision: http://reviews.llvm.org/D13931 llvm-svn: 251022
Diffstat (limited to 'clang/unittests/Tooling')
-rw-r--r--clang/unittests/Tooling/CMakeLists.txt1
-rw-r--r--clang/unittests/Tooling/LookupTest.cpp108
2 files changed, 109 insertions, 0 deletions
diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt
index 2ae3a3e31ed..33b2046ae92 100644
--- a/clang/unittests/Tooling/CMakeLists.txt
+++ b/clang/unittests/Tooling/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(ToolingTests
CommentHandlerTest.cpp
CompilationDatabaseTest.cpp
+ LookupTest.cpp
ToolingTest.cpp
RecursiveASTVisitorTest.cpp
RecursiveASTVisitorTestCallVisitor.cpp
diff --git a/clang/unittests/Tooling/LookupTest.cpp b/clang/unittests/Tooling/LookupTest.cpp
new file mode 100644
index 00000000000..d847a298fff
--- /dev/null
+++ b/clang/unittests/Tooling/LookupTest.cpp
@@ -0,0 +1,108 @@
+//===- unittest/Tooling/LookupTest.cpp ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include "clang/Tooling/Core/Lookup.h"
+using namespace clang;
+
+namespace {
+struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
+ std::function<void(CallExpr *)> OnCall;
+ SmallVector<Decl *, 4> DeclStack;
+
+ bool VisitCallExpr(CallExpr *Expr) {
+ OnCall(Expr);
+ return true;
+ }
+
+ bool TraverseDecl(Decl *D) {
+ DeclStack.push_back(D);
+ bool Ret = TestVisitor::TraverseDecl(D);
+ DeclStack.pop_back();
+ return Ret;
+ }
+};
+
+TEST(LookupTest, replaceNestedName) {
+ GetDeclsVisitor Visitor;
+
+ auto replaceCallExpr = [&](const CallExpr *Expr,
+ StringRef ReplacementString) {
+ const auto *Callee = cast<DeclRefExpr>(Expr->getCallee()->IgnoreImplicit());
+ const ValueDecl *FD = Callee->getDecl();
+ return tooling::replaceNestedName(
+ Callee->getQualifier(), Visitor.DeclStack.back()->getDeclContext(), FD,
+ ReplacementString);
+ };
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace a { void f() { foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace a { void f() { foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace b { void f() { a::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace b { namespace a { void foo(); }\n"
+ "void f() { a::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
+ };
+ Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+ "void f() { b::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+ "void f() { b::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+ };
+ Visitor.runOver("void foo(); void f() { foo(); }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
+ };
+ Visitor.runOver("void foo(); void f() { ::foo(); }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver(
+ "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
+}
+
+} // end anonymous namespace
OpenPOWER on IntegriCloud