arphaman created this revision.
Herald added a subscriber: mgorny.

The core engine of clang-rename will be used for local and global renames in 
the new refactoring engine 
(http://lists.llvm.org/pipermail/cfe-dev/2017-June/054286.html).
I haven't renamed the files/cleaned up the code in this patch, do you think I 
should? E.g. SymbolOccurrenceFinder instead of USRLocFinder.


Repository:
  rL LLVM

https://reviews.llvm.org/D34696

Files:
  include/clang/Tooling/Refactoring/USRFinder.h
  include/clang/Tooling/Refactoring/USRFindingAction.h
  include/clang/Tooling/Refactoring/USRLocFinder.h
  include/clang/module.modulemap
  lib/Tooling/Refactoring/CMakeLists.txt
  lib/Tooling/Refactoring/USRFinder.cpp
  lib/Tooling/Refactoring/USRFindingAction.cpp
  lib/Tooling/Refactoring/USRLocFinder.cpp
  tools/extra/clang-rename/CMakeLists.txt
  tools/extra/clang-rename/RenamingAction.cpp
  tools/extra/clang-rename/USRFinder.cpp
  tools/extra/clang-rename/USRFinder.h
  tools/extra/clang-rename/USRFindingAction.cpp
  tools/extra/clang-rename/USRFindingAction.h
  tools/extra/clang-rename/USRLocFinder.cpp
  tools/extra/clang-rename/USRLocFinder.h
  tools/extra/clang-rename/tool/ClangRename.cpp

Index: tools/extra/clang-rename/tool/ClangRename.cpp
===================================================================
--- tools/extra/clang-rename/tool/ClangRename.cpp
+++ tools/extra/clang-rename/tool/ClangRename.cpp
@@ -14,7 +14,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "../RenamingAction.h"
-#include "../USRFindingAction.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
@@ -26,6 +25,7 @@
 #include "clang/Rewrite/Core/Rewriter.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/USRFindingAction.h"
 #include "clang/Tooling/ReplacementsYaml.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -160,7 +160,7 @@
 
   auto Files = OP.getSourcePathList();
   tooling::RefactoringTool Tool(OP.getCompilations(), Files);
-  rename::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames, Force);
+  tooling::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames, Force);
   Tool.run(tooling::newFrontendActionFactory(&FindingAction).get());
   const std::vector<std::vector<std::string>> &USRList =
       FindingAction.getUSRList();
Index: tools/extra/clang-rename/USRLocFinder.h
===================================================================
--- tools/extra/clang-rename/USRLocFinder.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===--- tools/extra/clang-rename/USRLocFinder.h - Clang rename tool ------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides functionality for finding all instances of a USR in a given
-/// AST.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
-
-#include "clang/AST/AST.h"
-#include "clang/Tooling/Core/Replacement.h"
-#include "clang/Tooling/Refactoring/AtomicChange.h"
-#include "llvm/ADT/StringRef.h"
-#include <string>
-#include <vector>
-
-namespace clang {
-namespace rename {
-
-/// Create atomic changes for renaming all symbol references which are
-/// identified by the USRs set to a given new name.
-///
-/// \param USRs The set containing USRs of a particular old symbol.
-/// \param NewName The new name to replace old symbol name.
-/// \param TranslationUnitDecl The translation unit declaration.
-///
-/// \return Atomic changes for renaming.
-std::vector<tooling::AtomicChange>
-createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
-                          llvm::StringRef NewName, Decl *TranslationUnitDecl);
-
-// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
-std::vector<SourceLocation>
-getLocationsOfUSRs(const std::vector<std::string> &USRs,
-                   llvm::StringRef PrevName, Decl *Decl);
-
-} // namespace rename
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
Index: tools/extra/clang-rename/USRLocFinder.cpp
===================================================================
--- tools/extra/clang-rename/USRLocFinder.cpp
+++ /dev/null
@@ -1,509 +0,0 @@
-//===--- tools/extra/clang-rename/USRLocFinder.cpp - Clang rename tool ----===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Mehtods for finding all instances of a USR. Our strategy is very
-/// simple; we just compare the USR at every relevant AST node with the one
-/// provided.
-///
-//===----------------------------------------------------------------------===//
-
-#include "USRLocFinder.h"
-#include "USRFinder.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/Core/Lookup.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
-#include <cstddef>
-#include <set>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-
-namespace clang {
-namespace rename {
-
-namespace {
-
-// \brief This visitor recursively searches for all instances of a USR in a
-// translation unit and stores them for later usage.
-class USRLocFindingASTVisitor
-    : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
-public:
-  explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
-                                   StringRef PrevName,
-                                   const ASTContext &Context)
-      : USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
-  }
-
-  // Declaration visitors:
-
-  bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
-    for (const auto *Initializer : ConstructorDecl->inits()) {
-      // Ignore implicit initializers.
-      if (!Initializer->isWritten())
-        continue;
-      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
-        if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end())
-          LocationsFound.push_back(Initializer->getSourceLocation());
-      }
-    }
-    return true;
-  }
-
-  bool VisitNamedDecl(const NamedDecl *Decl) {
-    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
-      checkAndAddLocation(Decl->getLocation());
-    return true;
-  }
-
-  // Expression visitors:
-
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl();
-
-    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
-      const SourceManager &Manager = Decl->getASTContext().getSourceManager();
-      SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
-      checkAndAddLocation(Location);
-    }
-
-    return true;
-  }
-
-  bool VisitMemberExpr(const MemberExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
-    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
-      const SourceManager &Manager = Decl->getASTContext().getSourceManager();
-      SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
-      checkAndAddLocation(Location);
-    }
-    return true;
-  }
-
-  // Other visitors:
-
-  bool VisitTypeLoc(const TypeLoc Loc) {
-    if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
-        USRSet.end())
-      checkAndAddLocation(Loc.getBeginLoc());
-    if (const auto *TemplateTypeParm =
-            dyn_cast<TemplateTypeParmType>(Loc.getType())) {
-      if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
-          USRSet.end())
-        checkAndAddLocation(Loc.getBeginLoc());
-    }
-    return true;
-  }
-
-  // Non-visitors:
-
-  // \brief Returns a list of unique locations. Duplicate or overlapping
-  // locations are erroneous and should be reported!
-  const std::vector<clang::SourceLocation> &getLocationsFound() const {
-    return LocationsFound;
-  }
-
-  // Namespace traversal:
-  void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
-    while (NameLoc) {
-      const NamespaceDecl *Decl =
-          NameLoc.getNestedNameSpecifier()->getAsNamespace();
-      if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
-        checkAndAddLocation(NameLoc.getLocalBeginLoc());
-      NameLoc = NameLoc.getPrefix();
-    }
-  }
-
-private:
-  void checkAndAddLocation(SourceLocation Loc) {
-    const SourceLocation BeginLoc = Loc;
-    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
-        BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
-    StringRef TokenName =
-        Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
-                             Context.getSourceManager(), Context.getLangOpts());
-    size_t Offset = TokenName.find(PrevName);
-
-    // The token of the source location we find actually has the old
-    // name.
-    if (Offset != StringRef::npos)
-      LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
-  }
-
-  const std::set<std::string> USRSet;
-  const std::string PrevName;
-  std::vector<clang::SourceLocation> LocationsFound;
-  const ASTContext &Context;
-};
-
-SourceLocation StartLocationForType(TypeLoc TL) {
-  // For elaborated types (e.g. `struct a::A`) we want the portion after the
-  // `struct` but including the namespace qualifier, `a::`.
-  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
-    NestedNameSpecifierLoc NestedNameSpecifier =
-        ElaboratedTypeLoc.getQualifierLoc();
-    if (NestedNameSpecifier.getNestedNameSpecifier())
-      return NestedNameSpecifier.getBeginLoc();
-    TL = TL.getNextTypeLoc();
-  }
-  return TL.getLocStart();
-}
-
-SourceLocation EndLocationForType(TypeLoc TL) {
-  // Dig past any namespace or keyword qualifications.
-  while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
-         TL.getTypeLocClass() == TypeLoc::Qualified)
-    TL = TL.getNextTypeLoc();
-
-  // The location for template specializations (e.g. Foo<int>) includes the
-  // templated types in its location range.  We want to restrict this to just
-  // before the `<` character.
-  if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
-    return TL.castAs<TemplateSpecializationTypeLoc>()
-        .getLAngleLoc()
-        .getLocWithOffset(-1);
-  }
-  return TL.getEndLoc();
-}
-
-NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
-  // Dig past any keyword qualifications.
-  while (TL.getTypeLocClass() == TypeLoc::Qualified)
-    TL = TL.getNextTypeLoc();
-
-  // For elaborated types (e.g. `struct a::A`) we want the portion after the
-  // `struct` but including the namespace qualifier, `a::`.
-  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
-    return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
-  return nullptr;
-}
-
-// Find all locations identified by the given USRs for rename.
-//
-// This class will traverse the AST and find every AST node whose USR is in the
-// given USRs' set.
-class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
-public:
-  RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
-      : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
-
-  // A structure records all information of a symbol reference being renamed.
-  // We try to add as few prefix qualifiers as possible.
-  struct RenameInfo {
-    // The begin location of a symbol being renamed.
-    SourceLocation Begin;
-    // The end location of a symbol being renamed.
-    SourceLocation End;
-    // The declaration of a symbol being renamed (can be nullptr).
-    const NamedDecl *FromDecl;
-    // The declaration in which the nested name is contained (can be nullptr).
-    const Decl *Context;
-    // The nested name being replaced (can be nullptr).
-    const NestedNameSpecifier *Specifier;
-  };
-
-  // FIXME: Currently, prefix qualifiers will be added to the renamed symbol
-  // definition (e.g. "class Foo {};" => "class b::Bar {};" when renaming
-  // "a::Foo" to "b::Bar").
-  // For renaming declarations/definitions, prefix qualifiers should be filtered
-  // out.
-  bool VisitNamedDecl(const NamedDecl *Decl) {
-    // UsingDecl has been handled in other place.
-    if (llvm::isa<UsingDecl>(Decl))
-      return true;
-
-    // DestructorDecl has been handled in Typeloc.
-    if (llvm::isa<CXXDestructorDecl>(Decl))
-      return true;
-
-    if (Decl->isImplicit())
-      return true;
-
-    if (isInUSRSet(Decl)) {
-      RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr,
-                         nullptr, nullptr};
-      RenameInfos.push_back(Info);
-    }
-    return true;
-  }
-
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl();
-    if (isInUSRSet(Decl)) {
-      RenameInfo Info = {Expr->getSourceRange().getBegin(),
-                         Expr->getSourceRange().getEnd(), Decl,
-                         getClosestAncestorDecl(*Expr), Expr->getQualifier()};
-      RenameInfos.push_back(Info);
-    }
-
-    return true;
-  }
-
-  bool VisitUsingDecl(const UsingDecl *Using) {
-    for (const auto *UsingShadow : Using->shadows()) {
-      if (isInUSRSet(UsingShadow->getTargetDecl())) {
-        UsingDecls.push_back(Using);
-        break;
-      }
-    }
-    return true;
-  }
-
-  bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
-    if (!NestedLoc.getNestedNameSpecifier()->getAsType())
-      return true;
-    if (IsTypeAliasWhichWillBeRenamedElsewhere(NestedLoc.getTypeLoc()))
-      return true;
-
-    if (const auto *TargetDecl =
-            getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
-      if (isInUSRSet(TargetDecl)) {
-        RenameInfo Info = {NestedLoc.getBeginLoc(),
-                           EndLocationForType(NestedLoc.getTypeLoc()),
-                           TargetDecl, getClosestAncestorDecl(NestedLoc),
-                           NestedLoc.getNestedNameSpecifier()->getPrefix()};
-        RenameInfos.push_back(Info);
-      }
-    }
-    return true;
-  }
-
-  bool VisitTypeLoc(TypeLoc Loc) {
-    if (IsTypeAliasWhichWillBeRenamedElsewhere(Loc))
-      return true;
-
-    auto Parents = Context.getParents(Loc);
-    TypeLoc ParentTypeLoc;
-    if (!Parents.empty()) {
-      // Handle cases of nested name specificier locations.
-      //
-      // The VisitNestedNameSpecifierLoc interface is not impelmented in
-      // RecursiveASTVisitor, we have to handle it explicitly.
-      if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
-        VisitNestedNameSpecifierLocations(*NSL);
-        return true;
-      }
-
-      if (const auto *TL = Parents[0].get<TypeLoc>())
-        ParentTypeLoc = *TL;
-    }
-
-    // Handle the outermost TypeLoc which is directly linked to the interesting
-    // declaration and don't handle nested name specifier locations.
-    if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
-      if (isInUSRSet(TargetDecl)) {
-        // Only handle the outermost typeLoc.
-        //
-        // For a type like "a::Foo", there will be two typeLocs for it.
-        // One ElaboratedType, the other is RecordType:
-        //
-        //   ElaboratedType 0x33b9390 'a::Foo' sugar
-        //   `-RecordType 0x338fef0 'class a::Foo'
-        //     `-CXXRecord 0x338fe58 'Foo'
-        //
-        // Skip if this is an inner typeLoc.
-        if (!ParentTypeLoc.isNull() &&
-            isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
-          return true;
-        RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc),
-                           TargetDecl, getClosestAncestorDecl(Loc),
-                           GetNestedNameForType(Loc)};
-        RenameInfos.push_back(Info);
-        return true;
-      }
-    }
-
-    // Handle specific template class specialiation cases.
-    if (const auto *TemplateSpecType =
-            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
-      TypeLoc TargetLoc = Loc;
-      if (!ParentTypeLoc.isNull()) {
-        if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
-          TargetLoc = ParentTypeLoc;
-      }
-
-      if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
-        TypeLoc TargetLoc = Loc;
-        // FIXME: Find a better way to handle this case.
-        // For the qualified template class specification type like
-        // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
-        // (ElaboratedType) of the TemplateSpecializationType in order to
-        // catch the prefix qualifiers "ns::".
-        if (!ParentTypeLoc.isNull() &&
-            llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
-          TargetLoc = ParentTypeLoc;
-        RenameInfo Info = {
-            StartLocationForType(TargetLoc), EndLocationForType(TargetLoc),
-            TemplateSpecType->getTemplateName().getAsTemplateDecl(),
-            getClosestAncestorDecl(
-                ast_type_traits::DynTypedNode::create(TargetLoc)),
-            GetNestedNameForType(TargetLoc)};
-        RenameInfos.push_back(Info);
-      }
-    }
-    return true;
-  }
-
-  // Returns a list of RenameInfo.
-  const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
-
-  // Returns a list of using declarations which are needed to update.
-  const std::vector<const UsingDecl *> &getUsingDecls() const {
-    return UsingDecls;
-  }
-
-private:
-  // FIXME: This method may not be suitable for renaming other types like alias
-  // types. Need to figure out a way to handle it.
-  bool IsTypeAliasWhichWillBeRenamedElsewhere(TypeLoc TL) const {
-    while (!TL.isNull()) {
-      // SubstTemplateTypeParm is the TypeLocation class for a substituted type
-      // inside a template expansion so we ignore these.  For example:
-      //
-      // template<typename T> struct S {
-      //   T t;  // <-- this T becomes a TypeLoc(int) with class
-      //         //     SubstTemplateTypeParm when S<int> is instantiated
-      // }
-      if (TL.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
-        return true;
-
-      // Typedef is the TypeLocation class for a type which is a typedef to the
-      // type we want to replace.  We ignore the use of the typedef as we will
-      // replace the definition of it.  For example:
-      //
-      // typedef int T;
-      // T a;  // <---  This T is a TypeLoc(int) with class Typedef.
-      if (TL.getTypeLocClass() == TypeLoc::Typedef)
-        return true;
-      TL = TL.getNextTypeLoc();
-    }
-    return false;
-  }
-
-  // Get the supported declaration from a given typeLoc. If the declaration type
-  // is not supported, returns nullptr.
-  //
-  // FIXME: support more types, e.g. enum, type alias.
-  const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
-    if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
-      return RD;
-    return nullptr;
-  }
-
-  // Get the closest ancester which is a declaration of a given AST node.
-  template <typename ASTNodeType>
-  const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
-    auto Parents = Context.getParents(Node);
-    // FIXME: figure out how to handle it when there are multiple parents.
-    if (Parents.size() != 1)
-      return nullptr;
-    if (ast_type_traits::ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(
-            Parents[0].getNodeKind()))
-      return Parents[0].template get<Decl>();
-    return getClosestAncestorDecl(Parents[0]);
-  }
-
-  // Get the parent typeLoc of a given typeLoc. If there is no such parent,
-  // return nullptr.
-  const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
-    auto Parents = Context.getParents(Loc);
-    // FIXME: figure out how to handle it when there are multiple parents.
-    if (Parents.size() != 1)
-      return nullptr;
-    return Parents[0].get<TypeLoc>();
-  }
-
-  // Check whether the USR of a given Decl is in the USRSet.
-  bool isInUSRSet(const Decl *Decl) const {
-    auto USR = getUSRForDecl(Decl);
-    if (USR.empty())
-      return false;
-    return llvm::is_contained(USRSet, USR);
-  }
-
-  const std::set<std::string> USRSet;
-  ASTContext &Context;
-  std::vector<RenameInfo> RenameInfos;
-  // Record all interested using declarations which contains the using-shadow
-  // declarations of the symbol declarations being renamed.
-  std::vector<const UsingDecl *> UsingDecls;
-};
-
-} // namespace
-
-std::vector<SourceLocation>
-getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
-                   Decl *Decl) {
-  USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
-  Visitor.TraverseDecl(Decl);
-  NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
-
-  for (const auto &Location : Finder.getNestedNameSpecifierLocations())
-    Visitor.handleNestedNameSpecifierLoc(Location);
-
-  return Visitor.getLocationsFound();
-}
-
-std::vector<tooling::AtomicChange>
-createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
-                          llvm::StringRef NewName, Decl *TranslationUnitDecl) {
-  RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
-  Finder.TraverseDecl(TranslationUnitDecl);
-
-  const SourceManager &SM =
-      TranslationUnitDecl->getASTContext().getSourceManager();
-
-  std::vector<tooling::AtomicChange> AtomicChanges;
-  auto Replace = [&](SourceLocation Start, SourceLocation End,
-                     llvm::StringRef Text) {
-    tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
-    llvm::Error Err = ReplaceChange.replace(
-        SM, CharSourceRange::getTokenRange(Start, End), Text);
-    if (Err) {
-      llvm::errs() << "Faile to add replacement to AtomicChange: "
-                   << llvm::toString(std::move(Err)) << "\n";
-      return;
-    }
-    AtomicChanges.push_back(std::move(ReplaceChange));
-  };
-
-  for (const auto &RenameInfo : Finder.getRenameInfos()) {
-    std::string ReplacedName = NewName.str();
-    if (RenameInfo.FromDecl && RenameInfo.Context) {
-      if (!llvm::isa<clang::TranslationUnitDecl>(
-              RenameInfo.Context->getDeclContext())) {
-        ReplacedName = tooling::replaceNestedName(
-            RenameInfo.Specifier, RenameInfo.Context->getDeclContext(),
-            RenameInfo.FromDecl,
-            NewName.startswith("::") ? NewName.str() : ("::" + NewName).str());
-      }
-    }
-    // If the NewName contains leading "::", add it back.
-    if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
-      ReplacedName = NewName.str();
-    Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
-  }
-
-  // Hanlde using declarations explicitly as "using a::Foo" don't trigger
-  // typeLoc for "a::Foo".
-  for (const auto *Using : Finder.getUsingDecls())
-    Replace(Using->getLocStart(), Using->getLocEnd(), "using " + NewName.str());
-
-  return AtomicChanges;
-}
-
-} // namespace rename
-} // namespace clang
Index: tools/extra/clang-rename/USRFindingAction.h
===================================================================
--- tools/extra/clang-rename/USRFindingAction.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===--- tools/extra/clang-rename/USRFindingAction.h - Clang rename tool --===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides an action to find all relevant USRs at a point.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-
-#include <string>
-#include <vector>
-
-namespace clang {
-class ASTConsumer;
-class CompilerInstance;
-class NamedDecl;
-
-namespace rename {
-
-struct USRFindingAction {
-  USRFindingAction(ArrayRef<unsigned> SymbolOffsets,
-                   ArrayRef<std::string> QualifiedNames, bool Force)
-      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
-        ErrorOccurred(false), Force(Force) {}
-  std::unique_ptr<ASTConsumer> newASTConsumer();
-
-  ArrayRef<std::string> getUSRSpellings() { return SpellingNames; }
-  ArrayRef<std::vector<std::string>> getUSRList() { return USRList; }
-  bool errorOccurred() { return ErrorOccurred; }
-
-private:
-  std::vector<unsigned> SymbolOffsets;
-  std::vector<std::string> QualifiedNames;
-  std::vector<std::string> SpellingNames;
-  std::vector<std::vector<std::string>> USRList;
-  bool ErrorOccurred;
-  bool Force;
-};
-
-} // namespace rename
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
Index: tools/extra/clang-rename/USRFindingAction.cpp
===================================================================
--- tools/extra/clang-rename/USRFindingAction.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-//===--- tools/extra/clang-rename/USRFindingAction.cpp - Clang rename tool ===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provides an action to find USR for the symbol at <offset>, as well as
-/// all additional USRs.
-///
-//===----------------------------------------------------------------------===//
-
-#include "USRFindingAction.h"
-#include "USRFinder.h"
-#include "clang/AST/AST.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Tooling/CommonOptionsParser.h"
-#include "clang/Tooling/Refactoring.h"
-#include "clang/Tooling/Tooling.h"
-
-#include <algorithm>
-#include <set>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-
-namespace clang {
-namespace rename {
-
-namespace {
-// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
-// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
-// Decl refers to class and adds USRs of all overridden methods if Decl refers
-// to virtual method.
-class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
-public:
-  AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
-      : FoundDecl(FoundDecl), Context(Context) {}
-
-  std::vector<std::string> Find() {
-    // Fill OverriddenMethods and PartialSpecs storages.
-    TraverseDecl(Context.getTranslationUnitDecl());
-    if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
-      addUSRsOfOverridenFunctions(MethodDecl);
-      for (const auto &OverriddenMethod : OverriddenMethods) {
-        if (checkIfOverriddenFunctionAscends(OverriddenMethod))
-          USRSet.insert(getUSRForDecl(OverriddenMethod));
-      }
-    } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
-      handleCXXRecordDecl(RecordDecl);
-    } else if (const auto *TemplateDecl =
-                   dyn_cast<ClassTemplateDecl>(FoundDecl)) {
-      handleClassTemplateDecl(TemplateDecl);
-    } else {
-      USRSet.insert(getUSRForDecl(FoundDecl));
-    }
-    return std::vector<std::string>(USRSet.begin(), USRSet.end());
-  }
-
-  bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
-    if (MethodDecl->isVirtual())
-      OverriddenMethods.push_back(MethodDecl);
-    return true;
-  }
-
-  bool VisitClassTemplatePartialSpecializationDecl(
-      const ClassTemplatePartialSpecializationDecl *PartialSpec) {
-    PartialSpecs.push_back(PartialSpec);
-    return true;
-  }
-
-private:
-  void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
-    RecordDecl = RecordDecl->getDefinition();
-    if (const auto *ClassTemplateSpecDecl =
-            dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl))
-      handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
-    addUSRsOfCtorDtors(RecordDecl);
-  }
-
-  void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
-    for (const auto *Specialization : TemplateDecl->specializations())
-      addUSRsOfCtorDtors(Specialization);
-
-    for (const auto *PartialSpec : PartialSpecs) {
-      if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
-        addUSRsOfCtorDtors(PartialSpec);
-    }
-    addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
-  }
-
-  void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
-    RecordDecl = RecordDecl->getDefinition();
-
-    // Skip if the CXXRecordDecl doesn't have definition.
-    if (!RecordDecl)
-      return;
-
-    for (const auto *CtorDecl : RecordDecl->ctors())
-      USRSet.insert(getUSRForDecl(CtorDecl));
-
-    USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
-    USRSet.insert(getUSRForDecl(RecordDecl));
-  }
-
-  void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) {
-    USRSet.insert(getUSRForDecl(MethodDecl));
-    // Recursively visit each OverridenMethod.
-    for (const auto &OverriddenMethod : MethodDecl->overridden_methods())
-      addUSRsOfOverridenFunctions(OverriddenMethod);
-  }
-
-  bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
-    for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
-      if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
-        return true;
-      return checkIfOverriddenFunctionAscends(OverriddenMethod);
-    }
-    return false;
-  }
-
-  const Decl *FoundDecl;
-  ASTContext &Context;
-  std::set<std::string> USRSet;
-  std::vector<const CXXMethodDecl *> OverriddenMethods;
-  std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs;
-};
-} // namespace
-
-class NamedDeclFindingConsumer : public ASTConsumer {
-public:
-  NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
-                           ArrayRef<std::string> QualifiedNames,
-                           std::vector<std::string> &SpellingNames,
-                           std::vector<std::vector<std::string>> &USRList,
-                           bool Force, bool &ErrorOccurred)
-      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
-        SpellingNames(SpellingNames), USRList(USRList), Force(Force),
-        ErrorOccurred(ErrorOccurred) {}
-
-private:
-  bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr,
-                  unsigned SymbolOffset, const std::string &QualifiedName) {
-    DiagnosticsEngine &Engine = Context.getDiagnostics();
-    const FileID MainFileID = SourceMgr.getMainFileID();
-
-    if (SymbolOffset >= SourceMgr.getFileIDSize(MainFileID)) {
-      ErrorOccurred = true;
-      unsigned InvalidOffset = Engine.getCustomDiagID(
-          DiagnosticsEngine::Error,
-          "SourceLocation in file %0 at offset %1 is invalid");
-      Engine.Report(SourceLocation(), InvalidOffset)
-          << SourceMgr.getFileEntryForID(MainFileID)->getName() << SymbolOffset;
-      return false;
-    }
-
-    const SourceLocation Point = SourceMgr.getLocForStartOfFile(MainFileID)
-                                     .getLocWithOffset(SymbolOffset);
-    const NamedDecl *FoundDecl = QualifiedName.empty()
-                                     ? getNamedDeclAt(Context, Point)
-                                     : getNamedDeclFor(Context, QualifiedName);
-
-    if (FoundDecl == nullptr) {
-      if (QualifiedName.empty()) {
-        FullSourceLoc FullLoc(Point, SourceMgr);
-        unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID(
-            DiagnosticsEngine::Error,
-            "clang-rename could not find symbol (offset %0)");
-        Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset;
-        ErrorOccurred = true;
-        return false;
-      }
-
-      if (Force)
-        return true;
-
-      unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
-          DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
-      Engine.Report(CouldNotFindSymbolNamed) << QualifiedName;
-      ErrorOccurred = true;
-      return false;
-    }
-
-    // If FoundDecl is a constructor or destructor, we want to instead take
-    // the Decl of the corresponding class.
-    if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
-      FoundDecl = CtorDecl->getParent();
-    else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
-      FoundDecl = DtorDecl->getParent();
-
-    SpellingNames.push_back(FoundDecl->getNameAsString());
-    AdditionalUSRFinder Finder(FoundDecl, Context);
-    USRList.push_back(Finder.Find());
-    return true;
-  }
-
-  void HandleTranslationUnit(ASTContext &Context) override {
-    const SourceManager &SourceMgr = Context.getSourceManager();
-    for (unsigned Offset : SymbolOffsets) {
-      if (!FindSymbol(Context, SourceMgr, Offset, ""))
-        return;
-    }
-    for (const std::string &QualifiedName : QualifiedNames) {
-      if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))
-        return;
-    }
-  }
-
-  ArrayRef<unsigned> SymbolOffsets;
-  ArrayRef<std::string> QualifiedNames;
-  std::vector<std::string> &SpellingNames;
-  std::vector<std::vector<std::string>> &USRList;
-  bool Force;
-  bool &ErrorOccurred;
-};
-
-std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() {
-  return llvm::make_unique<NamedDeclFindingConsumer>(
-      SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force,
-      ErrorOccurred);
-}
-
-} // namespace rename
-} // namespace clang
Index: tools/extra/clang-rename/USRFinder.h
===================================================================
--- tools/extra/clang-rename/USRFinder.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===--- tools/extra/clang-rename/USRFinder.h - Clang rename tool ---------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Methods for determining the USR of a symbol at a location in source
-/// code.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
-
-#include "clang/AST/AST.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include <string>
-#include <vector>
-
-using namespace llvm;
-using namespace clang::ast_matchers;
-
-namespace clang {
-
-class ASTContext;
-class Decl;
-class SourceLocation;
-class NamedDecl;
-
-namespace rename {
-
-// Given an AST context and a point, returns a NamedDecl identifying the symbol
-// at the point. Returns null if nothing is found at the point.
-const NamedDecl *getNamedDeclAt(const ASTContext &Context,
-                                const SourceLocation Point);
-
-// Given an AST context and a fully qualified name, returns a NamedDecl
-// identifying the symbol with a matching name. Returns null if nothing is
-// found for the name.
-const NamedDecl *getNamedDeclFor(const ASTContext &Context,
-                                 const std::string &Name);
-
-// Converts a Decl into a USR.
-std::string getUSRForDecl(const Decl *Decl);
-
-// FIXME: Implement RecursiveASTVisitor<T>::VisitNestedNameSpecifier instead.
-class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback {
-public:
-  explicit NestedNameSpecifierLocFinder(ASTContext &Context)
-      : Context(Context) {}
-
-  std::vector<NestedNameSpecifierLoc> getNestedNameSpecifierLocations() {
-    addMatchers();
-    Finder.matchAST(Context);
-    return Locations;
-  }
-
-private:
-  void addMatchers() {
-    const auto NestedNameSpecifierLocMatcher =
-        nestedNameSpecifierLoc().bind("nestedNameSpecifierLoc");
-    Finder.addMatcher(NestedNameSpecifierLocMatcher, this);
-  }
-
-  void run(const MatchFinder::MatchResult &Result) override {
-    const auto *NNS = Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
-        "nestedNameSpecifierLoc");
-    Locations.push_back(*NNS);
-  }
-
-  ASTContext &Context;
-  std::vector<NestedNameSpecifierLoc> Locations;
-  MatchFinder Finder;
-};
-
-} // namespace rename
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
Index: tools/extra/clang-rename/USRFinder.cpp
===================================================================
--- tools/extra/clang-rename/USRFinder.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-//===--- tools/extra/clang-rename/USRFinder.cpp - Clang rename tool -------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file Implements a recursive AST visitor that finds the USR of a symbol at a
-/// point.
-///
-//===----------------------------------------------------------------------===//
-
-#include "USRFinder.h"
-#include "clang/AST/AST.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Index/USRGeneration.h"
-#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/SmallVector.h"
-
-using namespace llvm;
-
-namespace clang {
-namespace rename {
-
-// NamedDeclFindingASTVisitor recursively visits each AST node to find the
-// symbol underneath the cursor.
-// FIXME: move to separate .h/.cc file if this gets too large.
-namespace {
-class NamedDeclFindingASTVisitor
-    : public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> {
-public:
-  // \brief Finds the NamedDecl at a point in the source.
-  // \param Point the location in the source to search for the NamedDecl.
-  explicit NamedDeclFindingASTVisitor(const SourceLocation Point,
-                                      const ASTContext &Context)
-      : Result(nullptr), Point(Point), Context(Context) {}
-
-  // \brief Finds the NamedDecl for a name in the source.
-  // \param Name the fully qualified name.
-  explicit NamedDeclFindingASTVisitor(const std::string &Name,
-                                      const ASTContext &Context)
-      : Result(nullptr), Name(Name), Context(Context) {}
-
-  // Declaration visitors:
-
-  // \brief Checks if the point falls within the NameDecl. This covers every
-  // declaration of a named entity that we may come across. Usually, just
-  // checking if the point lies within the length of the name of the declaration
-  // and the start location is sufficient.
-  bool VisitNamedDecl(const NamedDecl *Decl) {
-    return dyn_cast<CXXConversionDecl>(Decl)
-               ? true
-               : setResult(Decl, Decl->getLocation(),
-                           Decl->getNameAsString().length());
-  }
-
-  // Expression visitors:
-
-  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl();
-    return setResult(Decl, Expr->getLocation(),
-                     Decl->getNameAsString().length());
-  }
-
-  bool VisitMemberExpr(const MemberExpr *Expr) {
-    const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
-    return setResult(Decl, Expr->getMemberLoc(),
-                     Decl->getNameAsString().length());
-  }
-
-  // Other visitors:
-
-  bool VisitTypeLoc(const TypeLoc Loc) {
-    const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
-    const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(
-        TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
-    if (const auto *TemplateTypeParm =
-            dyn_cast<TemplateTypeParmType>(Loc.getType()))
-      return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
-    if (const auto *TemplateSpecType =
-            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
-      return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
-                       TypeBeginLoc, TypeEndLoc);
-    }
-    return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
-                     TypeEndLoc);
-  }
-
-  bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
-    for (const auto *Initializer : ConstructorDecl->inits()) {
-      // Ignore implicit initializers.
-      if (!Initializer->isWritten())
-        continue;
-      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
-        const SourceLocation InitBeginLoc = Initializer->getSourceLocation(),
-                             InitEndLoc = Lexer::getLocForEndOfToken(
-                                 InitBeginLoc, 0, Context.getSourceManager(),
-                                 Context.getLangOpts());
-        if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc))
-          return false;
-      }
-    }
-    return true;
-  }
-
-  // Other:
-
-  const NamedDecl *getNamedDecl() { return Result; }
-
-  // \brief Determines if a namespace qualifier contains the point.
-  // \returns false on success and sets Result.
-  void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
-    while (NameLoc) {
-      const NamespaceDecl *Decl =
-          NameLoc.getNestedNameSpecifier()->getAsNamespace();
-      setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc());
-      NameLoc = NameLoc.getPrefix();
-    }
-  }
-
-private:
-  // \brief Sets Result to Decl if the Point is within Start and End.
-  // \returns false on success.
-  bool setResult(const NamedDecl *Decl, SourceLocation Start,
-                 SourceLocation End) {
-    if (!Decl)
-      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() &&
-          Name != "::" + Decl->getQualifiedNameAsString())
-        return true;
-    }
-    Result = Decl;
-    return false;
-  }
-
-  // \brief Sets Result to Decl if Point is within Loc and Loc + Offset.
-  // \returns false on success.
-  bool setResult(const NamedDecl *Decl, SourceLocation Loc, unsigned Offset) {
-    // FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc).
-    return Offset == 0 ||
-           setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));
-  }
-
-  // \brief Determines if the Point is within Start and End.
-  bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
-    // FIXME: Add tests for Point == End.
-    return Point == Start || Point == End ||
-           (Context.getSourceManager().isBeforeInTranslationUnit(Start,
-                                                                 Point) &&
-            Context.getSourceManager().isBeforeInTranslationUnit(Point, End));
-  }
-
-  const NamedDecl *Result;
-  const SourceLocation Point; // The location to find the NamedDecl.
-  const std::string Name;
-  const ASTContext &Context;
-};
-} // namespace
-
-const NamedDecl *getNamedDeclAt(const ASTContext &Context,
-                                const SourceLocation Point) {
-  const SourceManager &SM = Context.getSourceManager();
-  NamedDeclFindingASTVisitor Visitor(Point, Context);
-
-  // Try to be clever about pruning down the number of top-level declarations we
-  // see. If both start and end is either before or after the point we're
-  // looking for the point cannot be inside of this decl. Don't even look at it.
-  for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
-    SourceLocation StartLoc = CurrDecl->getLocStart();
-    SourceLocation EndLoc = CurrDecl->getLocEnd();
-    if (StartLoc.isValid() && EndLoc.isValid() &&
-        SM.isBeforeInTranslationUnit(StartLoc, Point) !=
-            SM.isBeforeInTranslationUnit(EndLoc, Point))
-      Visitor.TraverseDecl(CurrDecl);
-  }
-
-  NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context));
-  for (const auto &Location : Finder.getNestedNameSpecifierLocations())
-    Visitor.handleNestedNameSpecifierLoc(Location);
-
-  return Visitor.getNamedDecl();
-}
-
-const NamedDecl *getNamedDeclFor(const ASTContext &Context,
-                                 const std::string &Name) {
-  NamedDeclFindingASTVisitor Visitor(Name, Context);
-  Visitor.TraverseDecl(Context.getTranslationUnitDecl());
-
-  return Visitor.getNamedDecl();
-}
-
-std::string getUSRForDecl(const Decl *Decl) {
-  llvm::SmallVector<char, 128> Buff;
-
-  // FIXME: Add test for the nullptr case.
-  if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff))
-    return "";
-
-  return std::string(Buff.data(), Buff.size());
-}
-
-} // namespace rename
-} // namespace clang
Index: tools/extra/clang-rename/RenamingAction.cpp
===================================================================
--- tools/extra/clang-rename/RenamingAction.cpp
+++ tools/extra/clang-rename/RenamingAction.cpp
@@ -13,7 +13,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "RenamingAction.h"
-#include "USRLocFinder.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/Basic/FileManager.h"
@@ -23,6 +22,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/USRLocFinder.h"
 #include "clang/Tooling/Tooling.h"
 #include <string>
 #include <vector>
@@ -55,8 +55,8 @@
     std::vector<SourceLocation> RenamingCandidates;
     std::vector<SourceLocation> NewCandidates;
 
-    NewCandidates =
-        getLocationsOfUSRs(USRs, PrevName, Context.getTranslationUnitDecl());
+    NewCandidates = tooling::getLocationsOfUSRs(
+        USRs, PrevName, Context.getTranslationUnitDecl());
     RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(),
                               NewCandidates.end());
 
@@ -101,7 +101,7 @@
     for (unsigned I = 0; I < NewNames.size(); ++I) {
       // FIXME: Apply AtomicChanges directly once the refactoring APIs are
       // ready.
-      auto AtomicChanges = createRenameAtomicChanges(
+      auto AtomicChanges = tooling::createRenameAtomicChanges(
           USRList[I], NewNames[I], Context.getTranslationUnitDecl());
       for (const auto AtomicChange : AtomicChanges) {
         for (const auto &Replace : AtomicChange.getReplacements()) {
Index: tools/extra/clang-rename/CMakeLists.txt
===================================================================
--- tools/extra/clang-rename/CMakeLists.txt
+++ tools/extra/clang-rename/CMakeLists.txt
@@ -1,9 +1,6 @@
 set(LLVM_LINK_COMPONENTS support)
 
 add_clang_library(clangRename
-  USRFinder.cpp
-  USRFindingAction.cpp
-  USRLocFinder.cpp
   RenamingAction.cpp
 
   LINK_LIBS
Index: lib/Tooling/Refactoring/USRLocFinder.cpp
===================================================================
--- /dev/null
+++ lib/Tooling/Refactoring/USRLocFinder.cpp
@@ -0,0 +1,509 @@
+//===--- USRLocFinder.cpp - Clang refactoring library ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Mehtods for finding all instances of a USR. Our strategy is very
+/// simple; we just compare the USR at every relevant AST node with the one
+/// provided.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/USRLocFinder.h"
+#include "clang/Tooling/Refactoring/USRFinder.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Core/Lookup.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <cstddef>
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+namespace {
+
+// \brief This visitor recursively searches for all instances of a USR in a
+// translation unit and stores them for later usage.
+class USRLocFindingASTVisitor
+    : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
+public:
+  explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
+                                   StringRef PrevName,
+                                   const ASTContext &Context)
+      : USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
+  }
+
+  // Declaration visitors:
+
+  bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
+    for (const auto *Initializer : ConstructorDecl->inits()) {
+      // Ignore implicit initializers.
+      if (!Initializer->isWritten())
+        continue;
+      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
+        if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end())
+          LocationsFound.push_back(Initializer->getSourceLocation());
+      }
+    }
+    return true;
+  }
+
+  bool VisitNamedDecl(const NamedDecl *Decl) {
+    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
+      checkAndAddLocation(Decl->getLocation());
+    return true;
+  }
+
+  // Expression visitors:
+
+  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+    const NamedDecl *Decl = Expr->getFoundDecl();
+
+    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
+      const SourceManager &Manager = Decl->getASTContext().getSourceManager();
+      SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
+      checkAndAddLocation(Location);
+    }
+
+    return true;
+  }
+
+  bool VisitMemberExpr(const MemberExpr *Expr) {
+    const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
+    if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
+      const SourceManager &Manager = Decl->getASTContext().getSourceManager();
+      SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
+      checkAndAddLocation(Location);
+    }
+    return true;
+  }
+
+  // Other visitors:
+
+  bool VisitTypeLoc(const TypeLoc Loc) {
+    if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
+        USRSet.end())
+      checkAndAddLocation(Loc.getBeginLoc());
+    if (const auto *TemplateTypeParm =
+            dyn_cast<TemplateTypeParmType>(Loc.getType())) {
+      if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
+          USRSet.end())
+        checkAndAddLocation(Loc.getBeginLoc());
+    }
+    return true;
+  }
+
+  // Non-visitors:
+
+  // \brief Returns a list of unique locations. Duplicate or overlapping
+  // locations are erroneous and should be reported!
+  const std::vector<clang::SourceLocation> &getLocationsFound() const {
+    return LocationsFound;
+  }
+
+  // Namespace traversal:
+  void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
+    while (NameLoc) {
+      const NamespaceDecl *Decl =
+          NameLoc.getNestedNameSpecifier()->getAsNamespace();
+      if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
+        checkAndAddLocation(NameLoc.getLocalBeginLoc());
+      NameLoc = NameLoc.getPrefix();
+    }
+  }
+
+private:
+  void checkAndAddLocation(SourceLocation Loc) {
+    const SourceLocation BeginLoc = Loc;
+    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+        BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
+    StringRef TokenName =
+        Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
+                             Context.getSourceManager(), Context.getLangOpts());
+    size_t Offset = TokenName.find(PrevName);
+
+    // The token of the source location we find actually has the old
+    // name.
+    if (Offset != StringRef::npos)
+      LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
+  }
+
+  const std::set<std::string> USRSet;
+  const std::string PrevName;
+  std::vector<clang::SourceLocation> LocationsFound;
+  const ASTContext &Context;
+};
+
+SourceLocation StartLocationForType(TypeLoc TL) {
+  // For elaborated types (e.g. `struct a::A`) we want the portion after the
+  // `struct` but including the namespace qualifier, `a::`.
+  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
+    NestedNameSpecifierLoc NestedNameSpecifier =
+        ElaboratedTypeLoc.getQualifierLoc();
+    if (NestedNameSpecifier.getNestedNameSpecifier())
+      return NestedNameSpecifier.getBeginLoc();
+    TL = TL.getNextTypeLoc();
+  }
+  return TL.getLocStart();
+}
+
+SourceLocation EndLocationForType(TypeLoc TL) {
+  // Dig past any namespace or keyword qualifications.
+  while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
+         TL.getTypeLocClass() == TypeLoc::Qualified)
+    TL = TL.getNextTypeLoc();
+
+  // The location for template specializations (e.g. Foo<int>) includes the
+  // templated types in its location range.  We want to restrict this to just
+  // before the `<` character.
+  if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
+    return TL.castAs<TemplateSpecializationTypeLoc>()
+        .getLAngleLoc()
+        .getLocWithOffset(-1);
+  }
+  return TL.getEndLoc();
+}
+
+NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
+  // Dig past any keyword qualifications.
+  while (TL.getTypeLocClass() == TypeLoc::Qualified)
+    TL = TL.getNextTypeLoc();
+
+  // For elaborated types (e.g. `struct a::A`) we want the portion after the
+  // `struct` but including the namespace qualifier, `a::`.
+  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
+    return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
+  return nullptr;
+}
+
+// Find all locations identified by the given USRs for rename.
+//
+// This class will traverse the AST and find every AST node whose USR is in the
+// given USRs' set.
+class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
+public:
+  RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
+      : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
+
+  // A structure records all information of a symbol reference being renamed.
+  // We try to add as few prefix qualifiers as possible.
+  struct RenameInfo {
+    // The begin location of a symbol being renamed.
+    SourceLocation Begin;
+    // The end location of a symbol being renamed.
+    SourceLocation End;
+    // The declaration of a symbol being renamed (can be nullptr).
+    const NamedDecl *FromDecl;
+    // The declaration in which the nested name is contained (can be nullptr).
+    const Decl *Context;
+    // The nested name being replaced (can be nullptr).
+    const NestedNameSpecifier *Specifier;
+  };
+
+  // FIXME: Currently, prefix qualifiers will be added to the renamed symbol
+  // definition (e.g. "class Foo {};" => "class b::Bar {};" when renaming
+  // "a::Foo" to "b::Bar").
+  // For renaming declarations/definitions, prefix qualifiers should be filtered
+  // out.
+  bool VisitNamedDecl(const NamedDecl *Decl) {
+    // UsingDecl has been handled in other place.
+    if (llvm::isa<UsingDecl>(Decl))
+      return true;
+
+    // DestructorDecl has been handled in Typeloc.
+    if (llvm::isa<CXXDestructorDecl>(Decl))
+      return true;
+
+    if (Decl->isImplicit())
+      return true;
+
+    if (isInUSRSet(Decl)) {
+      RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr,
+                         nullptr, nullptr};
+      RenameInfos.push_back(Info);
+    }
+    return true;
+  }
+
+  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+    const NamedDecl *Decl = Expr->getFoundDecl();
+    if (isInUSRSet(Decl)) {
+      RenameInfo Info = {Expr->getSourceRange().getBegin(),
+                         Expr->getSourceRange().getEnd(), Decl,
+                         getClosestAncestorDecl(*Expr), Expr->getQualifier()};
+      RenameInfos.push_back(Info);
+    }
+
+    return true;
+  }
+
+  bool VisitUsingDecl(const UsingDecl *Using) {
+    for (const auto *UsingShadow : Using->shadows()) {
+      if (isInUSRSet(UsingShadow->getTargetDecl())) {
+        UsingDecls.push_back(Using);
+        break;
+      }
+    }
+    return true;
+  }
+
+  bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
+    if (!NestedLoc.getNestedNameSpecifier()->getAsType())
+      return true;
+    if (IsTypeAliasWhichWillBeRenamedElsewhere(NestedLoc.getTypeLoc()))
+      return true;
+
+    if (const auto *TargetDecl =
+            getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
+      if (isInUSRSet(TargetDecl)) {
+        RenameInfo Info = {NestedLoc.getBeginLoc(),
+                           EndLocationForType(NestedLoc.getTypeLoc()),
+                           TargetDecl, getClosestAncestorDecl(NestedLoc),
+                           NestedLoc.getNestedNameSpecifier()->getPrefix()};
+        RenameInfos.push_back(Info);
+      }
+    }
+    return true;
+  }
+
+  bool VisitTypeLoc(TypeLoc Loc) {
+    if (IsTypeAliasWhichWillBeRenamedElsewhere(Loc))
+      return true;
+
+    auto Parents = Context.getParents(Loc);
+    TypeLoc ParentTypeLoc;
+    if (!Parents.empty()) {
+      // Handle cases of nested name specificier locations.
+      //
+      // The VisitNestedNameSpecifierLoc interface is not impelmented in
+      // RecursiveASTVisitor, we have to handle it explicitly.
+      if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
+        VisitNestedNameSpecifierLocations(*NSL);
+        return true;
+      }
+
+      if (const auto *TL = Parents[0].get<TypeLoc>())
+        ParentTypeLoc = *TL;
+    }
+
+    // Handle the outermost TypeLoc which is directly linked to the interesting
+    // declaration and don't handle nested name specifier locations.
+    if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
+      if (isInUSRSet(TargetDecl)) {
+        // Only handle the outermost typeLoc.
+        //
+        // For a type like "a::Foo", there will be two typeLocs for it.
+        // One ElaboratedType, the other is RecordType:
+        //
+        //   ElaboratedType 0x33b9390 'a::Foo' sugar
+        //   `-RecordType 0x338fef0 'class a::Foo'
+        //     `-CXXRecord 0x338fe58 'Foo'
+        //
+        // Skip if this is an inner typeLoc.
+        if (!ParentTypeLoc.isNull() &&
+            isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
+          return true;
+        RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc),
+                           TargetDecl, getClosestAncestorDecl(Loc),
+                           GetNestedNameForType(Loc)};
+        RenameInfos.push_back(Info);
+        return true;
+      }
+    }
+
+    // Handle specific template class specialiation cases.
+    if (const auto *TemplateSpecType =
+            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
+      TypeLoc TargetLoc = Loc;
+      if (!ParentTypeLoc.isNull()) {
+        if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
+          TargetLoc = ParentTypeLoc;
+      }
+
+      if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
+        TypeLoc TargetLoc = Loc;
+        // FIXME: Find a better way to handle this case.
+        // For the qualified template class specification type like
+        // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
+        // (ElaboratedType) of the TemplateSpecializationType in order to
+        // catch the prefix qualifiers "ns::".
+        if (!ParentTypeLoc.isNull() &&
+            llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
+          TargetLoc = ParentTypeLoc;
+        RenameInfo Info = {
+            StartLocationForType(TargetLoc), EndLocationForType(TargetLoc),
+            TemplateSpecType->getTemplateName().getAsTemplateDecl(),
+            getClosestAncestorDecl(
+                ast_type_traits::DynTypedNode::create(TargetLoc)),
+            GetNestedNameForType(TargetLoc)};
+        RenameInfos.push_back(Info);
+      }
+    }
+    return true;
+  }
+
+  // Returns a list of RenameInfo.
+  const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
+
+  // Returns a list of using declarations which are needed to update.
+  const std::vector<const UsingDecl *> &getUsingDecls() const {
+    return UsingDecls;
+  }
+
+private:
+  // FIXME: This method may not be suitable for renaming other types like alias
+  // types. Need to figure out a way to handle it.
+  bool IsTypeAliasWhichWillBeRenamedElsewhere(TypeLoc TL) const {
+    while (!TL.isNull()) {
+      // SubstTemplateTypeParm is the TypeLocation class for a substituted type
+      // inside a template expansion so we ignore these.  For example:
+      //
+      // template<typename T> struct S {
+      //   T t;  // <-- this T becomes a TypeLoc(int) with class
+      //         //     SubstTemplateTypeParm when S<int> is instantiated
+      // }
+      if (TL.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
+        return true;
+
+      // Typedef is the TypeLocation class for a type which is a typedef to the
+      // type we want to replace.  We ignore the use of the typedef as we will
+      // replace the definition of it.  For example:
+      //
+      // typedef int T;
+      // T a;  // <---  This T is a TypeLoc(int) with class Typedef.
+      if (TL.getTypeLocClass() == TypeLoc::Typedef)
+        return true;
+      TL = TL.getNextTypeLoc();
+    }
+    return false;
+  }
+
+  // Get the supported declaration from a given typeLoc. If the declaration type
+  // is not supported, returns nullptr.
+  //
+  // FIXME: support more types, e.g. enum, type alias.
+  const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
+    if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
+      return RD;
+    return nullptr;
+  }
+
+  // Get the closest ancester which is a declaration of a given AST node.
+  template <typename ASTNodeType>
+  const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
+    auto Parents = Context.getParents(Node);
+    // FIXME: figure out how to handle it when there are multiple parents.
+    if (Parents.size() != 1)
+      return nullptr;
+    if (ast_type_traits::ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(
+            Parents[0].getNodeKind()))
+      return Parents[0].template get<Decl>();
+    return getClosestAncestorDecl(Parents[0]);
+  }
+
+  // Get the parent typeLoc of a given typeLoc. If there is no such parent,
+  // return nullptr.
+  const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
+    auto Parents = Context.getParents(Loc);
+    // FIXME: figure out how to handle it when there are multiple parents.
+    if (Parents.size() != 1)
+      return nullptr;
+    return Parents[0].get<TypeLoc>();
+  }
+
+  // Check whether the USR of a given Decl is in the USRSet.
+  bool isInUSRSet(const Decl *Decl) const {
+    auto USR = getUSRForDecl(Decl);
+    if (USR.empty())
+      return false;
+    return llvm::is_contained(USRSet, USR);
+  }
+
+  const std::set<std::string> USRSet;
+  ASTContext &Context;
+  std::vector<RenameInfo> RenameInfos;
+  // Record all interested using declarations which contains the using-shadow
+  // declarations of the symbol declarations being renamed.
+  std::vector<const UsingDecl *> UsingDecls;
+};
+
+} // namespace
+
+std::vector<SourceLocation>
+getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
+                   Decl *Decl) {
+  USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
+  Visitor.TraverseDecl(Decl);
+  NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
+
+  for (const auto &Location : Finder.getNestedNameSpecifierLocations())
+    Visitor.handleNestedNameSpecifierLoc(Location);
+
+  return Visitor.getLocationsFound();
+}
+
+std::vector<tooling::AtomicChange>
+createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
+                          llvm::StringRef NewName, Decl *TranslationUnitDecl) {
+  RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
+  Finder.TraverseDecl(TranslationUnitDecl);
+
+  const SourceManager &SM =
+      TranslationUnitDecl->getASTContext().getSourceManager();
+
+  std::vector<tooling::AtomicChange> AtomicChanges;
+  auto Replace = [&](SourceLocation Start, SourceLocation End,
+                     llvm::StringRef Text) {
+    tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
+    llvm::Error Err = ReplaceChange.replace(
+        SM, CharSourceRange::getTokenRange(Start, End), Text);
+    if (Err) {
+      llvm::errs() << "Faile to add replacement to AtomicChange: "
+                   << llvm::toString(std::move(Err)) << "\n";
+      return;
+    }
+    AtomicChanges.push_back(std::move(ReplaceChange));
+  };
+
+  for (const auto &RenameInfo : Finder.getRenameInfos()) {
+    std::string ReplacedName = NewName.str();
+    if (RenameInfo.FromDecl && RenameInfo.Context) {
+      if (!llvm::isa<clang::TranslationUnitDecl>(
+              RenameInfo.Context->getDeclContext())) {
+        ReplacedName = tooling::replaceNestedName(
+            RenameInfo.Specifier, RenameInfo.Context->getDeclContext(),
+            RenameInfo.FromDecl,
+            NewName.startswith("::") ? NewName.str() : ("::" + NewName).str());
+      }
+    }
+    // If the NewName contains leading "::", add it back.
+    if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
+      ReplacedName = NewName.str();
+    Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
+  }
+
+  // Hanlde using declarations explicitly as "using a::Foo" don't trigger
+  // typeLoc for "a::Foo".
+  for (const auto *Using : Finder.getUsingDecls())
+    Replace(Using->getLocStart(), Using->getLocEnd(), "using " + NewName.str());
+
+  return AtomicChanges;
+}
+
+} // end namespace tooling
+} // end namespace clang
Index: lib/Tooling/Refactoring/USRFindingAction.cpp
===================================================================
--- /dev/null
+++ lib/Tooling/Refactoring/USRFindingAction.cpp
@@ -0,0 +1,236 @@
+//===--- USRFindingAction.cpp - Clang refactoring library -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides an action to find USR for the symbol at <offset>, as well as
+/// all additional USRs.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/USRFindingAction.h"
+#include "clang/Tooling/Refactoring/USRFinder.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+
+#include <algorithm>
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+namespace {
+// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
+// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
+// Decl refers to class and adds USRs of all overridden methods if Decl refers
+// to virtual method.
+class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
+public:
+  AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
+      : FoundDecl(FoundDecl), Context(Context) {}
+
+  std::vector<std::string> Find() {
+    // Fill OverriddenMethods and PartialSpecs storages.
+    TraverseDecl(Context.getTranslationUnitDecl());
+    if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
+      addUSRsOfOverridenFunctions(MethodDecl);
+      for (const auto &OverriddenMethod : OverriddenMethods) {
+        if (checkIfOverriddenFunctionAscends(OverriddenMethod))
+          USRSet.insert(getUSRForDecl(OverriddenMethod));
+      }
+    } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
+      handleCXXRecordDecl(RecordDecl);
+    } else if (const auto *TemplateDecl =
+                   dyn_cast<ClassTemplateDecl>(FoundDecl)) {
+      handleClassTemplateDecl(TemplateDecl);
+    } else {
+      USRSet.insert(getUSRForDecl(FoundDecl));
+    }
+    return std::vector<std::string>(USRSet.begin(), USRSet.end());
+  }
+
+  bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
+    if (MethodDecl->isVirtual())
+      OverriddenMethods.push_back(MethodDecl);
+    return true;
+  }
+
+  bool VisitClassTemplatePartialSpecializationDecl(
+      const ClassTemplatePartialSpecializationDecl *PartialSpec) {
+    PartialSpecs.push_back(PartialSpec);
+    return true;
+  }
+
+private:
+  void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
+    RecordDecl = RecordDecl->getDefinition();
+    if (const auto *ClassTemplateSpecDecl =
+            dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl))
+      handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
+    addUSRsOfCtorDtors(RecordDecl);
+  }
+
+  void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
+    for (const auto *Specialization : TemplateDecl->specializations())
+      addUSRsOfCtorDtors(Specialization);
+
+    for (const auto *PartialSpec : PartialSpecs) {
+      if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
+        addUSRsOfCtorDtors(PartialSpec);
+    }
+    addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
+  }
+
+  void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
+    RecordDecl = RecordDecl->getDefinition();
+
+    // Skip if the CXXRecordDecl doesn't have definition.
+    if (!RecordDecl)
+      return;
+
+    for (const auto *CtorDecl : RecordDecl->ctors())
+      USRSet.insert(getUSRForDecl(CtorDecl));
+
+    USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
+    USRSet.insert(getUSRForDecl(RecordDecl));
+  }
+
+  void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) {
+    USRSet.insert(getUSRForDecl(MethodDecl));
+    // Recursively visit each OverridenMethod.
+    for (const auto &OverriddenMethod : MethodDecl->overridden_methods())
+      addUSRsOfOverridenFunctions(OverriddenMethod);
+  }
+
+  bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
+    for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
+      if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
+        return true;
+      return checkIfOverriddenFunctionAscends(OverriddenMethod);
+    }
+    return false;
+  }
+
+  const Decl *FoundDecl;
+  ASTContext &Context;
+  std::set<std::string> USRSet;
+  std::vector<const CXXMethodDecl *> OverriddenMethods;
+  std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs;
+};
+} // namespace
+
+class NamedDeclFindingConsumer : public ASTConsumer {
+public:
+  NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
+                           ArrayRef<std::string> QualifiedNames,
+                           std::vector<std::string> &SpellingNames,
+                           std::vector<std::vector<std::string>> &USRList,
+                           bool Force, bool &ErrorOccurred)
+      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
+        SpellingNames(SpellingNames), USRList(USRList), Force(Force),
+        ErrorOccurred(ErrorOccurred) {}
+
+private:
+  bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr,
+                  unsigned SymbolOffset, const std::string &QualifiedName) {
+    DiagnosticsEngine &Engine = Context.getDiagnostics();
+    const FileID MainFileID = SourceMgr.getMainFileID();
+
+    if (SymbolOffset >= SourceMgr.getFileIDSize(MainFileID)) {
+      ErrorOccurred = true;
+      unsigned InvalidOffset = Engine.getCustomDiagID(
+          DiagnosticsEngine::Error,
+          "SourceLocation in file %0 at offset %1 is invalid");
+      Engine.Report(SourceLocation(), InvalidOffset)
+          << SourceMgr.getFileEntryForID(MainFileID)->getName() << SymbolOffset;
+      return false;
+    }
+
+    const SourceLocation Point = SourceMgr.getLocForStartOfFile(MainFileID)
+                                     .getLocWithOffset(SymbolOffset);
+    const NamedDecl *FoundDecl = QualifiedName.empty()
+                                     ? getNamedDeclAt(Context, Point)
+                                     : getNamedDeclFor(Context, QualifiedName);
+
+    if (FoundDecl == nullptr) {
+      if (QualifiedName.empty()) {
+        FullSourceLoc FullLoc(Point, SourceMgr);
+        unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID(
+            DiagnosticsEngine::Error,
+            "clang-rename could not find symbol (offset %0)");
+        Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset;
+        ErrorOccurred = true;
+        return false;
+      }
+
+      if (Force)
+        return true;
+
+      unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
+          DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
+      Engine.Report(CouldNotFindSymbolNamed) << QualifiedName;
+      ErrorOccurred = true;
+      return false;
+    }
+
+    // If FoundDecl is a constructor or destructor, we want to instead take
+    // the Decl of the corresponding class.
+    if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
+      FoundDecl = CtorDecl->getParent();
+    else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
+      FoundDecl = DtorDecl->getParent();
+
+    SpellingNames.push_back(FoundDecl->getNameAsString());
+    AdditionalUSRFinder Finder(FoundDecl, Context);
+    USRList.push_back(Finder.Find());
+    return true;
+  }
+
+  void HandleTranslationUnit(ASTContext &Context) override {
+    const SourceManager &SourceMgr = Context.getSourceManager();
+    for (unsigned Offset : SymbolOffsets) {
+      if (!FindSymbol(Context, SourceMgr, Offset, ""))
+        return;
+    }
+    for (const std::string &QualifiedName : QualifiedNames) {
+      if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))
+        return;
+    }
+  }
+
+  ArrayRef<unsigned> SymbolOffsets;
+  ArrayRef<std::string> QualifiedNames;
+  std::vector<std::string> &SpellingNames;
+  std::vector<std::vector<std::string>> &USRList;
+  bool Force;
+  bool &ErrorOccurred;
+};
+
+std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() {
+  return llvm::make_unique<NamedDeclFindingConsumer>(
+      SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force,
+      ErrorOccurred);
+}
+
+} // end namespace tooling
+} // end namespace clang
Index: lib/Tooling/Refactoring/USRFinder.cpp
===================================================================
--- /dev/null
+++ lib/Tooling/Refactoring/USRFinder.cpp
@@ -0,0 +1,213 @@
+//===--- USRFinder.cpp - Clang refactoring library ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file Implements a recursive AST visitor that finds the USR of a symbol at a
+/// point.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/USRFinder.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Index/USRGeneration.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace llvm;
+
+namespace clang {
+namespace tooling {
+
+// NamedDeclFindingASTVisitor recursively visits each AST node to find the
+// symbol underneath the cursor.
+// FIXME: move to separate .h/.cc file if this gets too large.
+namespace {
+class NamedDeclFindingASTVisitor
+    : public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> {
+public:
+  // \brief Finds the NamedDecl at a point in the source.
+  // \param Point the location in the source to search for the NamedDecl.
+  explicit NamedDeclFindingASTVisitor(const SourceLocation Point,
+                                      const ASTContext &Context)
+      : Result(nullptr), Point(Point), Context(Context) {}
+
+  // \brief Finds the NamedDecl for a name in the source.
+  // \param Name the fully qualified name.
+  explicit NamedDeclFindingASTVisitor(const std::string &Name,
+                                      const ASTContext &Context)
+      : Result(nullptr), Name(Name), Context(Context) {}
+
+  // Declaration visitors:
+
+  // \brief Checks if the point falls within the NameDecl. This covers every
+  // declaration of a named entity that we may come across. Usually, just
+  // checking if the point lies within the length of the name of the declaration
+  // and the start location is sufficient.
+  bool VisitNamedDecl(const NamedDecl *Decl) {
+    return dyn_cast<CXXConversionDecl>(Decl)
+               ? true
+               : setResult(Decl, Decl->getLocation(),
+                           Decl->getNameAsString().length());
+  }
+
+  // Expression visitors:
+
+  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
+    const NamedDecl *Decl = Expr->getFoundDecl();
+    return setResult(Decl, Expr->getLocation(),
+                     Decl->getNameAsString().length());
+  }
+
+  bool VisitMemberExpr(const MemberExpr *Expr) {
+    const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
+    return setResult(Decl, Expr->getMemberLoc(),
+                     Decl->getNameAsString().length());
+  }
+
+  // Other visitors:
+
+  bool VisitTypeLoc(const TypeLoc Loc) {
+    const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
+    const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(
+        TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
+    if (const auto *TemplateTypeParm =
+            dyn_cast<TemplateTypeParmType>(Loc.getType()))
+      return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
+    if (const auto *TemplateSpecType =
+            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
+      return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
+                       TypeBeginLoc, TypeEndLoc);
+    }
+    return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
+                     TypeEndLoc);
+  }
+
+  bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
+    for (const auto *Initializer : ConstructorDecl->inits()) {
+      // Ignore implicit initializers.
+      if (!Initializer->isWritten())
+        continue;
+      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
+        const SourceLocation InitBeginLoc = Initializer->getSourceLocation(),
+                             InitEndLoc = Lexer::getLocForEndOfToken(
+                                 InitBeginLoc, 0, Context.getSourceManager(),
+                                 Context.getLangOpts());
+        if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc))
+          return false;
+      }
+    }
+    return true;
+  }
+
+  // Other:
+
+  const NamedDecl *getNamedDecl() { return Result; }
+
+  // \brief Determines if a namespace qualifier contains the point.
+  // \returns false on success and sets Result.
+  void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
+    while (NameLoc) {
+      const NamespaceDecl *Decl =
+          NameLoc.getNestedNameSpecifier()->getAsNamespace();
+      setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc());
+      NameLoc = NameLoc.getPrefix();
+    }
+  }
+
+private:
+  // \brief Sets Result to Decl if the Point is within Start and End.
+  // \returns false on success.
+  bool setResult(const NamedDecl *Decl, SourceLocation Start,
+                 SourceLocation End) {
+    if (!Decl)
+      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() &&
+          Name != "::" + Decl->getQualifiedNameAsString())
+        return true;
+    }
+    Result = Decl;
+    return false;
+  }
+
+  // \brief Sets Result to Decl if Point is within Loc and Loc + Offset.
+  // \returns false on success.
+  bool setResult(const NamedDecl *Decl, SourceLocation Loc, unsigned Offset) {
+    // FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc).
+    return Offset == 0 ||
+           setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));
+  }
+
+  // \brief Determines if the Point is within Start and End.
+  bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
+    // FIXME: Add tests for Point == End.
+    return Point == Start || Point == End ||
+           (Context.getSourceManager().isBeforeInTranslationUnit(Start,
+                                                                 Point) &&
+            Context.getSourceManager().isBeforeInTranslationUnit(Point, End));
+  }
+
+  const NamedDecl *Result;
+  const SourceLocation Point; // The location to find the NamedDecl.
+  const std::string Name;
+  const ASTContext &Context;
+};
+} // namespace
+
+const NamedDecl *getNamedDeclAt(const ASTContext &Context,
+                                const SourceLocation Point) {
+  const SourceManager &SM = Context.getSourceManager();
+  NamedDeclFindingASTVisitor Visitor(Point, Context);
+
+  // Try to be clever about pruning down the number of top-level declarations we
+  // see. If both start and end is either before or after the point we're
+  // looking for the point cannot be inside of this decl. Don't even look at it.
+  for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
+    SourceLocation StartLoc = CurrDecl->getLocStart();
+    SourceLocation EndLoc = CurrDecl->getLocEnd();
+    if (StartLoc.isValid() && EndLoc.isValid() &&
+        SM.isBeforeInTranslationUnit(StartLoc, Point) !=
+            SM.isBeforeInTranslationUnit(EndLoc, Point))
+      Visitor.TraverseDecl(CurrDecl);
+  }
+
+  NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context));
+  for (const auto &Location : Finder.getNestedNameSpecifierLocations())
+    Visitor.handleNestedNameSpecifierLoc(Location);
+
+  return Visitor.getNamedDecl();
+}
+
+const NamedDecl *getNamedDeclFor(const ASTContext &Context,
+                                 const std::string &Name) {
+  NamedDeclFindingASTVisitor Visitor(Name, Context);
+  Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+
+  return Visitor.getNamedDecl();
+}
+
+std::string getUSRForDecl(const Decl *Decl) {
+  llvm::SmallVector<char, 128> Buff;
+
+  // FIXME: Add test for the nullptr case.
+  if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff))
+    return "";
+
+  return std::string(Buff.data(), Buff.size());
+}
+
+} // end namespace tooling
+} // end namespace clang
Index: lib/Tooling/Refactoring/CMakeLists.txt
===================================================================
--- lib/Tooling/Refactoring/CMakeLists.txt
+++ lib/Tooling/Refactoring/CMakeLists.txt
@@ -5,6 +5,9 @@
 
 add_clang_library(clangToolingRefactor
   AtomicChange.cpp
+  USRFinder.cpp
+  USRFindingAction.cpp
+  USRLocFinder.cpp
 
   LINK_LIBS
   clangBasic
Index: include/clang/module.modulemap
===================================================================
--- include/clang/module.modulemap
+++ include/clang/module.modulemap
@@ -133,9 +133,10 @@
 
 module Clang_Tooling {
   requires cplusplus umbrella "Tooling" module * { export * }
-  // FIXME: Exclude this header to avoid pulling all of the AST matchers
+  // FIXME: Exclude these headers to avoid pulling all of the AST matchers
   // library into clang-format. Due to inline key functions in the headers,
   // importing the AST matchers library gives a link dependency on the AST
   // matchers (and thus the AST), which clang-format should not have.
   exclude header "Tooling/RefactoringCallbacks.h"
+  exclude header "Tooling/Refactoring/USRFinder.h"
 }
Index: include/clang/Tooling/Refactoring/USRLocFinder.h
===================================================================
--- /dev/null
+++ include/clang/Tooling/Refactoring/USRLocFinder.h
@@ -0,0 +1,49 @@
+//===--- USRLocFinder.h - Clang refactoring library -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides functionality for finding all instances of a USR in a given
+/// AST.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_USR_LOC_FINDER_H
+#define LLVM_CLANG_TOOLING_REFACTOR_USR_LOC_FINDER_H
+
+#include "clang/AST/AST.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// Create atomic changes for renaming all symbol references which are
+/// identified by the USRs set to a given new name.
+///
+/// \param USRs The set containing USRs of a particular old symbol.
+/// \param NewName The new name to replace old symbol name.
+/// \param TranslationUnitDecl The translation unit declaration.
+///
+/// \return Atomic changes for renaming.
+std::vector<tooling::AtomicChange>
+createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
+                          llvm::StringRef NewName, Decl *TranslationUnitDecl);
+
+// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
+std::vector<SourceLocation>
+getLocationsOfUSRs(const std::vector<std::string> &USRs,
+                   llvm::StringRef PrevName, Decl *Decl);
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_USR_LOC_FINDER_H
Index: include/clang/Tooling/Refactoring/USRFindingAction.h
===================================================================
--- /dev/null
+++ include/clang/Tooling/Refactoring/USRFindingAction.h
@@ -0,0 +1,54 @@
+//===--- USRFindingAction.h - Clang refactoring library -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides an action to find all relevant USRs at a point.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_USR_FINDING_ACTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_USR_FINDING_ACTION_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+
+#include <string>
+#include <vector>
+
+namespace clang {
+class ASTConsumer;
+class CompilerInstance;
+class NamedDecl;
+
+namespace tooling {
+
+struct USRFindingAction {
+  USRFindingAction(ArrayRef<unsigned> SymbolOffsets,
+                   ArrayRef<std::string> QualifiedNames, bool Force)
+      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
+        ErrorOccurred(false), Force(Force) {}
+  std::unique_ptr<ASTConsumer> newASTConsumer();
+
+  ArrayRef<std::string> getUSRSpellings() { return SpellingNames; }
+  ArrayRef<std::vector<std::string>> getUSRList() { return USRList; }
+  bool errorOccurred() { return ErrorOccurred; }
+
+private:
+  std::vector<unsigned> SymbolOffsets;
+  std::vector<std::string> QualifiedNames;
+  std::vector<std::string> SpellingNames;
+  std::vector<std::vector<std::string>> USRList;
+  bool ErrorOccurred;
+  bool Force;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_USR_FINDING_ACTION_H
Index: include/clang/Tooling/Refactoring/USRFinder.h
===================================================================
--- /dev/null
+++ include/clang/Tooling/Refactoring/USRFinder.h
@@ -0,0 +1,84 @@
+//===--- USRFinder.h - Clang refactoring library --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Methods for determining the USR of a symbol at a location in source
+/// code.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_USR_FINDER_H
+#define LLVM_CLANG_TOOLING_REFACTOR_USR_FINDER_H
+
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace clang::ast_matchers;
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class SourceLocation;
+class NamedDecl;
+
+namespace tooling {
+
+// Given an AST context and a point, returns a NamedDecl identifying the symbol
+// at the point. Returns null if nothing is found at the point.
+const NamedDecl *getNamedDeclAt(const ASTContext &Context,
+                                const SourceLocation Point);
+
+// Given an AST context and a fully qualified name, returns a NamedDecl
+// identifying the symbol with a matching name. Returns null if nothing is
+// found for the name.
+const NamedDecl *getNamedDeclFor(const ASTContext &Context,
+                                 const std::string &Name);
+
+// Converts a Decl into a USR.
+std::string getUSRForDecl(const Decl *Decl);
+
+// FIXME: Implement RecursiveASTVisitor<T>::VisitNestedNameSpecifier instead.
+class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback {
+public:
+  explicit NestedNameSpecifierLocFinder(ASTContext &Context)
+      : Context(Context) {}
+
+  std::vector<NestedNameSpecifierLoc> getNestedNameSpecifierLocations() {
+    addMatchers();
+    Finder.matchAST(Context);
+    return Locations;
+  }
+
+private:
+  void addMatchers() {
+    const auto NestedNameSpecifierLocMatcher =
+        nestedNameSpecifierLoc().bind("nestedNameSpecifierLoc");
+    Finder.addMatcher(NestedNameSpecifierLocMatcher, this);
+  }
+
+  void run(const MatchFinder::MatchResult &Result) override {
+    const auto *NNS = Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
+        "nestedNameSpecifierLoc");
+    Locations.push_back(*NNS);
+  }
+
+  ASTContext &Context;
+  std::vector<NestedNameSpecifierLoc> Locations;
+  MatchFinder Finder;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_USR_FINDER_H
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to