From 440d6c02ac5cfe1d6f777a2d0f61686783c108f1 Mon Sep 17 00:00:00 2001
From: Miklos Vajna <vmiklos@vmiklos.hu>
Date: Mon, 11 Sep 2017 20:18:38 +0000
Subject: [PATCH] clang-rename: let -force handle multiple renames

Summary:
The use case is that renaming multiple symbols in a large enough codebase is
much faster if all of these can be done with a single invocation, but
there will be multiple translation units where one or more symbols are
not found.

Old behavior was to exit with an error (default) or exit without
reporting an error (-force). New behavior is that -force results in a
best-effort rename: rename symbols which are found and just ignore the
rest.

The existing help for -force sort of already implies this behavior.

Reviewers: cfe-commits, klimek, arphaman

Reviewed By: klimek

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@312942 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Tooling/Refactoring/Rename/RenamingAction.cpp   | 7 ++++++-
 lib/Tooling/Refactoring/Rename/USRFindingAction.cpp | 5 ++++-
 test/clang-rename/ForceMulti.cpp                    | 8 ++++++++
 tools/clang-rename/ClangRename.cpp                  | 6 ------
 4 files changed, 18 insertions(+), 8 deletions(-)
 create mode 100644 test/clang-rename/ForceMulti.cpp

diff --git a/lib/Tooling/Refactoring/Rename/RenamingAction.cpp b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
index 9c000a72046..0aed67f5324 100644
--- a/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
+++ b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
@@ -84,8 +84,13 @@ public:
         FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
 
   void HandleTranslationUnit(ASTContext &Context) override {
-    for (unsigned I = 0; I < NewNames.size(); ++I)
+    for (unsigned I = 0; I < NewNames.size(); ++I) {
+      // If the previous name was not found, ignore this rename request.
+      if (PrevNames[I].empty())
+        continue;
+
       HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);
+    }
   }
 
   void HandleOneRename(ASTContext &Context, const std::string &NewName,
diff --git a/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
index bac3963e1bd..43287acb95e 100644
--- a/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -198,8 +198,11 @@ private:
         return false;
       }
 
-      if (Force)
+      if (Force) {
+        SpellingNames.push_back(std::string());
+        USRList.push_back(std::vector<std::string>());
         return true;
+      }
 
       unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
           DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
diff --git a/test/clang-rename/ForceMulti.cpp b/test/clang-rename/ForceMulti.cpp
new file mode 100644
index 00000000000..41983ce260c
--- /dev/null
+++ b/test/clang-rename/ForceMulti.cpp
@@ -0,0 +1,8 @@
+class B /* Test 1 */ { // CHECK: class B2 /* Test 1 */ {
+};
+
+class D : public B /* Test 1 */ { // CHECK: class D : public B2 /* Test 1 */ {
+};
+
+// Test 1.
+// RUN: clang-rename -force -qualified-name B -new-name B2 -qualified-name E -new-name E2 %s -- | sed 's,//.*,,' | FileCheck %s
diff --git a/tools/clang-rename/ClangRename.cpp b/tools/clang-rename/ClangRename.cpp
index cc18a05bcdb..fca12ca60c4 100644
--- a/tools/clang-rename/ClangRename.cpp
+++ b/tools/clang-rename/ClangRename.cpp
@@ -175,12 +175,6 @@ int main(int argc, const char **argv) {
     return 1;
   }
 
-  if (Force && PrevNames.size() < NewNames.size()) {
-    // No matching PrevName for all NewNames. Without Force this is an error
-    // above already.
-    return 0;
-  }
-
   // Perform the renaming.
   tooling::RenamingAction RenameAction(NewNames, PrevNames, USRList,
                                        Tool.getReplacements(), PrintLocations);
-- 
GitLab