clang-rename: add a -old-name option

This is similar to -offset with the following differences:

1) -offset can refer to local variables as well.

2) -old-name makes it easier to refer to e.g. ClassName::MemberName by
spelling out the fully qualified name, instead of having to use e.g.
grep to look up the exact offset.

In other words, -offset is great when clang-rename is invoked by e.g. an
IDE, but not really user-friendly when the tool is invoked by the user
from commandline.  That's the use case where -old-name is supposed to
improve the situation.

Reviewers: klimek

Differential Revision: http://reviews.llvm.org/D21517

llvm-svn: 273304
diff --git a/clang-tools-extra/clang-rename/USRFinder.cpp b/clang-tools-extra/clang-rename/USRFinder.cpp
index 2c73c87..01f7278 100644
--- a/clang-tools-extra/clang-rename/USRFinder.cpp
+++ b/clang-tools-extra/clang-rename/USRFinder.cpp
@@ -40,6 +40,14 @@
         Point(Point) {
   }
 
+  // \brief Finds the NamedDecl for a name in the source.
+  // \param Name the fully qualified name.
+  explicit NamedDeclFindingASTVisitor(const SourceManager &SourceMgr,
+                                      const std::string &Name)
+      : Result(nullptr), SourceMgr(SourceMgr),
+        Name(Name) {
+  }
+
   // Declaration visitors:
 
   // \brief Checks if the point falls within the NameDecl. This covers every
@@ -93,9 +101,17 @@
   // \returns false on success.
   bool setResult(const NamedDecl *Decl, SourceLocation Start,
                  SourceLocation End) {
-    if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
-        !End.isFileID() || !isPointWithin(Start, End)) {
-      return true;
+    if (Name.empty()) {
+      // Offset is used to find the declaration.
+      if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
+          !End.isFileID() || !isPointWithin(Start, End)) {
+        return true;
+      }
+    } else {
+      // Fully qualified name is used to find the declaration.
+      if (Name != Decl->getQualifiedNameAsString()) {
+        return true;
+      }
     }
     Result = Decl;
     return false;
@@ -121,6 +137,7 @@
   const NamedDecl *Result;
   const SourceManager &SourceMgr;
   const SourceLocation Point; // The location to find the NamedDecl.
+  const std::string Name;
 };
 }
 
@@ -148,6 +165,22 @@
   return nullptr;
 }
 
+const NamedDecl *getNamedDeclFor(const ASTContext &Context,
+                                 const std::string &Name) {
+  const auto &SourceMgr = Context.getSourceManager();
+  NamedDeclFindingASTVisitor Visitor(SourceMgr, Name);
+  auto Decls = Context.getTranslationUnitDecl()->decls();
+
+  for (auto &CurrDecl : Decls) {
+    Visitor.TraverseDecl(CurrDecl);
+    if (const NamedDecl *Result = Visitor.getNamedDecl()) {
+      return Result;
+    }
+  }
+
+  return nullptr;
+}
+
 std::string getUSRForDecl(const Decl *Decl) {
   llvm::SmallVector<char, 128> Buff;