[clang-tools-extra] r282146 - [change-namespace] fix qualifier of function references.

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 22 04:54:01 PDT 2016


Author: ioeric
Date: Thu Sep 22 06:54:00 2016
New Revision: 282146

URL: http://llvm.org/viewvc/llvm-project?rev=282146&view=rev
Log:
[change-namespace] fix qualifier of function references.

Reviewers: hokein

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D24803

Modified:
    clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
    clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp

Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp?rev=282146&r1=282145&r2=282146&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Thu Sep 22 06:54:00 2016
@@ -231,7 +231,6 @@ ChangeNamespaceTool::ChangeNamespaceTool
 }
 
 // FIXME: handle the following symbols:
-//   - Function references.
 //   - Variable references.
 void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
   // Match old namespace blocks.
@@ -283,6 +282,22 @@ void ChangeNamespaceTool::registerMatche
                              hasDeclaration(DeclMatcher.bind("from_decl"))))))
                          .bind("nested_specifier_loc"),
                      this);
+
+  // Handle function.
+  // Only handle functions that are defined in a namespace excluding static
+  // methods (qualified by nested specifier) and functions defined in the global
+  // namespace.
+  // Note that the matcher does not exclude calls to out-of-line static method
+  // definitions, so we need to exclude them in the callback handler.
+  auto FuncMatcher = functionDecl(
+      hasParent(namespaceDecl()),
+      unless(anyOf(IsInMovedNs, hasAncestor(namespaceDecl(isAnonymous())),
+                   hasAncestor(cxxRecordDecl()))));
+  Finder->addMatcher(
+      decl(forEachDescendant(callExpr(callee(FuncMatcher)).bind("call")),
+           IsInMovedNs)
+          .bind("dc"),
+      this);
 }
 
 void ChangeNamespaceTool::run(
@@ -301,11 +316,26 @@ void ChangeNamespaceTool::run(
     SourceLocation Start = Specifier->getBeginLoc();
     SourceLocation End = EndLocationForType(Specifier->getTypeLoc());
     fixTypeLoc(Result, Start, End, Specifier->getTypeLoc());
-  } else {
-    const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type");
-    assert(TLoc != nullptr && "Expecting callback for TypeLoc");
+  } else if (const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type")) {
     fixTypeLoc(Result, startLocationForType(*TLoc), EndLocationForType(*TLoc),
                *TLoc);
+  } else {
+    const auto* Call = Result.Nodes.getNodeAs<clang::CallExpr>("call");
+    assert(Call != nullptr &&"Expecting callback for CallExpr.");
+    const clang::FunctionDecl* Func = Call->getDirectCallee();
+    assert(Func != nullptr);
+    // Ignore out-of-line static methods since they will be handled by nested
+    // name specifiers.
+    if (Func->getCanonicalDecl()->getStorageClass() ==
+            clang::StorageClass::SC_Static &&
+        Func->isOutOfLine())
+      return;
+    std::string Name = Func->getQualifiedNameAsString();
+    const clang::Decl *Context = Result.Nodes.getNodeAs<clang::Decl>("dc");
+    assert(Context && "Empty decl context.");
+    clang::SourceRange CalleeRange = Call->getCallee()->getSourceRange();
+    replaceQualifiedSymbolInDeclContext(Result, Context, CalleeRange.getBegin(),
+                                        CalleeRange.getEnd(), Name);
   }
 }
 

Modified: clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp?rev=282146&r1=282145&r2=282146&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Thu Sep 22 06:54:00 2016
@@ -314,6 +314,43 @@ TEST_F(ChangeNamespaceTest, TypeInNested
   EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
 }
 
+TEST_F(ChangeNamespaceTest, FixFunctionNameSpecifiers) {
+  std::string Code =
+      "namespace na {\n"
+      "class A {\n"
+      "public:\n"
+      "  static void f() {}\n"
+      "  static void g();\n"
+      "};\n"
+      "void A::g() {}"
+      "void a_f() {}\n"
+      "static void static_f() {}\n"
+      "namespace nb {\n"
+      "void f() { a_f(); static_f(); A::f(); }\n"
+      "void g() { f(); A::g(); }\n"
+      "}  // namespace nb\n"
+      "}  // namespace na\n";
+  std::string Expected =
+      "namespace na {\n"
+      "class A {\n"
+      "public:\n"
+      "  static void f() {}\n"
+      "  static void g();\n"
+      "};\n"
+      "void A::g() {}"
+      "void a_f() {}\n"
+      "static void static_f() {}\n"
+      "\n"
+      "}  // namespace na\n"
+      "namespace x {\n"
+      "namespace y {\n"
+      "void f() { na::a_f(); na::static_f(); na::A::f(); }\n"
+      "void g() { f(); na::A::g(); }\n"
+      "}  // namespace y\n"
+      "}  // namespace x\n";
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
 } // anonymous namespace
 } // namespace change_namespace
 } // namespace clang




More information about the cfe-commits mailing list