[clang-tools-extra] r282837 - [change-namespace] fix namespace specifier of global variables.

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 29 21:32:40 PDT 2016


Author: ioeric
Date: Thu Sep 29 23:32:39 2016
New Revision: 282837

URL: http://llvm.org/viewvc/llvm-project?rev=282837&view=rev
Log:
[change-namespace] fix namespace specifier of global variables.

Reviewers: hokein

Subscribers: cfe-commits

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

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=282837&r1=282836&r2=282837&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Thu Sep 29 23:32:39 2016
@@ -230,8 +230,6 @@ ChangeNamespaceTool::ChangeNamespaceTool
   DiffNewNamespace = joinNamespaces(NewNsSplitted);
 }
 
-// FIXME: handle the following symbols:
-//   - Variable references.
 void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
   // Match old namespace blocks.
   std::string FullOldNs = "::" + OldNamespace;
@@ -303,6 +301,14 @@ void ChangeNamespaceTool::registerMatche
            IsInMovedNs, unless(isImplicit()))
           .bind("dc"),
       this);
+
+  auto GlobalVarMatcher = varDecl(
+      hasGlobalStorage(), hasParent(namespaceDecl()),
+      unless(anyOf(IsInMovedNs, hasAncestor(namespaceDecl(isAnonymous())))));
+  Finder->addMatcher(declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")),
+                                 to(GlobalVarMatcher.bind("var_decl")))
+                         .bind("var_ref"),
+                     this);
 }
 
 void ChangeNamespaceTool::run(
@@ -324,8 +330,19 @@ void ChangeNamespaceTool::run(
   } else if (const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type")) {
     fixTypeLoc(Result, startLocationForType(*TLoc), EndLocationForType(*TLoc),
                *TLoc);
+  } else if (const auto *VarRef = Result.Nodes.getNodeAs<DeclRefExpr>("var_ref")){
+    const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var_decl");
+    assert(Var);
+    if (Var->getCanonicalDecl()->isStaticDataMember())
+      return;
+    std::string Name = Var->getQualifiedNameAsString();
+    const clang::Decl *Context = Result.Nodes.getNodeAs<clang::Decl>("dc");
+    assert(Context && "Empty decl context.");
+    clang::SourceRange VarRefRange = VarRef->getSourceRange();
+    replaceQualifiedSymbolInDeclContext(Result, Context, VarRefRange.getBegin(),
+                                        VarRefRange.getEnd(), Name);
   } else {
-    const auto* Call = Result.Nodes.getNodeAs<clang::CallExpr>("call");
+    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);

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=282837&r1=282836&r2=282837&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Thu Sep 29 23:32:39 2016
@@ -447,6 +447,72 @@ TEST_F(ChangeNamespaceTest, FixFunctionN
   EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
 }
 
+TEST_F(ChangeNamespaceTest, MoveAndFixGlobalVariables) {
+  std::string Code = "namespace na {\n"
+                     "int GlobA;\n"
+                     "static int GlobAStatic = 0;\n"
+                     "namespace nc { int GlobC; }\n"
+                     "namespace nb {\n"
+                     "int GlobB;\n"
+                     "void f() {\n"
+                     "  int a = GlobA;\n"
+                     "  int b = GlobAStatic;\n"
+                     "  int c = nc::GlobC;\n"
+                     "}\n"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace na {\n"
+                         "int GlobA;\n"
+                         "static int GlobAStatic = 0;\n"
+                         "namespace nc { int GlobC; }\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "int GlobB;\n"
+                         "void f() {\n"
+                         "  int a = na::GlobA;\n"
+                         "  int b = na::GlobAStatic;\n"
+                         "  int c = na::nc::GlobC;\n"
+                         "}\n"
+                         "}  // namespace y\n"
+                         "}  // namespace x\n";
+
+  EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
+TEST_F(ChangeNamespaceTest, DoNotFixStaticVariableOfClass) {
+  std::string Code = "namespace na {\n"
+                     "class A {\n"
+                     "public:\n"
+                     "static int A1;\n"
+                     "static int A2;\n"
+                     "}\n"
+                     "static int A::A1 = 0;\n"
+                     "namespace nb {\n"
+                     "void f() { int a = A::A1; int b = A::A2; }"
+                     "} // namespace nb\n"
+                     "} // namespace na\n";
+
+  std::string Expected = "namespace na {\n"
+                         "class A {\n"
+                         "public:\n"
+                         "static int A1;\n"
+                         "static int A2;\n"
+                         "}\n"
+                         "static int A::A1 = 0;\n"
+                         "\n"
+                         "} // namespace na\n"
+                         "namespace x {\n"
+                         "namespace y {\n"
+                         "void f() { int a = na::A::A1; int b = na::A::A2; }"
+                         "}  // 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