<div dir="ltr">Hi,<div><br></div><div>there are new memory leaks related to this change:</div><div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/6072/steps/check-clang%20asan/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/6072/steps/check-clang%20asan/logs/stdio</a><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 30, 2017 at 9:36 AM, Alex Lorenz via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: arphaman<br>
Date: Fri Jun 30 09:36:09 2017<br>
New Revision: 306840<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=306840&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=306840&view=rev</a><br>
Log:<br>
[refactor] Move clang-rename into the clang repository<br>
<br>
The core engine of clang-rename will be used for local and global renames in the<br>
new refactoring engine, as mentioned in<br>
<a href="http://lists.llvm.org/pipermail/cfe-dev/2017-June/054286.html" rel="noreferrer" target="_blank">http://lists.llvm.org/<wbr>pipermail/cfe-dev/2017-June/<wbr>054286.html</a>.<br>
<br>
The clang-rename tool is still supported but might get deprecated in the future.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D34696" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D34696</a><br>
<br>
Added:<br>
    cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<br>
    cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>RenamingAction.h<br>
    cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFinder.h<br>
    cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFindingAction.h<br>
    cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRLocFinder.h<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>RenamingAction.cpp<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/USRFinder.<wbr>cpp<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRFindingAction.cpp<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRLocFinder.cpp<br>
    cfe/trunk/test/clang-rename/<br>
    cfe/trunk/test/clang-rename/<wbr>ClassAsTemplateArgument.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>ClassFindByName.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>ClassReplacements.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>ClassSimpleRenaming.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>ClassTestMulti.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>ClassTestMultiByName.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>ComplexFunctionOverride.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>ComplicatedClassType.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>Ctor.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>CtorInitializer.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>DeclRefExpr.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>Field.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>FunctionMacro.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>FunctionOverride.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>FunctionWithClassFindByName.<wbr>cpp<br>
    cfe/trunk/test/clang-rename/<wbr>IncludeHeaderWithSymbol.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>Inputs/<br>
    cfe/trunk/test/clang-rename/<wbr>Inputs/HeaderWithSymbol.h<br>
    cfe/trunk/test/clang-rename/<wbr>Inputs/OffsetToNewName.yaml<br>
    cfe/trunk/test/clang-rename/<wbr>Inputs/QualifiedNameToNewName.<wbr>yaml<br>
    cfe/trunk/test/clang-rename/<wbr>InvalidNewName.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>InvalidOffset.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>InvalidQualifiedName.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>MemberExprMacro.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>Namespace.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>NoNewName.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>TemplateClassInstantiation.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>TemplateTypename.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>TemplatedClassFunction.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>UserDefinedConversion.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>Variable.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>VariableMacro.cpp<br>
    cfe/trunk/test/clang-rename/<wbr>YAMLInput.cpp<br>
    cfe/trunk/tools/clang-rename/<br>
    cfe/trunk/tools/clang-rename/<wbr>CMakeLists.txt<br>
    cfe/trunk/tools/clang-rename/<wbr>ClangRename.cpp<br>
    cfe/trunk/tools/clang-rename/<wbr>clang-rename.el<br>
    cfe/trunk/tools/clang-rename/<wbr>clang-rename.py<br>
    cfe/trunk/unittests/Rename/<br>
    cfe/trunk/unittests/Rename/<wbr>CMakeLists.txt<br>
    cfe/trunk/unittests/Rename/<wbr>ClangRenameTest.h<br>
    cfe/trunk/unittests/Rename/<wbr>RenameClassTest.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/<wbr>module.modulemap<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt<br>
    cfe/trunk/test/CMakeLists.txt<br>
    cfe/trunk/tools/CMakeLists.txt<br>
    cfe/trunk/unittests/<wbr>CMakeLists.txt<br>
<br>
Added: cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>RenamingAction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/Rename/RenamingAction.h?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Tooling/Refactoring/<wbr>Rename/RenamingAction.h?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>RenamingAction.h (added)<br>
+++ cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>RenamingAction.h Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,70 @@<br>
+//===--- RenamingAction.h - Clang refactoring library ---------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Provides an action to rename every symbol at a point.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_RENAMING_ACTION_H<br>
+#define LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_RENAMING_ACTION_H<br>
+<br>
+#include "clang/Tooling/Refactoring.h"<br>
+<br>
+namespace clang {<br>
+class ASTConsumer;<br>
+class CompilerInstance;<br>
+<br>
+namespace tooling {<br>
+<br>
+class RenamingAction {<br>
+public:<br>
+  RenamingAction(const std::vector<std::string> &NewNames,<br>
+                 const std::vector<std::string> &PrevNames,<br>
+                 const std::vector<std::vector<std::<wbr>string>> &USRList,<br>
+                 std::map<std::string, tooling::Replacements> &FileToReplaces,<br>
+                 bool PrintLocations = false)<br>
+      : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),<br>
+        FileToReplaces(FileToReplaces)<wbr>, PrintLocations(PrintLocations) {}<br>
+<br>
+  std::unique_ptr<ASTConsumer> newASTConsumer();<br>
+<br>
+private:<br>
+  const std::vector<std::string> &NewNames, &PrevNames;<br>
+  const std::vector<std::vector<std::<wbr>string>> &USRList;<br>
+  std::map<std::string, tooling::Replacements> &FileToReplaces;<br>
+  bool PrintLocations;<br>
+};<br>
+<br>
+/// Rename all symbols identified by the given USRs.<br>
+class QualifiedRenamingAction {<br>
+public:<br>
+  QualifiedRenamingAction(<br>
+      const std::vector<std::string> &NewNames,<br>
+      const std::vector<std::vector<std::<wbr>string>> &USRList,<br>
+      std::map<std::string, tooling::Replacements> &FileToReplaces)<br>
+      : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {}<br>
+<br>
+  std::unique_ptr<ASTConsumer> newASTConsumer();<br>
+<br>
+private:<br>
+  /// New symbol names.<br>
+  const std::vector<std::string> &NewNames;<br>
+<br>
+  /// A list of USRs. Each element represents USRs of a symbol being renamed.<br>
+  const std::vector<std::vector<std::<wbr>string>> &USRList;<br>
+<br>
+  /// A file path to replacements map.<br>
+  std::map<std::string, tooling::Replacements> &FileToReplaces;<br>
+};<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
+<br>
+#endif // LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_RENAMING_ACTION_H<br>
<br>
Added: cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFinder.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/Rename/USRFinder.h?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Tooling/Refactoring/<wbr>Rename/USRFinder.h?rev=306840&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFinder.h (added)<br>
+++ cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFinder.h Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,84 @@<br>
+//===--- USRFinder.h - Clang refactoring library --------------------------===/<wbr>/<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Methods for determining the USR of a symbol at a location in source<br>
+/// code.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_FINDER_H<br>
+#define LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_FINDER_H<br>
+<br>
+#include "clang/AST/AST.h"<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/ASTMatchers/<wbr>ASTMatchFinder.h"<br>
+#include <string><br>
+#include <vector><br>
+<br>
+using namespace llvm;<br>
+using namespace clang::ast_matchers;<br>
+<br>
+namespace clang {<br>
+<br>
+class ASTContext;<br>
+class Decl;<br>
+class SourceLocation;<br>
+class NamedDecl;<br>
+<br>
+namespace tooling {<br>
+<br>
+// Given an AST context and a point, returns a NamedDecl identifying the symbol<br>
+// at the point. Returns null if nothing is found at the point.<br>
+const NamedDecl *getNamedDeclAt(const ASTContext &Context,<br>
+                                const SourceLocation Point);<br>
+<br>
+// Given an AST context and a fully qualified name, returns a NamedDecl<br>
+// identifying the symbol with a matching name. Returns null if nothing is<br>
+// found for the name.<br>
+const NamedDecl *getNamedDeclFor(const ASTContext &Context,<br>
+                                 const std::string &Name);<br>
+<br>
+// Converts a Decl into a USR.<br>
+std::string getUSRForDecl(const Decl *Decl);<br>
+<br>
+// FIXME: Implement RecursiveASTVisitor<T>::<wbr>VisitNestedNameSpecifier instead.<br>
+class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback {<br>
+public:<br>
+  explicit NestedNameSpecifierLocFinder(<wbr>ASTContext &Context)<br>
+      : Context(Context) {}<br>
+<br>
+  std::vector<<wbr>NestedNameSpecifierLoc> getNestedNameSpecifierLocation<wbr>s() {<br>
+    addMatchers();<br>
+    Finder.matchAST(Context);<br>
+    return Locations;<br>
+  }<br>
+<br>
+private:<br>
+  void addMatchers() {<br>
+    const auto NestedNameSpecifierLocMatcher =<br>
+        nestedNameSpecifierLoc().bind(<wbr>"nestedNameSpecifierLoc");<br>
+    Finder.addMatcher(<wbr>NestedNameSpecifierLocMatcher, this);<br>
+  }<br>
+<br>
+  void run(const MatchFinder::MatchResult &Result) override {<br>
+    const auto *NNS = Result.Nodes.getNodeAs<<wbr>NestedNameSpecifierLoc>(<br>
+        "nestedNameSpecifierLoc");<br>
+    Locations.push_back(*NNS);<br>
+  }<br>
+<br>
+  ASTContext &Context;<br>
+  std::vector<<wbr>NestedNameSpecifierLoc> Locations;<br>
+  MatchFinder Finder;<br>
+};<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
+<br>
+#endif // LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_FINDER_H<br>
<br>
Added: cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFindingAction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Tooling/Refactoring/<wbr>Rename/USRFindingAction.h?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFindingAction.h (added)<br>
+++ cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRFindingAction.h Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,54 @@<br>
+//===--- USRFindingAction.h - Clang refactoring library -------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Provides an action to find all relevant USRs at a point.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_FINDING_ACTION_H<br>
+#define LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_FINDING_ACTION_H<br>
+<br>
+#include "clang/Basic/LLVM.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+<br>
+#include <string><br>
+#include <vector><br>
+<br>
+namespace clang {<br>
+class ASTConsumer;<br>
+class CompilerInstance;<br>
+class NamedDecl;<br>
+<br>
+namespace tooling {<br>
+<br>
+struct USRFindingAction {<br>
+  USRFindingAction(ArrayRef<<wbr>unsigned> SymbolOffsets,<br>
+                   ArrayRef<std::string> QualifiedNames, bool Force)<br>
+      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames)<wbr>,<br>
+        ErrorOccurred(false), Force(Force) {}<br>
+  std::unique_ptr<ASTConsumer> newASTConsumer();<br>
+<br>
+  ArrayRef<std::string> getUSRSpellings() { return SpellingNames; }<br>
+  ArrayRef<std::vector<std::<wbr>string>> getUSRList() { return USRList; }<br>
+  bool errorOccurred() { return ErrorOccurred; }<br>
+<br>
+private:<br>
+  std::vector<unsigned> SymbolOffsets;<br>
+  std::vector<std::string> QualifiedNames;<br>
+  std::vector<std::string> SpellingNames;<br>
+  std::vector<std::vector<std::<wbr>string>> USRList;<br>
+  bool ErrorOccurred;<br>
+  bool Force;<br>
+};<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
+<br>
+#endif // LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_FINDING_ACTION_H<br>
<br>
Added: cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRLocFinder.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Tooling/Refactoring/<wbr>Rename/USRLocFinder.h?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRLocFinder.h (added)<br>
+++ cfe/trunk/include/clang/<wbr>Tooling/Refactoring/Rename/<wbr>USRLocFinder.h Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,49 @@<br>
+//===--- USRLocFinder.h - Clang refactoring library -----------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Provides functionality for finding all instances of a USR in a given<br>
+/// AST.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_LOC_FINDER_H<br>
+#define LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_LOC_FINDER_H<br>
+<br>
+#include "clang/AST/AST.h"<br>
+#include "clang/Tooling/Core/<wbr>Replacement.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>AtomicChange.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include <string><br>
+#include <vector><br>
+<br>
+namespace clang {<br>
+namespace tooling {<br>
+<br>
+/// Create atomic changes for renaming all symbol references which are<br>
+/// identified by the USRs set to a given new name.<br>
+///<br>
+/// \param USRs The set containing USRs of a particular old symbol.<br>
+/// \param NewName The new name to replace old symbol name.<br>
+/// \param TranslationUnitDecl The translation unit declaration.<br>
+///<br>
+/// \return Atomic changes for renaming.<br>
+std::vector<tooling::<wbr>AtomicChange><br>
+createRenameAtomicChanges(<wbr>llvm::ArrayRef<std::string> USRs,<br>
+                          llvm::StringRef NewName, Decl *TranslationUnitDecl);<br>
+<br>
+// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!<br>
+std::vector<SourceLocation><br>
+getLocationsOfUSRs(const std::vector<std::string> &USRs,<br>
+                   llvm::StringRef PrevName, Decl *Decl);<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
+<br>
+#endif // LLVM_CLANG_TOOLING_REFACTOR_<wbr>RENAME_USR_LOC_FINDER_H<br>
<br>
Modified: cfe/trunk/include/clang/<wbr>module.modulemap<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/module.modulemap?rev=306840&r1=306839&r2=306840&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/module.modulemap?rev=<wbr>306840&r1=306839&r2=306840&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>module.modulemap (original)<br>
+++ cfe/trunk/include/clang/<wbr>module.modulemap Fri Jun 30 09:36:09 2017<br>
@@ -133,9 +133,10 @@ module Clang_StaticAnalyzer_Frontend {<br>
<br>
 module Clang_Tooling {<br>
   requires cplusplus umbrella "Tooling" module * { export * }<br>
-  // FIXME: Exclude this header to avoid pulling all of the AST matchers<br>
+  // FIXME: Exclude these headers to avoid pulling all of the AST matchers<br>
   // library into clang-format. Due to inline key functions in the headers,<br>
   // importing the AST matchers library gives a link dependency on the AST<br>
   // matchers (and thus the AST), which clang-format should not have.<br>
   exclude header "Tooling/RefactoringCallbacks.<wbr>h"<br>
+  exclude header "Tooling/Refactoring/Rename/<wbr>USRFinder.h"<br>
 }<br>
<br>
Modified: cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt?rev=306840&r1=306839&r2=306840&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt?<wbr>rev=306840&r1=306839&r2=<wbr>306840&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt (original)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt Fri Jun 30 09:36:09 2017<br>
@@ -5,8 +5,16 @@ set(LLVM_LINK_COMPONENTS<br>
<br>
 add_clang_library(<wbr>clangToolingRefactor<br>
   AtomicChange.cpp<br>
+  Rename/RenamingAction.cpp<br>
+  Rename/USRFinder.cpp<br>
+  Rename/USRFindingAction.cpp<br>
+  Rename/USRLocFinder.cpp<br>
<br>
   LINK_LIBS<br>
+  clangAST<br>
+  clangASTMatchers<br>
   clangBasic<br>
+  clangIndex<br>
+  clangLex<br>
   clangToolingCore<br>
   )<br>
<br>
Added: cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>RenamingAction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Rename/RenamingAction.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>RenamingAction.cpp?rev=306840&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>RenamingAction.cpp (added)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>RenamingAction.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,134 @@<br>
+//===--- RenamingAction.cpp - Clang refactoring library -------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Provides an action to rename every symbol at a point.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/RenamingAction.h"<br>
+#include "clang/AST/ASTConsumer.h"<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/Basic/FileManager.h"<br>
+#include "clang/Frontend/<wbr>CompilerInstance.h"<br>
+#include "clang/Frontend/<wbr>FrontendAction.h"<br>
+#include "clang/Lex/Lexer.h"<br>
+#include "clang/Lex/Preprocessor.h"<br>
+#include "clang/Tooling/<wbr>CommonOptionsParser.h"<br>
+#include "clang/Tooling/Refactoring.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRLocFinder.h"<br>
+#include "clang/Tooling/Tooling.h"<br>
+#include <string><br>
+#include <vector><br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace clang {<br>
+namespace tooling {<br>
+<br>
+class RenamingASTConsumer : public ASTConsumer {<br>
+public:<br>
+  RenamingASTConsumer(<br>
+      const std::vector<std::string> &NewNames,<br>
+      const std::vector<std::string> &PrevNames,<br>
+      const std::vector<std::vector<std::<wbr>string>> &USRList,<br>
+      std::map<std::string, tooling::Replacements> &FileToReplaces,<br>
+      bool PrintLocations)<br>
+      : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),<br>
+        FileToReplaces(FileToReplaces)<wbr>, PrintLocations(PrintLocations) {}<br>
+<br>
+  void HandleTranslationUnit(<wbr>ASTContext &Context) override {<br>
+    for (unsigned I = 0; I < NewNames.size(); ++I)<br>
+      HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);<br>
+  }<br>
+<br>
+  void HandleOneRename(ASTContext &Context, const std::string &NewName,<br>
+                       const std::string &PrevName,<br>
+                       const std::vector<std::string> &USRs) {<br>
+    const SourceManager &SourceMgr = Context.getSourceManager();<br>
+    std::vector<SourceLocation> RenamingCandidates;<br>
+    std::vector<SourceLocation> NewCandidates;<br>
+<br>
+    NewCandidates = tooling::getLocationsOfUSRs(<br>
+        USRs, PrevName, Context.<wbr>getTranslationUnitDecl());<br>
+    RenamingCandidates.insert(<wbr>RenamingCandidates.end(), NewCandidates.begin(),<br>
+                              NewCandidates.end());<br>
+<br>
+    unsigned PrevNameLen = PrevName.length();<br>
+    for (const auto &Loc : RenamingCandidates) {<br>
+      if (PrintLocations) {<br>
+        FullSourceLoc FullLoc(Loc, SourceMgr);<br>
+        errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc)<br>
+               << ":" << FullLoc.getSpellingLineNumber(<wbr>) << ":"<br>
+               << FullLoc.<wbr>getSpellingColumnNumber() << "\n";<br>
+      }<br>
+      // FIXME: better error handling.<br>
+      tooling::Replacement Replace(SourceMgr, Loc, PrevNameLen, NewName);<br>
+      llvm::Error Err = FileToReplaces[Replace.<wbr>getFilePath()].add(Replace);<br>
+      if (Err)<br>
+        llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "<br>
+                     << llvm::toString(std::move(Err)) << "\n";<br>
+    }<br>
+  }<br>
+<br>
+private:<br>
+  const std::vector<std::string> &NewNames, &PrevNames;<br>
+  const std::vector<std::vector<std::<wbr>string>> &USRList;<br>
+  std::map<std::string, tooling::Replacements> &FileToReplaces;<br>
+  bool PrintLocations;<br>
+};<br>
+<br>
+// A renamer to rename symbols which are identified by a give USRList to<br>
+// new name.<br>
+//<br>
+// FIXME: Merge with the above RenamingASTConsumer.<br>
+class USRSymbolRenamer : public ASTConsumer {<br>
+public:<br>
+  USRSymbolRenamer(const std::vector<std::string> &NewNames,<br>
+                   const std::vector<std::vector<std::<wbr>string>> &USRList,<br>
+                   std::map<std::string, tooling::Replacements> &FileToReplaces)<br>
+      : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {<br>
+    assert(USRList.size() == NewNames.size());<br>
+  }<br>
+<br>
+  void HandleTranslationUnit(<wbr>ASTContext &Context) override {<br>
+    for (unsigned I = 0; I < NewNames.size(); ++I) {<br>
+      // FIXME: Apply AtomicChanges directly once the refactoring APIs are<br>
+      // ready.<br>
+      auto AtomicChanges = tooling::<wbr>createRenameAtomicChanges(<br>
+          USRList[I], NewNames[I], Context.<wbr>getTranslationUnitDecl());<br>
+      for (const auto AtomicChange : AtomicChanges) {<br>
+        for (const auto &Replace : AtomicChange.getReplacements()<wbr>) {<br>
+          llvm::Error Err = FileToReplaces[Replace.<wbr>getFilePath()].add(Replace);<br>
+          if (Err) {<br>
+            llvm::errs() << "Renaming failed in " << Replace.getFilePath()<br>
+                         << "! " << llvm::toString(std::move(Err)) << "\n";<br>
+          }<br>
+        }<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+private:<br>
+  const std::vector<std::string> &NewNames;<br>
+  const std::vector<std::vector<std::<wbr>string>> &USRList;<br>
+  std::map<std::string, tooling::Replacements> &FileToReplaces;<br>
+};<br>
+<br>
+std::unique_ptr<ASTConsumer> RenamingAction::<wbr>newASTConsumer() {<br>
+  return llvm::make_unique<<wbr>RenamingASTConsumer>(NewNames, PrevNames, USRList,<br>
+                                                FileToReplaces, PrintLocations);<br>
+}<br>
+<br>
+std::unique_ptr<ASTConsumer> QualifiedRenamingAction::<wbr>newASTConsumer() {<br>
+  return llvm::make_unique<<wbr>USRSymbolRenamer>(NewNames, USRList, FileToReplaces);<br>
+}<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
<br>
Added: cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/USRFinder.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Rename/USRFinder.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/USRFinder.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/USRFinder.<wbr>cpp (added)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/USRFinder.<wbr>cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,213 @@<br>
+//===--- USRFinder.cpp - Clang refactoring library ------------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file Implements a recursive AST visitor that finds the USR of a symbol at a<br>
+/// point.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRFinder.h"<br>
+#include "clang/AST/AST.h"<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/<wbr>RecursiveASTVisitor.h"<br>
+#include "clang/Index/USRGeneration.h"<br>
+#include "clang/Lex/Lexer.h"<br>
+#include "llvm/ADT/SmallVector.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace clang {<br>
+namespace tooling {<br>
+<br>
+// NamedDeclFindingASTVisitor recursively visits each AST node to find the<br>
+// symbol underneath the cursor.<br>
+// FIXME: move to separate .h/.cc file if this gets too large.<br>
+namespace {<br>
+class NamedDeclFindingASTVisitor<br>
+    : public clang::RecursiveASTVisitor<<wbr>NamedDeclFindingASTVisitor> {<br>
+public:<br>
+  // \brief Finds the NamedDecl at a point in the source.<br>
+  // \param Point the location in the source to search for the NamedDecl.<br>
+  explicit NamedDeclFindingASTVisitor(<wbr>const SourceLocation Point,<br>
+                                      const ASTContext &Context)<br>
+      : Result(nullptr), Point(Point), Context(Context) {}<br>
+<br>
+  // \brief Finds the NamedDecl for a name in the source.<br>
+  // \param Name the fully qualified name.<br>
+  explicit NamedDeclFindingASTVisitor(<wbr>const std::string &Name,<br>
+                                      const ASTContext &Context)<br>
+      : Result(nullptr), Name(Name), Context(Context) {}<br>
+<br>
+  // Declaration visitors:<br>
+<br>
+  // \brief Checks if the point falls within the NameDecl. This covers every<br>
+  // declaration of a named entity that we may come across. Usually, just<br>
+  // checking if the point lies within the length of the name of the declaration<br>
+  // and the start location is sufficient.<br>
+  bool VisitNamedDecl(const NamedDecl *Decl) {<br>
+    return dyn_cast<CXXConversionDecl>(<wbr>Decl)<br>
+               ? true<br>
+               : setResult(Decl, Decl->getLocation(),<br>
+                           Decl->getNameAsString().<wbr>length());<br>
+  }<br>
+<br>
+  // Expression visitors:<br>
+<br>
+  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {<br>
+    const NamedDecl *Decl = Expr->getFoundDecl();<br>
+    return setResult(Decl, Expr->getLocation(),<br>
+                     Decl->getNameAsString().<wbr>length());<br>
+  }<br>
+<br>
+  bool VisitMemberExpr(const MemberExpr *Expr) {<br>
+    const NamedDecl *Decl = Expr->getFoundDecl().getDecl()<wbr>;<br>
+    return setResult(Decl, Expr->getMemberLoc(),<br>
+                     Decl->getNameAsString().<wbr>length());<br>
+  }<br>
+<br>
+  // Other visitors:<br>
+<br>
+  bool VisitTypeLoc(const TypeLoc Loc) {<br>
+    const SourceLocation TypeBeginLoc = Loc.getBeginLoc();<br>
+    const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(<br>
+        TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());<br>
+    if (const auto *TemplateTypeParm =<br>
+            dyn_cast<TemplateTypeParmType><wbr>(Loc.getType()))<br>
+      return setResult(TemplateTypeParm-><wbr>getDecl(), TypeBeginLoc, TypeEndLoc);<br>
+    if (const auto *TemplateSpecType =<br>
+            dyn_cast<<wbr>TemplateSpecializationType>(<wbr>Loc.getType())) {<br>
+      return setResult(TemplateSpecType-><wbr>getTemplateName().<wbr>getAsTemplateDecl(),<br>
+                       TypeBeginLoc, TypeEndLoc);<br>
+    }<br>
+    return setResult(Loc.getType()-><wbr>getAsCXXRecordDecl(), TypeBeginLoc,<br>
+                     TypeEndLoc);<br>
+  }<br>
+<br>
+  bool VisitCXXConstructorDecl(clang:<wbr>:CXXConstructorDecl *ConstructorDecl) {<br>
+    for (const auto *Initializer : ConstructorDecl->inits()) {<br>
+      // Ignore implicit initializers.<br>
+      if (!Initializer->isWritten())<br>
+        continue;<br>
+      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {<br>
+        const SourceLocation InitBeginLoc = Initializer-><wbr>getSourceLocation(),<br>
+                             InitEndLoc = Lexer::getLocForEndOfToken(<br>
+                                 InitBeginLoc, 0, Context.getSourceManager(),<br>
+                                 Context.getLangOpts());<br>
+        if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc))<br>
+          return false;<br>
+      }<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  // Other:<br>
+<br>
+  const NamedDecl *getNamedDecl() { return Result; }<br>
+<br>
+  // \brief Determines if a namespace qualifier contains the point.<br>
+  // \returns false on success and sets Result.<br>
+  void handleNestedNameSpecifierLoc(<wbr>NestedNameSpecifierLoc NameLoc) {<br>
+    while (NameLoc) {<br>
+      const NamespaceDecl *Decl =<br>
+          NameLoc.<wbr>getNestedNameSpecifier()-><wbr>getAsNamespace();<br>
+      setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc());<br>
+      NameLoc = NameLoc.getPrefix();<br>
+    }<br>
+  }<br>
+<br>
+private:<br>
+  // \brief Sets Result to Decl if the Point is within Start and End.<br>
+  // \returns false on success.<br>
+  bool setResult(const NamedDecl *Decl, SourceLocation Start,<br>
+                 SourceLocation End) {<br>
+    if (!Decl)<br>
+      return true;<br>
+    if (Name.empty()) {<br>
+      // Offset is used to find the declaration.<br>
+      if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||<br>
+          !End.isFileID() || !isPointWithin(Start, End))<br>
+        return true;<br>
+    } else {<br>
+      // Fully qualified name is used to find the declaration.<br>
+      if (Name != Decl-><wbr>getQualifiedNameAsString() &&<br>
+          Name != "::" + Decl-><wbr>getQualifiedNameAsString())<br>
+        return true;<br>
+    }<br>
+    Result = Decl;<br>
+    return false;<br>
+  }<br>
+<br>
+  // \brief Sets Result to Decl if Point is within Loc and Loc + Offset.<br>
+  // \returns false on success.<br>
+  bool setResult(const NamedDecl *Decl, SourceLocation Loc, unsigned Offset) {<br>
+    // FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc).<br>
+    return Offset == 0 ||<br>
+           setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));<br>
+  }<br>
+<br>
+  // \brief Determines if the Point is within Start and End.<br>
+  bool isPointWithin(const SourceLocation Start, const SourceLocation End) {<br>
+    // FIXME: Add tests for Point == End.<br>
+    return Point == Start || Point == End ||<br>
+           (Context.getSourceManager().<wbr>isBeforeInTranslationUnit(<wbr>Start,<br>
+                                                                 Point) &&<br>
+            Context.getSourceManager().<wbr>isBeforeInTranslationUnit(<wbr>Point, End));<br>
+  }<br>
+<br>
+  const NamedDecl *Result;<br>
+  const SourceLocation Point; // The location to find the NamedDecl.<br>
+  const std::string Name;<br>
+  const ASTContext &Context;<br>
+};<br>
+} // namespace<br>
+<br>
+const NamedDecl *getNamedDeclAt(const ASTContext &Context,<br>
+                                const SourceLocation Point) {<br>
+  const SourceManager &SM = Context.getSourceManager();<br>
+  NamedDeclFindingASTVisitor Visitor(Point, Context);<br>
+<br>
+  // Try to be clever about pruning down the number of top-level declarations we<br>
+  // see. If both start and end is either before or after the point we're<br>
+  // looking for the point cannot be inside of this decl. Don't even look at it.<br>
+  for (auto *CurrDecl : Context.<wbr>getTranslationUnitDecl()-><wbr>decls()) {<br>
+    SourceLocation StartLoc = CurrDecl->getLocStart();<br>
+    SourceLocation EndLoc = CurrDecl->getLocEnd();<br>
+    if (StartLoc.isValid() && EndLoc.isValid() &&<br>
+        SM.isBeforeInTranslationUnit(<wbr>StartLoc, Point) !=<br>
+            SM.isBeforeInTranslationUnit(<wbr>EndLoc, Point))<br>
+      Visitor.TraverseDecl(CurrDecl)<wbr>;<br>
+  }<br>
+<br>
+  NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context));<br>
+  for (const auto &Location : Finder.<wbr>getNestedNameSpecifierLocation<wbr>s())<br>
+    Visitor.<wbr>handleNestedNameSpecifierLoc(<wbr>Location);<br>
+<br>
+  return Visitor.getNamedDecl();<br>
+}<br>
+<br>
+const NamedDecl *getNamedDeclFor(const ASTContext &Context,<br>
+                                 const std::string &Name) {<br>
+  NamedDeclFindingASTVisitor Visitor(Name, Context);<br>
+  Visitor.TraverseDecl(Context.<wbr>getTranslationUnitDecl());<br>
+<br>
+  return Visitor.getNamedDecl();<br>
+}<br>
+<br>
+std::string getUSRForDecl(const Decl *Decl) {<br>
+  llvm::SmallVector<char, 128> Buff;<br>
+<br>
+  // FIXME: Add test for the nullptr case.<br>
+  if (Decl == nullptr || index::generateUSRForDecl(<wbr>Decl, Buff))<br>
+    return "";<br>
+<br>
+  return std::string(Buff.data(), Buff.size());<br>
+}<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
<br>
Added: cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRFindingAction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRFindingAction.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRFindingAction.cpp (added)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRFindingAction.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,236 @@<br>
+//===--- USRFindingAction.cpp - Clang refactoring library -----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Provides an action to find USR for the symbol at <offset>, as well as<br>
+/// all additional USRs.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRFindingAction.h"<br>
+#include "clang/AST/AST.h"<br>
+#include "clang/AST/ASTConsumer.h"<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/Decl.h"<br>
+#include "clang/AST/<wbr>RecursiveASTVisitor.h"<br>
+#include "clang/Basic/FileManager.h"<br>
+#include "clang/Frontend/<wbr>CompilerInstance.h"<br>
+#include "clang/Frontend/<wbr>FrontendAction.h"<br>
+#include "clang/Lex/Lexer.h"<br>
+#include "clang/Lex/Preprocessor.h"<br>
+#include "clang/Tooling/<wbr>CommonOptionsParser.h"<br>
+#include "clang/Tooling/Refactoring.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRFinder.h"<br>
+#include "clang/Tooling/Tooling.h"<br>
+<br>
+#include <algorithm><br>
+#include <set><br>
+#include <string><br>
+#include <vector><br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace clang {<br>
+namespace tooling {<br>
+<br>
+namespace {<br>
+// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to<br>
+// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given<br>
+// Decl refers to class and adds USRs of all overridden methods if Decl refers<br>
+// to virtual method.<br>
+class AdditionalUSRFinder : public RecursiveASTVisitor<<wbr>AdditionalUSRFinder> {<br>
+public:<br>
+  AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)<br>
+      : FoundDecl(FoundDecl), Context(Context) {}<br>
+<br>
+  std::vector<std::string> Find() {<br>
+    // Fill OverriddenMethods and PartialSpecs storages.<br>
+    TraverseDecl(Context.<wbr>getTranslationUnitDecl());<br>
+    if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(<wbr>FoundDecl)) {<br>
+      addUSRsOfOverridenFunctions(<wbr>MethodDecl);<br>
+      for (const auto &OverriddenMethod : OverriddenMethods) {<br>
+        if (<wbr>checkIfOverriddenFunctionAscen<wbr>ds(OverriddenMethod))<br>
+          USRSet.insert(getUSRForDecl(<wbr>OverriddenMethod));<br>
+      }<br>
+    } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(<wbr>FoundDecl)) {<br>
+      handleCXXRecordDecl(<wbr>RecordDecl);<br>
+    } else if (const auto *TemplateDecl =<br>
+                   dyn_cast<ClassTemplateDecl>(<wbr>FoundDecl)) {<br>
+      handleClassTemplateDecl(<wbr>TemplateDecl);<br>
+    } else {<br>
+      USRSet.insert(getUSRForDecl(<wbr>FoundDecl));<br>
+    }<br>
+    return std::vector<std::string>(<wbr>USRSet.begin(), USRSet.end());<br>
+  }<br>
+<br>
+  bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {<br>
+    if (MethodDecl->isVirtual())<br>
+      OverriddenMethods.push_back(<wbr>MethodDecl);<br>
+    return true;<br>
+  }<br>
+<br>
+  bool VisitClassTemplatePartialSpeci<wbr>alizationDecl(<br>
+      const ClassTemplatePartialSpecializa<wbr>tionDecl *PartialSpec) {<br>
+    PartialSpecs.push_back(<wbr>PartialSpec);<br>
+    return true;<br>
+  }<br>
+<br>
+private:<br>
+  void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {<br>
+    RecordDecl = RecordDecl->getDefinition();<br>
+    if (const auto *ClassTemplateSpecDecl =<br>
+            dyn_cast<<wbr>ClassTemplateSpecializationDec<wbr>l>(RecordDecl))<br>
+      handleClassTemplateDecl(<wbr>ClassTemplateSpecDecl-><wbr>getSpecializedTemplate());<br>
+    addUSRsOfCtorDtors(RecordDecl)<wbr>;<br>
+  }<br>
+<br>
+  void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {<br>
+    for (const auto *Specialization : TemplateDecl->specializations(<wbr>))<br>
+      addUSRsOfCtorDtors(<wbr>Specialization);<br>
+<br>
+    for (const auto *PartialSpec : PartialSpecs) {<br>
+      if (PartialSpec-><wbr>getSpecializedTemplate() == TemplateDecl)<br>
+        addUSRsOfCtorDtors(<wbr>PartialSpec);<br>
+    }<br>
+    addUSRsOfCtorDtors(<wbr>TemplateDecl-><wbr>getTemplatedDecl());<br>
+  }<br>
+<br>
+  void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {<br>
+    RecordDecl = RecordDecl->getDefinition();<br>
+<br>
+    // Skip if the CXXRecordDecl doesn't have definition.<br>
+    if (!RecordDecl)<br>
+      return;<br>
+<br>
+    for (const auto *CtorDecl : RecordDecl->ctors())<br>
+      USRSet.insert(getUSRForDecl(<wbr>CtorDecl));<br>
+<br>
+    USRSet.insert(getUSRForDecl(<wbr>RecordDecl->getDestructor()));<br>
+    USRSet.insert(getUSRForDecl(<wbr>RecordDecl));<br>
+  }<br>
+<br>
+  void addUSRsOfOverridenFunctions(<wbr>const CXXMethodDecl *MethodDecl) {<br>
+    USRSet.insert(getUSRForDecl(<wbr>MethodDecl));<br>
+    // Recursively visit each OverridenMethod.<br>
+    for (const auto &OverriddenMethod : MethodDecl->overridden_<wbr>methods())<br>
+      addUSRsOfOverridenFunctions(<wbr>OverriddenMethod);<br>
+  }<br>
+<br>
+  bool checkIfOverriddenFunctionAscen<wbr>ds(const CXXMethodDecl *MethodDecl) {<br>
+    for (const auto &OverriddenMethod : MethodDecl->overridden_<wbr>methods()) {<br>
+      if (USRSet.find(getUSRForDecl(<wbr>OverriddenMethod)) != USRSet.end())<br>
+        return true;<br>
+      return checkIfOverriddenFunctionAscen<wbr>ds(OverriddenMethod);<br>
+    }<br>
+    return false;<br>
+  }<br>
+<br>
+  const Decl *FoundDecl;<br>
+  ASTContext &Context;<br>
+  std::set<std::string> USRSet;<br>
+  std::vector<const CXXMethodDecl *> OverriddenMethods;<br>
+  std::vector<const ClassTemplatePartialSpecializa<wbr>tionDecl *> PartialSpecs;<br>
+};<br>
+} // namespace<br>
+<br>
+class NamedDeclFindingConsumer : public ASTConsumer {<br>
+public:<br>
+  NamedDeclFindingConsumer(<wbr>ArrayRef<unsigned> SymbolOffsets,<br>
+                           ArrayRef<std::string> QualifiedNames,<br>
+                           std::vector<std::string> &SpellingNames,<br>
+                           std::vector<std::vector<std::<wbr>string>> &USRList,<br>
+                           bool Force, bool &ErrorOccurred)<br>
+      : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames)<wbr>,<br>
+        SpellingNames(SpellingNames), USRList(USRList), Force(Force),<br>
+        ErrorOccurred(ErrorOccurred) {}<br>
+<br>
+private:<br>
+  bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr,<br>
+                  unsigned SymbolOffset, const std::string &QualifiedName) {<br>
+    DiagnosticsEngine &Engine = Context.getDiagnostics();<br>
+    const FileID MainFileID = SourceMgr.getMainFileID();<br>
+<br>
+    if (SymbolOffset >= SourceMgr.getFileIDSize(<wbr>MainFileID)) {<br>
+      ErrorOccurred = true;<br>
+      unsigned InvalidOffset = Engine.getCustomDiagID(<br>
+          DiagnosticsEngine::Error,<br>
+          "SourceLocation in file %0 at offset %1 is invalid");<br>
+      Engine.Report(SourceLocation()<wbr>, InvalidOffset)<br>
+          << SourceMgr.getFileEntryForID(<wbr>MainFileID)->getName() << SymbolOffset;<br>
+      return false;<br>
+    }<br>
+<br>
+    const SourceLocation Point = SourceMgr.<wbr>getLocForStartOfFile(<wbr>MainFileID)<br>
+                                     .getLocWithOffset(<wbr>SymbolOffset);<br>
+    const NamedDecl *FoundDecl = QualifiedName.empty()<br>
+                                     ? getNamedDeclAt(Context, Point)<br>
+                                     : getNamedDeclFor(Context, QualifiedName);<br>
+<br>
+    if (FoundDecl == nullptr) {<br>
+      if (QualifiedName.empty()) {<br>
+        FullSourceLoc FullLoc(Point, SourceMgr);<br>
+        unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID(<br>
+            DiagnosticsEngine::Error,<br>
+            "clang-rename could not find symbol (offset %0)");<br>
+        Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset;<br>
+        ErrorOccurred = true;<br>
+        return false;<br>
+      }<br>
+<br>
+      if (Force)<br>
+        return true;<br>
+<br>
+      unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(<br>
+          DiagnosticsEngine::Error, "clang-rename could not find symbol %0");<br>
+      Engine.Report(<wbr>CouldNotFindSymbolNamed) << QualifiedName;<br>
+      ErrorOccurred = true;<br>
+      return false;<br>
+    }<br>
+<br>
+    // If FoundDecl is a constructor or destructor, we want to instead take<br>
+    // the Decl of the corresponding class.<br>
+    if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(<wbr>FoundDecl))<br>
+      FoundDecl = CtorDecl->getParent();<br>
+    else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(<wbr>FoundDecl))<br>
+      FoundDecl = DtorDecl->getParent();<br>
+<br>
+    SpellingNames.push_back(<wbr>FoundDecl->getNameAsString());<br>
+    AdditionalUSRFinder Finder(FoundDecl, Context);<br>
+    USRList.push_back(Finder.Find(<wbr>));<br>
+    return true;<br>
+  }<br>
+<br>
+  void HandleTranslationUnit(<wbr>ASTContext &Context) override {<br>
+    const SourceManager &SourceMgr = Context.getSourceManager();<br>
+    for (unsigned Offset : SymbolOffsets) {<br>
+      if (!FindSymbol(Context, SourceMgr, Offset, ""))<br>
+        return;<br>
+    }<br>
+    for (const std::string &QualifiedName : QualifiedNames) {<br>
+      if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))<br>
+        return;<br>
+    }<br>
+  }<br>
+<br>
+  ArrayRef<unsigned> SymbolOffsets;<br>
+  ArrayRef<std::string> QualifiedNames;<br>
+  std::vector<std::string> &SpellingNames;<br>
+  std::vector<std::vector<std::<wbr>string>> &USRList;<br>
+  bool Force;<br>
+  bool &ErrorOccurred;<br>
+};<br>
+<br>
+std::unique_ptr<ASTConsumer> USRFindingAction::<wbr>newASTConsumer() {<br>
+  return llvm::make_unique<<wbr>NamedDeclFindingConsumer>(<br>
+      SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force,<br>
+      ErrorOccurred);<br>
+}<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
<br>
Added: cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRLocFinder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRLocFinder.cpp?rev=306840&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRLocFinder.cpp (added)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/Rename/<wbr>USRLocFinder.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,509 @@<br>
+//===--- USRLocFinder.cpp - Clang refactoring library ---------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief Methods for finding all instances of a USR. Our strategy is very<br>
+/// simple; we just compare the USR at every relevant AST node with the one<br>
+/// provided.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRLocFinder.h"<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/<wbr>RecursiveASTVisitor.h"<br>
+#include "clang/Basic/LLVM.h"<br>
+#include "clang/Basic/SourceLocation.h"<br>
+#include "clang/Basic/SourceManager.h"<br>
+#include "clang/Lex/Lexer.h"<br>
+#include "clang/Tooling/Core/Lookup.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRFinder.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Support/Casting.h"<br>
+#include <cstddef><br>
+#include <set><br>
+#include <string><br>
+#include <vector><br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace clang {<br>
+namespace tooling {<br>
+<br>
+namespace {<br>
+<br>
+// \brief This visitor recursively searches for all instances of a USR in a<br>
+// translation unit and stores them for later usage.<br>
+class USRLocFindingASTVisitor<br>
+    : public clang::RecursiveASTVisitor<<wbr>USRLocFindingASTVisitor> {<br>
+public:<br>
+  explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,<br>
+                                   StringRef PrevName,<br>
+                                   const ASTContext &Context)<br>
+      : USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {<br>
+  }<br>
+<br>
+  // Declaration visitors:<br>
+<br>
+  bool VisitCXXConstructorDecl(clang:<wbr>:CXXConstructorDecl *ConstructorDecl) {<br>
+    for (const auto *Initializer : ConstructorDecl->inits()) {<br>
+      // Ignore implicit initializers.<br>
+      if (!Initializer->isWritten())<br>
+        continue;<br>
+      if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {<br>
+        if (USRSet.find(getUSRForDecl(<wbr>FieldDecl)) != USRSet.end())<br>
+          LocationsFound.push_back(<wbr>Initializer-><wbr>getSourceLocation());<br>
+      }<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  bool VisitNamedDecl(const NamedDecl *Decl) {<br>
+    if (USRSet.find(getUSRForDecl(<wbr>Decl)) != USRSet.end())<br>
+      checkAndAddLocation(Decl-><wbr>getLocation());<br>
+    return true;<br>
+  }<br>
+<br>
+  // Expression visitors:<br>
+<br>
+  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {<br>
+    const NamedDecl *Decl = Expr->getFoundDecl();<br>
+<br>
+    if (USRSet.find(getUSRForDecl(<wbr>Decl)) != USRSet.end()) {<br>
+      const SourceManager &Manager = Decl->getASTContext().<wbr>getSourceManager();<br>
+      SourceLocation Location = Manager.getSpellingLoc(Expr-><wbr>getLocation());<br>
+      checkAndAddLocation(Location);<br>
+    }<br>
+<br>
+    return true;<br>
+  }<br>
+<br>
+  bool VisitMemberExpr(const MemberExpr *Expr) {<br>
+    const NamedDecl *Decl = Expr->getFoundDecl().getDecl()<wbr>;<br>
+    if (USRSet.find(getUSRForDecl(<wbr>Decl)) != USRSet.end()) {<br>
+      const SourceManager &Manager = Decl->getASTContext().<wbr>getSourceManager();<br>
+      SourceLocation Location = Manager.getSpellingLoc(Expr-><wbr>getMemberLoc());<br>
+      checkAndAddLocation(Location);<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  // Other visitors:<br>
+<br>
+  bool VisitTypeLoc(const TypeLoc Loc) {<br>
+    if (USRSet.find(getUSRForDecl(<wbr>Loc.getType()-><wbr>getAsCXXRecordDecl())) !=<br>
+        USRSet.end())<br>
+      checkAndAddLocation(Loc.<wbr>getBeginLoc());<br>
+    if (const auto *TemplateTypeParm =<br>
+            dyn_cast<TemplateTypeParmType><wbr>(Loc.getType())) {<br>
+      if (USRSet.find(getUSRForDecl(<wbr>TemplateTypeParm->getDecl())) !=<br>
+          USRSet.end())<br>
+        checkAndAddLocation(Loc.<wbr>getBeginLoc());<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  // Non-visitors:<br>
+<br>
+  // \brief Returns a list of unique locations. Duplicate or overlapping<br>
+  // locations are erroneous and should be reported!<br>
+  const std::vector<clang::<wbr>SourceLocation> &getLocationsFound() const {<br>
+    return LocationsFound;<br>
+  }<br>
+<br>
+  // Namespace traversal:<br>
+  void handleNestedNameSpecifierLoc(<wbr>NestedNameSpecifierLoc NameLoc) {<br>
+    while (NameLoc) {<br>
+      const NamespaceDecl *Decl =<br>
+          NameLoc.<wbr>getNestedNameSpecifier()-><wbr>getAsNamespace();<br>
+      if (Decl && USRSet.find(getUSRForDecl(<wbr>Decl)) != USRSet.end())<br>
+        checkAndAddLocation(NameLoc.<wbr>getLocalBeginLoc());<br>
+      NameLoc = NameLoc.getPrefix();<br>
+    }<br>
+  }<br>
+<br>
+private:<br>
+  void checkAndAddLocation(<wbr>SourceLocation Loc) {<br>
+    const SourceLocation BeginLoc = Loc;<br>
+    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(<br>
+        BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());<br>
+    StringRef TokenName =<br>
+        Lexer::getSourceText(<wbr>CharSourceRange::<wbr>getTokenRange(BeginLoc, EndLoc),<br>
+                             Context.getSourceManager(), Context.getLangOpts());<br>
+    size_t Offset = TokenName.find(PrevName);<br>
+<br>
+    // The token of the source location we find actually has the old<br>
+    // name.<br>
+    if (Offset != StringRef::npos)<br>
+      LocationsFound.push_back(<wbr>BeginLoc.getLocWithOffset(<wbr>Offset));<br>
+  }<br>
+<br>
+  const std::set<std::string> USRSet;<br>
+  const std::string PrevName;<br>
+  std::vector<clang::<wbr>SourceLocation> LocationsFound;<br>
+  const ASTContext &Context;<br>
+};<br>
+<br>
+SourceLocation StartLocationForType(TypeLoc TL) {<br>
+  // For elaborated types (e.g. `struct a::A`) we want the portion after the<br>
+  // `struct` but including the namespace qualifier, `a::`.<br>
+  if (auto ElaboratedTypeLoc = TL.getAs<clang::<wbr>ElaboratedTypeLoc>()) {<br>
+    NestedNameSpecifierLoc NestedNameSpecifier =<br>
+        ElaboratedTypeLoc.<wbr>getQualifierLoc();<br>
+    if (NestedNameSpecifier.<wbr>getNestedNameSpecifier())<br>
+      return NestedNameSpecifier.<wbr>getBeginLoc();<br>
+    TL = TL.getNextTypeLoc();<br>
+  }<br>
+  return TL.getLocStart();<br>
+}<br>
+<br>
+SourceLocation EndLocationForType(TypeLoc TL) {<br>
+  // Dig past any namespace or keyword qualifications.<br>
+  while (TL.getTypeLocClass() == TypeLoc::Elaborated ||<br>
+         TL.getTypeLocClass() == TypeLoc::Qualified)<br>
+    TL = TL.getNextTypeLoc();<br>
+<br>
+  // The location for template specializations (e.g. Foo<int>) includes the<br>
+  // templated types in its location range.  We want to restrict this to just<br>
+  // before the `<` character.<br>
+  if (TL.getTypeLocClass() == TypeLoc::<wbr>TemplateSpecialization) {<br>
+    return TL.castAs<<wbr>TemplateSpecializationTypeLoc><wbr>()<br>
+        .getLAngleLoc()<br>
+        .getLocWithOffset(-1);<br>
+  }<br>
+  return TL.getEndLoc();<br>
+}<br>
+<br>
+NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {<br>
+  // Dig past any keyword qualifications.<br>
+  while (TL.getTypeLocClass() == TypeLoc::Qualified)<br>
+    TL = TL.getNextTypeLoc();<br>
+<br>
+  // For elaborated types (e.g. `struct a::A`) we want the portion after the<br>
+  // `struct` but including the namespace qualifier, `a::`.<br>
+  if (auto ElaboratedTypeLoc = TL.getAs<clang::<wbr>ElaboratedTypeLoc>())<br>
+    return ElaboratedTypeLoc.<wbr>getQualifierLoc().<wbr>getNestedNameSpecifier();<br>
+  return nullptr;<br>
+}<br>
+<br>
+// Find all locations identified by the given USRs for rename.<br>
+//<br>
+// This class will traverse the AST and find every AST node whose USR is in the<br>
+// given USRs' set.<br>
+class RenameLocFinder : public RecursiveASTVisitor<<wbr>RenameLocFinder> {<br>
+public:<br>
+  RenameLocFinder(llvm::<wbr>ArrayRef<std::string> USRs, ASTContext &Context)<br>
+      : USRSet(USRs.begin(), USRs.end()), Context(Context) {}<br>
+<br>
+  // A structure records all information of a symbol reference being renamed.<br>
+  // We try to add as few prefix qualifiers as possible.<br>
+  struct RenameInfo {<br>
+    // The begin location of a symbol being renamed.<br>
+    SourceLocation Begin;<br>
+    // The end location of a symbol being renamed.<br>
+    SourceLocation End;<br>
+    // The declaration of a symbol being renamed (can be nullptr).<br>
+    const NamedDecl *FromDecl;<br>
+    // The declaration in which the nested name is contained (can be nullptr).<br>
+    const Decl *Context;<br>
+    // The nested name being replaced (can be nullptr).<br>
+    const NestedNameSpecifier *Specifier;<br>
+  };<br>
+<br>
+  // FIXME: Currently, prefix qualifiers will be added to the renamed symbol<br>
+  // definition (e.g. "class Foo {};" => "class b::Bar {};" when renaming<br>
+  // "a::Foo" to "b::Bar").<br>
+  // For renaming declarations/definitions, prefix qualifiers should be filtered<br>
+  // out.<br>
+  bool VisitNamedDecl(const NamedDecl *Decl) {<br>
+    // UsingDecl has been handled in other place.<br>
+    if (llvm::isa<UsingDecl>(Decl))<br>
+      return true;<br>
+<br>
+    // DestructorDecl has been handled in Typeloc.<br>
+    if (llvm::isa<CXXDestructorDecl>(<wbr>Decl))<br>
+      return true;<br>
+<br>
+    if (Decl->isImplicit())<br>
+      return true;<br>
+<br>
+    if (isInUSRSet(Decl)) {<br>
+      RenameInfo Info = {Decl->getLocation(), Decl->getLocation(), nullptr,<br>
+                         nullptr, nullptr};<br>
+      RenameInfos.push_back(Info);<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {<br>
+    const NamedDecl *Decl = Expr->getFoundDecl();<br>
+    if (isInUSRSet(Decl)) {<br>
+      RenameInfo Info = {Expr->getSourceRange().<wbr>getBegin(),<br>
+                         Expr->getSourceRange().getEnd(<wbr>), Decl,<br>
+                         getClosestAncestorDecl(*Expr), Expr->getQualifier()};<br>
+      RenameInfos.push_back(Info);<br>
+    }<br>
+<br>
+    return true;<br>
+  }<br>
+<br>
+  bool VisitUsingDecl(const UsingDecl *Using) {<br>
+    for (const auto *UsingShadow : Using->shadows()) {<br>
+      if (isInUSRSet(UsingShadow-><wbr>getTargetDecl())) {<br>
+        UsingDecls.push_back(Using);<br>
+        break;<br>
+      }<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  bool VisitNestedNameSpecifierLocati<wbr>ons(NestedNameSpecifierLoc NestedLoc) {<br>
+    if (!NestedLoc.<wbr>getNestedNameSpecifier()-><wbr>getAsType())<br>
+      return true;<br>
+    if (<wbr>IsTypeAliasWhichWillBeRenamedE<wbr>lsewhere(NestedLoc.getTypeLoc(<wbr>)))<br>
+      return true;<br>
+<br>
+    if (const auto *TargetDecl =<br>
+            getSupportedDeclFromTypeLoc(<wbr>NestedLoc.getTypeLoc())) {<br>
+      if (isInUSRSet(TargetDecl)) {<br>
+        RenameInfo Info = {NestedLoc.getBeginLoc(),<br>
+                           EndLocationForType(NestedLoc.<wbr>getTypeLoc()),<br>
+                           TargetDecl, getClosestAncestorDecl(<wbr>NestedLoc),<br>
+                           NestedLoc.<wbr>getNestedNameSpecifier()-><wbr>getPrefix()};<br>
+        RenameInfos.push_back(Info);<br>
+      }<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  bool VisitTypeLoc(TypeLoc Loc) {<br>
+    if (<wbr>IsTypeAliasWhichWillBeRenamedE<wbr>lsewhere(Loc))<br>
+      return true;<br>
+<br>
+    auto Parents = Context.getParents(Loc);<br>
+    TypeLoc ParentTypeLoc;<br>
+    if (!Parents.empty()) {<br>
+      // Handle cases of nested name specificier locations.<br>
+      //<br>
+      // The VisitNestedNameSpecifierLoc interface is not impelmented in<br>
+      // RecursiveASTVisitor, we have to handle it explicitly.<br>
+      if (const auto *NSL = Parents[0].get<<wbr>NestedNameSpecifierLoc>()) {<br>
+        VisitNestedNameSpecifierLocati<wbr>ons(*NSL);<br>
+        return true;<br>
+      }<br>
+<br>
+      if (const auto *TL = Parents[0].get<TypeLoc>())<br>
+        ParentTypeLoc = *TL;<br>
+    }<br>
+<br>
+    // Handle the outermost TypeLoc which is directly linked to the interesting<br>
+    // declaration and don't handle nested name specifier locations.<br>
+    if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(<wbr>Loc)) {<br>
+      if (isInUSRSet(TargetDecl)) {<br>
+        // Only handle the outermost typeLoc.<br>
+        //<br>
+        // For a type like "a::Foo", there will be two typeLocs for it.<br>
+        // One ElaboratedType, the other is RecordType:<br>
+        //<br>
+        //   ElaboratedType 0x33b9390 'a::Foo' sugar<br>
+        //   `-RecordType 0x338fef0 'class a::Foo'<br>
+        //     `-CXXRecord 0x338fe58 'Foo'<br>
+        //<br>
+        // Skip if this is an inner typeLoc.<br>
+        if (!ParentTypeLoc.isNull() &&<br>
+            isInUSRSet(<wbr>getSupportedDeclFromTypeLoc(<wbr>ParentTypeLoc)))<br>
+          return true;<br>
+        RenameInfo Info = {StartLocationForType(Loc), EndLocationForType(Loc),<br>
+                           TargetDecl, getClosestAncestorDecl(Loc),<br>
+                           GetNestedNameForType(Loc)};<br>
+        RenameInfos.push_back(Info);<br>
+        return true;<br>
+      }<br>
+    }<br>
+<br>
+    // Handle specific template class specialiation cases.<br>
+    if (const auto *TemplateSpecType =<br>
+            dyn_cast<<wbr>TemplateSpecializationType>(<wbr>Loc.getType())) {<br>
+      TypeLoc TargetLoc = Loc;<br>
+      if (!ParentTypeLoc.isNull()) {<br>
+        if (llvm::isa<ElaboratedType>(<wbr>ParentTypeLoc.getType()))<br>
+          TargetLoc = ParentTypeLoc;<br>
+      }<br>
+<br>
+      if (isInUSRSet(TemplateSpecType-><wbr>getTemplateName().<wbr>getAsTemplateDecl())) {<br>
+        TypeLoc TargetLoc = Loc;<br>
+        // FIXME: Find a better way to handle this case.<br>
+        // For the qualified template class specification type like<br>
+        // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc<br>
+        // (ElaboratedType) of the TemplateSpecializationType in order to<br>
+        // catch the prefix qualifiers "ns::".<br>
+        if (!ParentTypeLoc.isNull() &&<br>
+            llvm::isa<ElaboratedType>(<wbr>ParentTypeLoc.getType()))<br>
+          TargetLoc = ParentTypeLoc;<br>
+        RenameInfo Info = {<br>
+            StartLocationForType(<wbr>TargetLoc), EndLocationForType(TargetLoc),<br>
+            TemplateSpecType-><wbr>getTemplateName().<wbr>getAsTemplateDecl(),<br>
+            getClosestAncestorDecl(<br>
+                ast_type_traits::DynTypedNode:<wbr>:create(TargetLoc)),<br>
+            GetNestedNameForType(<wbr>TargetLoc)};<br>
+        RenameInfos.push_back(Info);<br>
+      }<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  // Returns a list of RenameInfo.<br>
+  const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }<br>
+<br>
+  // Returns a list of using declarations which are needed to update.<br>
+  const std::vector<const UsingDecl *> &getUsingDecls() const {<br>
+    return UsingDecls;<br>
+  }<br>
+<br>
+private:<br>
+  // FIXME: This method may not be suitable for renaming other types like alias<br>
+  // types. Need to figure out a way to handle it.<br>
+  bool IsTypeAliasWhichWillBeRenamedE<wbr>lsewhere(TypeLoc TL) const {<br>
+    while (!TL.isNull()) {<br>
+      // SubstTemplateTypeParm is the TypeLocation class for a substituted type<br>
+      // inside a template expansion so we ignore these.  For example:<br>
+      //<br>
+      // template<typename T> struct S {<br>
+      //   T t;  // <-- this T becomes a TypeLoc(int) with class<br>
+      //         //     SubstTemplateTypeParm when S<int> is instantiated<br>
+      // }<br>
+      if (TL.getTypeLocClass() == TypeLoc::<wbr>SubstTemplateTypeParm)<br>
+        return true;<br>
+<br>
+      // Typedef is the TypeLocation class for a type which is a typedef to the<br>
+      // type we want to replace.  We ignore the use of the typedef as we will<br>
+      // replace the definition of it.  For example:<br>
+      //<br>
+      // typedef int T;<br>
+      // T a;  // <---  This T is a TypeLoc(int) with class Typedef.<br>
+      if (TL.getTypeLocClass() == TypeLoc::Typedef)<br>
+        return true;<br>
+      TL = TL.getNextTypeLoc();<br>
+    }<br>
+    return false;<br>
+  }<br>
+<br>
+  // Get the supported declaration from a given typeLoc. If the declaration type<br>
+  // is not supported, returns nullptr.<br>
+  //<br>
+  // FIXME: support more types, e.g. enum, type alias.<br>
+  const NamedDecl *getSupportedDeclFromTypeLoc(<wbr>TypeLoc Loc) {<br>
+    if (const auto *RD = Loc.getType()-><wbr>getAsCXXRecordDecl())<br>
+      return RD;<br>
+    return nullptr;<br>
+  }<br>
+<br>
+  // Get the closest ancester which is a declaration of a given AST node.<br>
+  template <typename ASTNodeType><br>
+  const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {<br>
+    auto Parents = Context.getParents(Node);<br>
+    // FIXME: figure out how to handle it when there are multiple parents.<br>
+    if (Parents.size() != 1)<br>
+      return nullptr;<br>
+    if (ast_type_traits::ASTNodeKind:<wbr>:getFromNodeKind<Decl>().<wbr>isBaseOf(<br>
+            Parents[0].getNodeKind()))<br>
+      return Parents[0].template get<Decl>();<br>
+    return getClosestAncestorDecl(<wbr>Parents[0]);<br>
+  }<br>
+<br>
+  // Get the parent typeLoc of a given typeLoc. If there is no such parent,<br>
+  // return nullptr.<br>
+  const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {<br>
+    auto Parents = Context.getParents(Loc);<br>
+    // FIXME: figure out how to handle it when there are multiple parents.<br>
+    if (Parents.size() != 1)<br>
+      return nullptr;<br>
+    return Parents[0].get<TypeLoc>();<br>
+  }<br>
+<br>
+  // Check whether the USR of a given Decl is in the USRSet.<br>
+  bool isInUSRSet(const Decl *Decl) const {<br>
+    auto USR = getUSRForDecl(Decl);<br>
+    if (USR.empty())<br>
+      return false;<br>
+    return llvm::is_contained(USRSet, USR);<br>
+  }<br>
+<br>
+  const std::set<std::string> USRSet;<br>
+  ASTContext &Context;<br>
+  std::vector<RenameInfo> RenameInfos;<br>
+  // Record all interested using declarations which contains the using-shadow<br>
+  // declarations of the symbol declarations being renamed.<br>
+  std::vector<const UsingDecl *> UsingDecls;<br>
+};<br>
+<br>
+} // namespace<br>
+<br>
+std::vector<SourceLocation><br>
+getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,<br>
+                   Decl *Decl) {<br>
+  USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());<br>
+  Visitor.TraverseDecl(Decl);<br>
+  NestedNameSpecifierLocFinder Finder(Decl->getASTContext());<br>
+<br>
+  for (const auto &Location : Finder.<wbr>getNestedNameSpecifierLocation<wbr>s())<br>
+    Visitor.<wbr>handleNestedNameSpecifierLoc(<wbr>Location);<br>
+<br>
+  return Visitor.getLocationsFound();<br>
+}<br>
+<br>
+std::vector<tooling::<wbr>AtomicChange><br>
+createRenameAtomicChanges(<wbr>llvm::ArrayRef<std::string> USRs,<br>
+                          llvm::StringRef NewName, Decl *TranslationUnitDecl) {<br>
+  RenameLocFinder Finder(USRs, TranslationUnitDecl-><wbr>getASTContext());<br>
+  Finder.TraverseDecl(<wbr>TranslationUnitDecl);<br>
+<br>
+  const SourceManager &SM =<br>
+      TranslationUnitDecl-><wbr>getASTContext().<wbr>getSourceManager();<br>
+<br>
+  std::vector<tooling::<wbr>AtomicChange> AtomicChanges;<br>
+  auto Replace = [&](SourceLocation Start, SourceLocation End,<br>
+                     llvm::StringRef Text) {<br>
+    tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);<br>
+    llvm::Error Err = ReplaceChange.replace(<br>
+        SM, CharSourceRange::<wbr>getTokenRange(Start, End), Text);<br>
+    if (Err) {<br>
+      llvm::errs() << "Faile to add replacement to AtomicChange: "<br>
+                   << llvm::toString(std::move(Err)) << "\n";<br>
+      return;<br>
+    }<br>
+    AtomicChanges.push_back(std::<wbr>move(ReplaceChange));<br>
+  };<br>
+<br>
+  for (const auto &RenameInfo : Finder.getRenameInfos()) {<br>
+    std::string ReplacedName = NewName.str();<br>
+    if (RenameInfo.FromDecl && RenameInfo.Context) {<br>
+      if (!llvm::isa<clang::<wbr>TranslationUnitDecl>(<br>
+              RenameInfo.Context-><wbr>getDeclContext())) {<br>
+        ReplacedName = tooling::replaceNestedName(<br>
+            RenameInfo.Specifier, RenameInfo.Context-><wbr>getDeclContext(),<br>
+            RenameInfo.FromDecl,<br>
+            NewName.startswith("::") ? NewName.str() : ("::" + NewName).str());<br>
+      }<br>
+    }<br>
+    // If the NewName contains leading "::", add it back.<br>
+    if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)<br>
+      ReplacedName = NewName.str();<br>
+    Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);<br>
+  }<br>
+<br>
+  // Hanlde using declarations explicitly as "using a::Foo" don't trigger<br>
+  // typeLoc for "a::Foo".<br>
+  for (const auto *Using : Finder.getUsingDecls())<br>
+    Replace(Using->getLocStart(), Using->getLocEnd(), "using " + NewName.str());<br>
+<br>
+  return AtomicChanges;<br>
+}<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
<br>
Modified: cfe/trunk/test/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CMakeLists.txt?rev=306840&r1=306839&r2=306840&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CMakeLists.txt?rev=306840&r1=<wbr>306839&r2=306840&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CMakeLists.txt (original)<br>
+++ cfe/trunk/test/CMakeLists.txt Fri Jun 30 09:36:09 2017<br>
@@ -47,6 +47,7 @@ list(APPEND CLANG_TEST_DEPS<br>
   clang-tblgen<br>
   clang-offload-bundler<br>
   clang-import-test<br>
+  clang-rename<br>
   )<br>
<br>
 if(CLANG_ENABLE_STATIC_<wbr>ANALYZER)<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ClassAsTemplateArgument.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ClassAsTemplateArgument.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/<wbr>ClassAsTemplateArgument.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ClassAsTemplateArgument.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ClassAsTemplateArgument.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,21 @@<br>
+class Foo /* Test 1 */ {};    // CHECK: class Bar /* Test 1 */ {};<br>
+<br>
+template <typename T><br>
+void func() {}<br>
+<br>
+template <typename T><br>
+class Baz {};<br>
+<br>
+int main() {<br>
+  func<Foo>();                // CHECK: func<Bar>();<br>
+  Baz<Foo> /* Test 2 */ obj;  // CHECK: Baz<Bar> /* Test 2 */ obj;<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=215 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ClassFindByName.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ClassFindByName.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/ClassFindByName.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ClassFindByName.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ClassFindByName.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,10 @@<br>
+class Foo {         // CHECK: class Bar {<br>
+};<br>
+<br>
+int main() {<br>
+  Foo *Pointer = 0; // CHECK: Bar *Pointer = 0;<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ClassReplacements.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ClassReplacements.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/ClassReplacements.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ClassReplacements.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ClassReplacements.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,11 @@<br>
+// RUN: rm -rf %t<br>
+// RUN: mkdir -p %t/fixes<br>
+// RUN: cat %s > %t.cpp<br>
+// RUN: clang-rename -offset=254 -new-name=Bar -export-fixes=%t/fixes/clang-<wbr>rename.yaml %t.cpp --<br>
+// RUN: clang-apply-replacements %t<br>
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s<br>
+<br>
+class Foo {}; // CHECK: class Bar {};<br>
+<br>
+// Use grep -FUbo 'Foo' <file> to get the correct offset of Cla when changing<br>
+// this file.<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ClassSimpleRenaming.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ClassSimpleRenaming.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/ClassSimpleRenaming.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ClassSimpleRenaming.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ClassSimpleRenaming.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,14 @@<br>
+class Foo /* Test 1 */ {              // CHECK: class Bar /* Test 1 */ {<br>
+public:<br>
+  void foo(int x);<br>
+};<br>
+<br>
+void Foo::foo(int x) /* Test 2 */ {}  // CHECK: void Bar::foo(int x) /* Test 2 */ {}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=109 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ClassTestMulti.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ClassTestMulti.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/ClassTestMulti.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ClassTestMulti.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ClassTestMulti.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,11 @@<br>
+class Foo1 /* Offset 1 */ { // CHECK: class Bar1 /* Offset 1 */ {<br>
+};<br>
+<br>
+class Foo2 /* Offset 2 */ { // CHECK: class Bar2 /* Offset 2 */ {<br>
+};<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=6 -new-name=Bar1 -offset=76 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ClassTestMultiByName.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ClassTestMultiByName.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/ClassTestMultiByName.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ClassTestMultiByName.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ClassTestMultiByName.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,8 @@<br>
+class Foo1 { // CHECK: class Bar1<br>
+};<br>
+<br>
+class Foo2 { // CHECK: class Bar2<br>
+};<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -qualified-name=Foo1 -new-name=Bar1 -qualified-name=Foo2 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ComplexFunctionOverride.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ComplexFunctionOverride.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/<wbr>ComplexFunctionOverride.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ComplexFunctionOverride.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ComplexFunctionOverride.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,47 @@<br>
+struct A {<br>
+  virtual void foo() {} /* Test 1 */    // CHECK: virtual void bar() {}<br>
+};<br>
+<br>
+struct B : A {<br>
+  void foo() override {} /* Test 2 */   // CHECK: void bar() override {}<br>
+};<br>
+<br>
+struct C : B {<br>
+  void foo() override {} /* Test 3 */   // CHECK: void bar() override {}<br>
+};<br>
+<br>
+struct D : B {<br>
+  void foo() override {} /* Test 4 */   // CHECK: void bar() override {}<br>
+};<br>
+<br>
+struct E : D {<br>
+  void foo() override {} /* Test 5 */   // CHECK: void bar() override {}<br>
+};<br>
+<br>
+int main() {<br>
+  A a;<br>
+  a.foo();                              // CHECK: a.bar();<br>
+  B b;<br>
+  b.foo();                              // CHECK: b.bar();<br>
+  C c;<br>
+  c.foo();                              // CHECK: c.bar();<br>
+  D d;<br>
+  d.foo();                              // CHECK: d.bar();<br>
+  E e;<br>
+  e.foo();                              // CHECK: e.bar();<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=26 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=109 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=201 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 4.<br>
+// RUN: clang-rename -offset=293 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 5.<br>
+// RUN: clang-rename -offset=385 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>ComplicatedClassType.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/ComplicatedClassType.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/ComplicatedClassType.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>ComplicatedClassType.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>ComplicatedClassType.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,63 @@<br>
+// Forward declaration.<br>
+class Foo; /* Test 1 */               // CHECK: class Bar; /* Test 1 */<br>
+<br>
+class Baz {<br>
+  virtual int getValue() const = 0;<br>
+};<br>
+<br>
+class Foo : public Baz  { /* Test 2 */// CHECK: class Bar : public Baz {<br>
+public:<br>
+  Foo(int value = 0) : x(value) {}    // CHECK: Bar(int value = 0) : x(value) {}<br>
+<br>
+  Foo &operator++(int) {              // CHECK: Bar &operator++(int) {<br>
+    x++;<br>
+    return *this;<br>
+  }<br>
+<br>
+  bool operator<(Foo const &rhs) {    // CHECK: bool operator<(Bar const &rhs) {<br>
+    return this->x < rhs.x;<br>
+  }<br>
+<br>
+  int getValue() const {<br>
+    return 0;<br>
+  }<br>
+<br>
+private:<br>
+  int x;<br>
+};<br>
+<br>
+int main() {<br>
+  Foo *Pointer = 0;                   // CHECK: Bar *Pointer = 0;<br>
+  Foo Variable = Foo(10);             // CHECK: Bar Variable = Bar(10);<br>
+  for (Foo it; it < Variable; it++) { // CHECK: for (Bar it; it < Variable; it++) {<br>
+  }<br>
+  const Foo *C = new Foo();           // CHECK: const Bar *C = new Bar();<br>
+  const_cast<Foo *>(C)->getValue();   // CHECK: const_cast<Bar *>(C)->getValue();<br>
+  Foo foo;                            // CHECK: Bar foo;<br>
+  const Baz &BazReference = foo;<br>
+  const Baz *BazPointer = &foo;<br>
+  dynamic_cast<const Foo &>(BazReference).getValue();     /* Test 3 */ // CHECK: dynamic_cast<const Bar &>(BazReference).getValue();<br>
+  dynamic_cast<const Foo *>(BazPointer)->getValue();      /* Test 4 */ // CHECK: dynamic_cast<const Bar *>(BazPointer)->getValue();<br>
+  reinterpret_cast<const Foo *>(BazPointer)->getValue();  /* Test 5 */ // CHECK: reinterpret_cast<const Bar *>(BazPointer)->getValue();<br>
+  static_cast<const Foo &>(BazReference).getValue();      /* Test 6 */ // CHECK: static_cast<const Bar &>(BazReference).getValue();<br>
+  static_cast<const Foo *>(BazPointer)->getValue();       /* Test 7 */ // CHECK: static_cast<const Bar *>(BazPointer)->getValue();<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=30 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=155 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=1133 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s<br>
+// Test 4.<br>
+// RUN: clang-rename -offset=1266 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s<br>
+// Test 5.<br>
+// RUN: clang-rename -offset=1402 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s<br>
+// Test 6.<br>
+// RUN: clang-rename -offset=1533 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s<br>
+// Test 7.<br>
+// RUN: clang-rename -offset=1665 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>Ctor.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/Ctor.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/Ctor.cpp?rev=306840&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>Ctor.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>Ctor.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,14 @@<br>
+class Foo {                   // CHECK: class Bar {<br>
+public:<br>
+  Foo();    /* Test 1 */      // CHECK: Bar();<br>
+};<br>
+<br>
+Foo::Foo()  /* Test 2 */ {}   // CHECK: Bar::Bar()  /* Test 2 */ {}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=62 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=116 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>CtorInitializer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/CtorInitializer.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/CtorInitializer.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>CtorInitializer.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>CtorInitializer.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,17 @@<br>
+class Baz {};<br>
+<br>
+class Qux {<br>
+  Baz Foo;         /* Test 1 */       // CHECK: Baz Bar;<br>
+public:<br>
+  Qux();<br>
+};<br>
+<br>
+Qux::Qux() : Foo() /* Test 2 */ {}    // CHECK: Qux::Qux() : Bar() /* Test 2 */ {}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=33 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=118 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>DeclRefExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/DeclRefExpr.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/DeclRefExpr.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>DeclRefExpr.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>DeclRefExpr.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,24 @@<br>
+class C {<br>
+public:<br>
+  static int Foo; /* Test 1 */  // CHECK: static int Bar;<br>
+};<br>
+<br>
+int foo(int x) { return 0; }<br>
+#define MACRO(a) foo(a)<br>
+<br>
+int main() {<br>
+  C::Foo = 1;     /* Test 2 */  // CHECK: C::Bar = 1;<br>
+  MACRO(C::Foo);                // CHECK: MACRO(C::Bar);<br>
+  int y = C::Foo; /* Test 3 */  // CHECK: int y = C::Bar;<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=31 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=152 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=271 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>Field.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/Field.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/Field.cpp?rev=306840&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>Field.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>Field.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,15 @@<br>
+class Baz {<br>
+  int Foo; /* Test 1 */ // CHECK: int Bar;<br>
+public:<br>
+  Baz();<br>
+};<br>
+<br>
+Baz::Baz() : Foo(0) /* Test 2 */ {}  // CHECK: Baz::Baz() : Bar(0)<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=18 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=89 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>FunctionMacro.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/FunctionMacro.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/FunctionMacro.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>FunctionMacro.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>FunctionMacro.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,20 @@<br>
+#define moo foo           // CHECK: #define moo macro_function<br>
+<br>
+int foo() /* Test 1 */ {  // CHECK: int macro_function() /* Test 1 */ {<br>
+  return 42;<br>
+}<br>
+<br>
+void boo(int value) {}<br>
+<br>
+void qoo() {<br>
+  foo();                  // CHECK: macro_function();<br>
+  boo(foo());             // CHECK: boo(macro_function());<br>
+  moo();<br>
+  boo(moo());<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=68 -new-name=macro_function %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>FunctionOverride.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/FunctionOverride.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/FunctionOverride.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>FunctionOverride.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>FunctionOverride.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,13 @@<br>
+class A { virtual void foo();     /* Test 1 */ }; // CHECK: class A { virtual void bar();<br>
+class B : public A { void foo();  /* Test 2 */ }; // CHECK: class B : public A { void bar();<br>
+class C : public B { void foo();  /* Test 3 */ }; // CHECK: class C : public B { void bar();<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=23 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=116 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=209 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>FunctionWithClassFindByName.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/FunctionWithClassFindByName.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/<wbr>FunctionWithClassFindByName.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>FunctionWithClassFindByName.<wbr>cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>FunctionWithClassFindByName.<wbr>cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,12 @@<br>
+void foo() {<br>
+}<br>
+<br>
+class Foo {         // CHECK: class Bar<br>
+};<br>
+<br>
+int main() {<br>
+  Foo *Pointer = 0; // CHECK: Bar *Pointer = 0;<br>
+  return 0;<br>
+}<br>
+<br>
+// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>IncludeHeaderWithSymbol.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/IncludeHeaderWithSymbol.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/<wbr>IncludeHeaderWithSymbol.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>IncludeHeaderWithSymbol.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>IncludeHeaderWithSymbol.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,10 @@<br>
+#include "Inputs/HeaderWithSymbol.h"<br>
+<br>
+int main() {<br>
+  return 0; // CHECK: {{^  return 0;}}<br>
+}<br>
+<br>
+// Test 1.<br>
+// The file IncludeHeaderWithSymbol.cpp doesn't contain the symbol Foo<br>
+// and is expected to be written to stdout without modifications<br>
+// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | FileCheck %s<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>Inputs/HeaderWithSymbol.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/Inputs/HeaderWithSymbol.h?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/Inputs/<wbr>HeaderWithSymbol.h?rev=306840&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>Inputs/HeaderWithSymbol.h (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>Inputs/HeaderWithSymbol.h Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1 @@<br>
+struct Foo {};<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>Inputs/OffsetToNewName.yaml<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/Inputs/OffsetToNewName.yaml?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/Inputs/OffsetToNewName.<wbr>yaml?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>Inputs/OffsetToNewName.yaml (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>Inputs/OffsetToNewName.yaml Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,6 @@<br>
+---<br>
+- Offset:         6<br>
+  NewName:        Bar1<br>
+- Offset:         44<br>
+  NewName:        Bar2<br>
+...<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>Inputs/QualifiedNameToNewName.<wbr>yaml<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/Inputs/QualifiedNameToNewName.yaml?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/Inputs/<wbr>QualifiedNameToNewName.yaml?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>Inputs/QualifiedNameToNewName.<wbr>yaml (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>Inputs/QualifiedNameToNewName.<wbr>yaml Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,6 @@<br>
+---<br>
+- QualifiedName:  Foo1<br>
+  NewName:        Bar1<br>
+- QualifiedName:  Foo2<br>
+  NewName:        Bar2<br>
+...<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>InvalidNewName.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/InvalidNewName.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/InvalidNewName.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>InvalidNewName.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>InvalidNewName.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,2 @@<br>
+// RUN: not clang-rename -new-name=class -offset=133 %s 2>&1 | FileCheck %s<br>
+// CHECK: ERROR: new name is not a valid identifier in C++17.<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>InvalidOffset.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/InvalidOffset.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/InvalidOffset.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>InvalidOffset.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>InvalidOffset.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,9 @@<br>
+#include "Inputs/HeaderWithSymbol.h"<br>
+#define FOO int bar;<br>
+FOO<br>
+<br>
+int foo;<br>
+<br>
+// RUN: not clang-rename -new-name=qux -offset=259 %s -- 2>&1 | FileCheck %s<br>
+// CHECK-NOT: CHECK<br>
+// CHECK: error: SourceLocation in file {{.*}}InvalidOffset.cpp at offset 259 is invalid<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>InvalidQualifiedName.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/InvalidQualifiedName.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/InvalidQualifiedName.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>InvalidQualifiedName.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>InvalidQualifiedName.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,4 @@<br>
+struct S {<br>
+};<br>
+<br>
+// RUN: clang-rename -force -qualified-name S2 -new-name=T %s --<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>MemberExprMacro.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/MemberExprMacro.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/MemberExprMacro.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>MemberExprMacro.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>MemberExprMacro.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,22 @@<br>
+class Baz {<br>
+public:<br>
+  int Foo;  /* Test 1 */    // CHECK: int Bar;<br>
+};<br>
+<br>
+int qux(int x) { return 0; }<br>
+#define MACRO(a) qux(a)<br>
+<br>
+int main() {<br>
+  Baz baz;<br>
+  baz.Foo = 1; /* Test 2 */ // CHECK: baz.Bar = 1;<br>
+  MACRO(baz.Foo);           // CHECK: MACRO(baz.Bar);<br>
+  int y = baz.Foo;          // CHECK: int y = baz.Bar;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=26 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=155 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>Namespace.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/Namespace.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/Namespace.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>Namespace.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>Namespace.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,13 @@<br>
+namespace gcc /* Test 1 */ {  // CHECK: namespace clang /* Test 1 */ {<br>
+  int x;<br>
+}<br>
+<br>
+void boo() {<br>
+  gcc::x = 42;                // CHECK: clang::x = 42;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=10 -new-name=clang %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>NoNewName.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/NoNewName.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/NoNewName.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>NoNewName.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>NoNewName.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,4 @@<br>
+// Check for an error while -new-name argument has not been passed to<br>
+// clang-rename.<br>
+// RUN: not clang-rename -offset=133 %s 2>&1 | FileCheck %s<br>
+// CHECK: clang-rename: -new-name must be specified.<br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>TemplateClassInstantiation.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/TemplateClassInstantiation.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/<wbr>TemplateClassInstantiation.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>TemplateClassInstantiation.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>TemplateClassInstantiation.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,42 @@<br>
+template <typename T><br>
+class Foo { /* Test 1 */   // CHECK: class Bar { /* Test 1 */<br>
+public:<br>
+  T foo(T arg, T& ref, T* ptr) {<br>
+    T value;<br>
+    int number = 42;<br>
+    value = (T)number;<br>
+    value = static_cast<T>(number);<br>
+    return value;<br>
+  }<br>
+  static void foo(T value) {}<br>
+  T member;<br>
+};<br>
+<br>
+template <typename T><br>
+void func() {<br>
+  Foo<T> obj; /* Test 2 */  // CHECK: Bar<T> obj;<br>
+  obj.member = T();<br>
+  Foo<T>::foo();            // CHECK: Bar<T>::foo();<br>
+}<br>
+<br>
+int main() {<br>
+  Foo<int> i; /* Test 3 */  // CHECK: Bar<int> i;<br>
+  i.member = 0;<br>
+  Foo<int>::foo(0);         // CHECK: Bar<int>::foo(0);<br>
+<br>
+  Foo<bool> b;              // CHECK: Bar<bool> b;<br>
+  b.member = false;<br>
+  Foo<bool>::foo(false);    // CHECK: Bar<bool>::foo(false);<br>
+<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=29 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=324 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=463 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>TemplateTypename.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/TemplateTypename.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/TemplateTypename.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>TemplateTypename.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>TemplateTypename.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,24 @@<br>
+template <typename T /* Test 1 */>              // CHECK: template <typename U /* Test 1 */><br>
+class Foo {<br>
+T foo(T arg, T& ref, T* /* Test 2 */ ptr) {     // CHECK: U foo(U arg, U& ref, U* /* Test 2 */ ptr) {<br>
+  T value;                                      // CHECK: U value;<br>
+  int number = 42;<br>
+  value = (T)number;                            // CHECK: value = (U)number;<br>
+  value = static_cast<T /* Test 3 */>(number);  // CHECK: value = static_cast<U /* Test 3 */>(number);<br>
+  return value;<br>
+}<br>
+<br>
+static void foo(T value) {}                     // CHECK: static void foo(U value) {}<br>
+<br>
+T member;                                       // CHECK: U member;<br>
+};<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=19 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=126 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=392 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'T.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>TemplatedClassFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/TemplatedClassFunction.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/TemplatedClassFunction.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>TemplatedClassFunction.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>TemplatedClassFunction.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,22 @@<br>
+template <typename T><br>
+class A {<br>
+public:<br>
+  void foo() /* Test 1 */ {}  // CHECK: void bar() /* Test 1 */ {}<br>
+};<br>
+<br>
+int main(int argc, char **argv) {<br>
+  A<int> a;<br>
+  a.foo();   /* Test 2 */     // CHECK: a.bar()   /* Test 2 */<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-refactor rename -offset=48 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-refactor rename -offset=162 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+//<br>
+// Currently unsupported test.<br>
+// XFAIL: *<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>UserDefinedConversion.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/UserDefinedConversion.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/UserDefinedConversion.<wbr>cpp?rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>UserDefinedConversion.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>UserDefinedConversion.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,26 @@<br>
+class Foo {       /* Test 1 */          // CHECK: class Bar {<br>
+public:<br>
+  Foo() {}                              // CHECK: Bar() {}<br>
+};<br>
+<br>
+class Baz {<br>
+public:<br>
+  operator Foo()  /* Test 2 */ const {  // CHECK: operator Bar()  /* Test 2 */ const {<br>
+    Foo foo;                            // CHECK: Bar foo;<br>
+    return foo;<br>
+  }<br>
+};<br>
+<br>
+int main() {<br>
+  Baz boo;<br>
+  Foo foo = static_cast<Foo>(boo);      // CHECK: Bar foo = static_cast<Bar>(boo);<br>
+  return 0;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=164 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>Variable.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/Variable.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/Variable.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>Variable.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>Variable.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,33 @@<br>
+#define NAMESPACE namespace A<br>
+NAMESPACE {<br>
+int Foo;          /* Test 1 */        // CHECK: int Bar;<br>
+}<br>
+int Foo;                              // CHECK: int Foo;<br>
+int Qux = Foo;                        // CHECK: int Qux = Foo;<br>
+int Baz = A::Foo; /* Test 2 */        // CHECK: Baz = A::Bar;<br>
+void fun() {<br>
+  struct {<br>
+    int Foo;                          // CHECK: int Foo;<br>
+  } b = {100};<br>
+  int Foo = 100;                      // CHECK: int Foo = 100;<br>
+  Baz = Foo;                          // CHECK: Baz = Foo;<br>
+  {<br>
+    extern int Foo;                   // CHECK: extern int Foo;<br>
+    Baz = Foo;                        // CHECK: Baz = Foo;<br>
+    Foo = A::Foo /* Test 3 */ + Baz;  // CHECK: Foo = A::Bar /* Test 3 */ + Baz;<br>
+    A::Foo /* Test 4 */ = b.Foo;      // CHECK: A::Bar /* Test 4 */ = b.Foo;<br>
+  }<br>
+  Foo = b.Foo;                        // Foo = b.Foo;<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=46 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=234 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=641 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 4.<br>
+// RUN: clang-rename -offset=716 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>VariableMacro.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/VariableMacro.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/VariableMacro.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>VariableMacro.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>VariableMacro.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,21 @@<br>
+#define Baz Foo // CHECK: #define Baz Bar<br>
+<br>
+void foo(int value) {}<br>
+<br>
+void macro() {<br>
+  int Foo;  /* Test 1 */  // CHECK: int Bar;<br>
+  Foo = 42; /* Test 2 */  // CHECK: Bar = 42;<br>
+  Baz -= 0;<br>
+  foo(Foo); /* Test 3 */  // CHECK: foo(Bar);<br>
+  foo(Baz);<br>
+}<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -offset=88 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -offset=129 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 3.<br>
+// RUN: clang-rename -offset=191 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s<br>
+<br>
+// To find offsets after modifying the file, use:<br>
+//   grep -Ubo 'Foo.*' <file><br>
<br>
Added: cfe/trunk/test/clang-rename/<wbr>YAMLInput.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/clang-rename/YAMLInput.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/clang-<wbr>rename/YAMLInput.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/clang-rename/<wbr>YAMLInput.cpp (added)<br>
+++ cfe/trunk/test/clang-rename/<wbr>YAMLInput.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,10 @@<br>
+class Foo1 { // CHECK: class Bar1<br>
+};<br>
+<br>
+class Foo2 { // CHECK: class Bar2<br>
+};<br>
+<br>
+// Test 1.<br>
+// RUN: clang-rename -input %S/Inputs/OffsetToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s<br>
+// Test 2.<br>
+// RUN: clang-rename -input %S/Inputs/<wbr>QualifiedNameToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s<br>
<br>
Modified: cfe/trunk/tools/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CMakeLists.txt?rev=306840&r1=306839&r2=306840&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/tools/<wbr>CMakeLists.txt?rev=306840&r1=<wbr>306839&r2=306840&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/tools/CMakeLists.txt (original)<br>
+++ cfe/trunk/tools/CMakeLists.txt Fri Jun 30 09:36:09 2017<br>
@@ -10,6 +10,8 @@ add_clang_subdirectory(clang-<wbr>offload-bun<br>
<br>
 add_clang_subdirectory(c-<wbr>index-test)<br>
<br>
+add_clang_subdirectory(clang-<wbr>rename)<br>
+<br>
 if(CLANG_ENABLE_ARCMT)<br>
   add_clang_subdirectory(arcmt-<wbr>test)<br>
   add_clang_subdirectory(c-<wbr>arcmt-test)<br>
<br>
Added: cfe/trunk/tools/clang-rename/<wbr>CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-rename/CMakeLists.txt?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/tools/clang-<wbr>rename/CMakeLists.txt?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/tools/clang-rename/<wbr>CMakeLists.txt (added)<br>
+++ cfe/trunk/tools/clang-rename/<wbr>CMakeLists.txt Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,19 @@<br>
+add_clang_executable(clang-<wbr>rename ClangRename.cpp)<br>
+<br>
+target_link_libraries(clang-<wbr>rename<br>
+  clangBasic<br>
+  clangFrontend<br>
+  clangRewrite<br>
+  clangTooling<br>
+  clangToolingCore<br>
+  clangToolingRefactor<br>
+  )<br>
+<br>
+install(TARGETS clang-rename RUNTIME DESTINATION bin)<br>
+<br>
+install(PROGRAMS clang-rename.py<br>
+  DESTINATION share/clang<br>
+  COMPONENT clang-rename)<br>
+install(PROGRAMS clang-rename.el<br>
+  DESTINATION share/clang<br>
+  COMPONENT clang-rename)<br>
<br>
Added: cfe/trunk/tools/clang-rename/<wbr>ClangRename.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-rename/ClangRename.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/tools/clang-<wbr>rename/ClangRename.cpp?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/tools/clang-rename/<wbr>ClangRename.cpp (added)<br>
+++ cfe/trunk/tools/clang-rename/<wbr>ClangRename.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,240 @@<br>
+//===--- tools/extra/clang-rename/<wbr>ClangRename.cpp - Clang rename tool -----===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief This file implements a clang-rename tool that automatically finds and<br>
+/// renames symbols in C++ code.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "clang/Basic/Diagnostic.h"<br>
+#include "clang/Basic/<wbr>DiagnosticOptions.h"<br>
+#include "clang/Basic/FileManager.h"<br>
+#include "clang/Basic/IdentifierTable.<wbr>h"<br>
+#include "clang/Basic/LangOptions.h"<br>
+#include "clang/Basic/SourceManager.h"<br>
+#include "clang/Basic/TokenKinds.h"<br>
+#include "clang/Frontend/<wbr>TextDiagnosticPrinter.h"<br>
+#include "clang/Rewrite/Core/Rewriter.<wbr>h"<br>
+#include "clang/Tooling/<wbr>CommonOptionsParser.h"<br>
+#include "clang/Tooling/Refactoring.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/RenamingAction.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRFindingAction.h"<br>
+#include "clang/Tooling/<wbr>ReplacementsYaml.h"<br>
+#include "clang/Tooling/Tooling.h"<br>
+#include "llvm/ADT/IntrusiveRefCntPtr.<wbr>h"<br>
+#include "llvm/Support/CommandLine.h"<br>
+#include "llvm/Support/FileSystem.h"<br>
+#include "llvm/Support/YAMLTraits.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include <cstdlib><br>
+#include <string><br>
+#include <system_error><br>
+<br>
+using namespace llvm;<br>
+using namespace clang;<br>
+<br>
+/// \brief An oldname -> newname rename.<br>
+struct RenameAllInfo {<br>
+  unsigned Offset = 0;<br>
+  std::string QualifiedName;<br>
+  std::string NewName;<br>
+};<br>
+<br>
+LLVM_YAML_IS_SEQUENCE_VECTOR(<wbr>RenameAllInfo)<br>
+<br>
+namespace llvm {<br>
+namespace yaml {<br>
+<br>
+/// \brief Specialized MappingTraits to describe how a RenameAllInfo is<br>
+/// (de)serialized.<br>
+template <> struct MappingTraits<RenameAllInfo> {<br>
+  static void mapping(IO &IO, RenameAllInfo &Info) {<br>
+    IO.mapOptional("Offset", Info.Offset);<br>
+    IO.mapOptional("QualifiedName"<wbr>, Info.QualifiedName);<br>
+    IO.mapRequired("NewName", Info.NewName);<br>
+  }<br>
+};<br>
+<br>
+} // end namespace yaml<br>
+} // end namespace llvm<br>
+<br>
+static cl::OptionCategory ClangRenameOptions("clang-<wbr>rename common options");<br>
+<br>
+static cl::list<unsigned> SymbolOffsets(<br>
+    "offset",<br>
+    cl::desc("Locates the symbol by offset as opposed to <line>:<column>."),<br>
+    cl::ZeroOrMore, cl::cat(ClangRenameOptions));<br>
+static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited <file>s."),<br>
+                             cl::cat(ClangRenameOptions));<br>
+static cl::list<std::string><br>
+    QualifiedNames("qualified-<wbr>name",<br>
+                   cl::desc("The fully qualified name of the symbol."),<br>
+                   cl::ZeroOrMore, cl::cat(ClangRenameOptions));<br>
+<br>
+static cl::list<std::string><br>
+    NewNames("new-name", cl::desc("The new name to change the symbol to."),<br>
+             cl::ZeroOrMore, cl::cat(ClangRenameOptions));<br>
+static cl::opt<bool> PrintName(<br>
+    "pn",<br>
+    cl::desc("Print the found symbol's name prior to renaming to stderr."),<br>
+    cl::cat(ClangRenameOptions));<br>
+static cl::opt<bool> PrintLocations(<br>
+    "pl", cl::desc("Print the locations affected by renaming to stderr."),<br>
+    cl::cat(ClangRenameOptions));<br>
+static cl::opt<std::string><br>
+    ExportFixes("export-fixes",<br>
+                cl::desc("YAML file to store suggested fixes in."),<br>
+                cl::value_desc("filename"), cl::cat(ClangRenameOptions));<br>
+static cl::opt<std::string><br>
+    Input("input", cl::desc("YAML file to load oldname-newname pairs from."),<br>
+          cl::Optional, cl::cat(ClangRenameOptions));<br>
+static cl::opt<bool> Force("force",<br>
+                           cl::desc("Ignore nonexistent qualified names."),<br>
+                           cl::cat(ClangRenameOptions));<br>
+<br>
+int main(int argc, const char **argv) {<br>
+  tooling::CommonOptionsParser OP(argc, argv, ClangRenameOptions);<br>
+<br>
+  if (!Input.empty()) {<br>
+    // Populate QualifiedNames and NewNames from a YAML file.<br>
+    ErrorOr<std::unique_ptr<<wbr>MemoryBuffer>> Buffer =<br>
+        llvm::MemoryBuffer::getFile(<wbr>Input);<br>
+    if (!Buffer) {<br>
+      errs() << "clang-rename: failed to read " << Input << ": "<br>
+             << Buffer.getError().message() << "\n";<br>
+      return 1;<br>
+    }<br>
+<br>
+    std::vector<RenameAllInfo> Infos;<br>
+    llvm::yaml::Input YAML(Buffer.get()->getBuffer()<wbr>);<br>
+    YAML >> Infos;<br>
+    for (const auto &Info : Infos) {<br>
+      if (!Info.QualifiedName.empty())<br>
+        QualifiedNames.push_back(Info.<wbr>QualifiedName);<br>
+      else<br>
+        SymbolOffsets.push_back(Info.<wbr>Offset);<br>
+      NewNames.push_back(Info.<wbr>NewName);<br>
+    }<br>
+  }<br>
+<br>
+  // Check the arguments for correctness.<br>
+  if (NewNames.empty()) {<br>
+    errs() << "clang-rename: -new-name must be specified.\n\n";<br>
+    exit(1);<br>
+  }<br>
+<br>
+  if (SymbolOffsets.empty() == QualifiedNames.empty()) {<br>
+    errs() << "clang-rename: -offset and -qualified-name can't be present at "<br>
+              "the same time.\n";<br>
+    exit(1);<br>
+  }<br>
+<br>
+  // Check if NewNames is a valid identifier in C++17.<br>
+  LangOptions Options;<br>
+  Options.CPlusPlus = true;<br>
+  Options.CPlusPlus1z = true;<br>
+  IdentifierTable Table(Options);<br>
+  for (const auto &NewName : NewNames) {<br>
+    auto NewNameTokKind = Table.get(NewName).getTokenID(<wbr>);<br>
+    if (!tok::isAnyIdentifier(<wbr>NewNameTokKind)) {<br>
+      errs() << "ERROR: new name is not a valid identifier in C++17.\n\n";<br>
+      exit(1);<br>
+    }<br>
+  }<br>
+<br>
+  if (SymbolOffsets.size() + QualifiedNames.size() != NewNames.size()) {<br>
+    errs() << "clang-rename: number of symbol offsets(" << SymbolOffsets.size()<br>
+           << ") + number of qualified names (" << QualifiedNames.size()<br>
+           << ") must be equal to number of new names(" << NewNames.size()<br>
+           << ").\n\n";<br>
+    cl::PrintHelpMessage();<br>
+    exit(1);<br>
+  }<br>
+<br>
+  auto Files = OP.getSourcePathList();<br>
+  tooling::RefactoringTool Tool(OP.getCompilations(), Files);<br>
+  tooling::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames, Force);<br>
+  Tool.run(tooling::<wbr>newFrontendActionFactory(&<wbr>FindingAction).get());<br>
+  const std::vector<std::vector<std::<wbr>string>> &USRList =<br>
+      FindingAction.getUSRList();<br>
+  const std::vector<std::string> &PrevNames = FindingAction.getUSRSpellings(<wbr>);<br>
+  if (PrintName) {<br>
+    for (const auto &PrevName : PrevNames) {<br>
+      outs() << "clang-rename found name: " << PrevName << '\n';<br>
+    }<br>
+  }<br>
+<br>
+  if (FindingAction.errorOccurred()<wbr>) {<br>
+    // Diagnostics are already issued at this point.<br>
+    exit(1);<br>
+  }<br>
+<br>
+  if (Force && PrevNames.size() < NewNames.size()) {<br>
+    // No matching PrevName for all NewNames. Without Force this is an error<br>
+    // above already.<br>
+    exit(0);<br>
+  }<br>
+<br>
+  // Perform the renaming.<br>
+  tooling::RenamingAction RenameAction(NewNames, PrevNames, USRList,<br>
+                                       Tool.getReplacements(), PrintLocations);<br>
+  std::unique_ptr<tooling::<wbr>FrontendActionFactory> Factory =<br>
+      tooling::<wbr>newFrontendActionFactory(&<wbr>RenameAction);<br>
+  int ExitCode;<br>
+<br>
+  if (Inplace) {<br>
+    ExitCode = Tool.runAndSave(Factory.get())<wbr>;<br>
+  } else {<br>
+    ExitCode = Tool.run(Factory.get());<br>
+<br>
+    if (!ExportFixes.empty()) {<br>
+      std::error_code EC;<br>
+      llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None);<br>
+      if (EC) {<br>
+        llvm::errs() << "Error opening output file: " << EC.message() << '\n';<br>
+        exit(1);<br>
+      }<br>
+<br>
+      // Export replacements.<br>
+      tooling::<wbr>TranslationUnitReplacements TUR;<br>
+      const auto &FileToReplacements = Tool.getReplacements();<br>
+      for (const auto &Entry : FileToReplacements)<br>
+        TUR.Replacements.insert(TUR.<wbr>Replacements.end(), Entry.second.begin(),<br>
+                                Entry.second.end());<br>
+<br>
+      yaml::Output YAML(OS);<br>
+      YAML << TUR;<br>
+      OS.close();<br>
+      exit(0);<br>
+    }<br>
+<br>
+    // Write every file to stdout. Right now we just barf the files without any<br>
+    // indication of which files start where, other than that we print the files<br>
+    // in the same order we see them.<br>
+    LangOptions DefaultLangOptions;<br>
+    IntrusiveRefCntPtr<<wbr>DiagnosticOptions> DiagOpts = new DiagnosticOptions();<br>
+    TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);<br>
+    DiagnosticsEngine Diagnostics(<br>
+        IntrusiveRefCntPtr<<wbr>DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,<br>
+        &DiagnosticPrinter, false);<br>
+    auto &FileMgr = Tool.getFiles();<br>
+    SourceManager Sources(Diagnostics, FileMgr);<br>
+    Rewriter Rewrite(Sources, DefaultLangOptions);<br>
+<br>
+    Tool.applyAllReplacements(<wbr>Rewrite);<br>
+    for (const auto &File : Files) {<br>
+      const auto *Entry = FileMgr.getFile(File);<br>
+      const auto ID = Sources.getOrCreateFileID(<wbr>Entry, SrcMgr::C_User);<br>
+      Rewrite.getEditBuffer(ID).<wbr>write(outs());<br>
+    }<br>
+  }<br>
+<br>
+  exit(ExitCode);<br>
+}<br>
<br>
Added: cfe/trunk/tools/clang-rename/<wbr>clang-rename.el<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-rename/clang-rename.el?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/tools/clang-<wbr>rename/clang-rename.el?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/tools/clang-rename/<wbr>clang-rename.el (added)<br>
+++ cfe/trunk/tools/clang-rename/<wbr>clang-rename.el Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,79 @@<br>
+;;; clang-rename.el --- Renames every occurrence of a symbol found at <offset>.  -*- lexical-binding: t; -*-<br>
+<br>
+;; Keywords: tools, c<br>
+<br>
+;;; Commentary:<br>
+<br>
+;; To install clang-rename.el make sure the directory of this file is in your<br>
+;; `load-path' and add<br>
+;;<br>
+;;   (require 'clang-rename)<br>
+;;<br>
+;; to your .emacs configuration.<br>
+<br>
+;;; Code:<br>
+<br>
+(defgroup clang-rename nil<br>
+  "Integration with clang-rename"<br>
+  :group 'c)<br>
+<br>
+(defcustom clang-rename-binary "clang-rename"<br>
+  "Path to clang-rename executable."<br>
+  :type '(file :must-match t)<br>
+  :group 'clang-rename)<br>
+<br>
+;;;###autoload<br>
+(defun clang-rename (new-name)<br>
+  "Rename all instances of the symbol at point to NEW-NAME using clang-rename."<br>
+  (interactive "sEnter a new name: ")<br>
+  (save-some-buffers :all)<br>
+  ;; clang-rename should not be combined with other operations when undoing.<br>
+  (undo-boundary)<br>
+  (let ((output-buffer (get-buffer-create "*clang-rename*")))<br>
+    (with-current-buffer output-buffer (erase-buffer))<br>
+    (let ((exit-code (call-process<br>
+                      clang-rename-binary nil output-buffer nil<br>
+                      (format "-offset=%d"<br>
+                              ;; clang-rename wants file (byte) offsets, not<br>
+                              ;; buffer (character) positions.<br>
+                              (clang-rename--bufferpos-to-<wbr>filepos<br>
+                               ;; Emacs treats one character after a symbol as<br>
+                               ;; part of the symbol, but clang-rename doesn’t.<br>
+                               ;; Use the beginning of the current symbol, if<br>
+                               ;; available, to resolve the inconsistency.<br>
+                               (or (car (bounds-of-thing-at-point 'symbol))<br>
+                                   (point))<br>
+                               'exact))<br>
+                      (format "-new-name=%s" new-name)<br>
+                      "-i" (buffer-file-name))))<br>
+      (if (and (integerp exit-code) (zerop exit-code))<br>
+          ;; Success; revert current buffer so it gets the modifications.<br>
+          (progn<br>
+            (kill-buffer output-buffer)<br>
+            (revert-buffer :ignore-auto :noconfirm :preserve-modes))<br>
+        ;; Failure; append exit code to output buffer and display it.<br>
+        (let ((message (clang-rename--format-message<br>
+                        "clang-rename failed with %s %s"<br>
+                        (if (integerp exit-code) "exit status" "signal")<br>
+                        exit-code)))<br>
+          (with-current-buffer output-buffer<br>
+            (insert ?\n message ?\n))<br>
+          (message "%s" message)<br>
+          (display-buffer output-buffer))))))<br>
+<br>
+(defalias 'clang-rename--bufferpos-to-<wbr>filepos<br>
+  (if (fboundp 'bufferpos-to-filepos)<br>
+      'bufferpos-to-filepos<br>
+    ;; Emacs 24 doesn’t have â€˜bufferpos-to-filepos’, simulate it using<br>
+    ;; â€˜position-bytes’.<br>
+    (lambda (position &optional _quality _coding-system)<br>
+      (1- (position-bytes position)))))<br>
+<br>
+;; â€˜format-message’ is new in Emacs 25.1.  Provide a fallback for older<br>
+;; versions.<br>
+(defalias 'clang-rename--format-message<br>
+  (if (fboundp 'format-message) 'format-message 'format))<br>
+<br>
+(provide 'clang-rename)<br>
+<br>
+;;; clang-rename.el ends here<br>
<br>
Added: cfe/trunk/tools/clang-rename/<wbr>clang-rename.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-rename/clang-rename.py?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/tools/clang-<wbr>rename/clang-rename.py?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/tools/clang-rename/<wbr>clang-rename.py (added)<br>
+++ cfe/trunk/tools/clang-rename/<wbr>clang-rename.py Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,61 @@<br>
+'''<br>
+Minimal clang-rename integration with Vim.<br>
+<br>
+Before installing make sure one of the following is satisfied:<br>
+<br>
+* clang-rename is in your PATH<br>
+* `g:clang_rename_path` in ~/.vimrc points to valid clang-rename executable<br>
+* `binary` in clang-rename.py points to valid to clang-rename executable<br>
+<br>
+To install, simply put this into your ~/.vimrc<br>
+<br>
+    noremap <leader>cr :pyf <path-to>/clang-rename.py<cr><br>
+<br>
+IMPORTANT NOTE: Before running the tool, make sure you saved the file.<br>
+<br>
+All you have to do now is to place a cursor on a variable/function/class which<br>
+you would like to rename and press '<leader>cr'. You will be prompted for a new<br>
+name if the cursor points to a valid symbol.<br>
+'''<br>
+<br>
+import vim<br>
+import subprocess<br>
+import sys<br>
+<br>
+def main():<br>
+    binary = 'clang-rename'<br>
+    if vim.eval('exists("g:clang_<wbr>rename_path")') == "1":<br>
+        binary = vim.eval('g:clang_rename_path'<wbr>)<br>
+<br>
+    # Get arguments for clang-rename binary.<br>
+    offset = int(vim.eval('line2byte(line("<wbr>."))+col(".")')) - 2<br>
+    if offset < 0:<br>
+        print >> sys.stderr, '''Couldn\'t determine cursor position.<br>
+                                Is your file empty?'''<br>
+        return<br>
+    filename = <a href="http://vim.current.buffer.name" rel="noreferrer" target="_blank">vim.current.buffer.name</a><br>
+<br>
+    new_name_request_message = 'type new name:'<br>
+    new_name = vim.eval("input('{}\n')".<wbr>format(new_name_request_<wbr>message))<br>
+<br>
+    # Call clang-rename.<br>
+    command = [binary,<br>
+               filename,<br>
+               '-i',<br>
+               '-offset', str(offset),<br>
+               '-new-name', str(new_name)]<br>
+    # FIXME: make it possible to run the tool on unsaved file.<br>
+    p = subprocess.Popen(command,<br>
+                         stdout=subprocess.PIPE,<br>
+                         stderr=subprocess.PIPE)<br>
+    stdout, stderr = p.communicate()<br>
+<br>
+    if stderr:<br>
+        print stderr<br>
+<br>
+    # Reload all buffers in Vim.<br>
+    vim.command("checktime")<br>
+<br>
+<br>
+if __name__ == '__main__':<br>
+    main()<br>
<br>
Modified: cfe/trunk/unittests/<wbr>CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/CMakeLists.txt?rev=306840&r1=306839&r2=306840&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/unittests/<wbr>CMakeLists.txt?rev=306840&r1=<wbr>306839&r2=306840&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/<wbr>CMakeLists.txt (original)<br>
+++ cfe/trunk/unittests/<wbr>CMakeLists.txt Fri Jun 30 09:36:09 2017<br>
@@ -29,3 +29,4 @@ add_subdirectory(CodeGen)<br>
 if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD)<br>
   add_subdirectory(libclang)<br>
 endif()<br>
+add_subdirectory(Rename)<br>
<br>
Added: cfe/trunk/unittests/Rename/<wbr>CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Rename/CMakeLists.txt?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/unittests/<wbr>Rename/CMakeLists.txt?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/Rename/<wbr>CMakeLists.txt (added)<br>
+++ cfe/trunk/unittests/Rename/<wbr>CMakeLists.txt Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,22 @@<br>
+set(LLVM_LINK_COMPONENTS<br>
+  support<br>
+  )<br>
+<br>
+# We'd like clang/unittests/Tooling/<wbr>RewriterTestContext.h in the test.<br>
+include_directories(${CLANG_<wbr>SOURCE_DIR})<br>
+<br>
+add_extra_unittest(<wbr>ClangRenameTests<br>
+  RenameClassTest.cpp<br>
+  )<br>
+<br>
+target_link_libraries(<wbr>ClangRenameTests<br>
+  clangAST<br>
+  clangASTMatchers<br>
+  clangBasic<br>
+  clangFormat<br>
+  clangFrontend<br>
+  clangRewrite<br>
+  clangTooling<br>
+  clangToolingCore<br>
+  clangToolingRefactor<br>
+  )<br>
<br>
Added: cfe/trunk/unittests/Rename/<wbr>ClangRenameTest.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Rename/ClangRenameTest.h?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/unittests/<wbr>Rename/ClangRenameTest.h?rev=<wbr>306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/Rename/<wbr>ClangRenameTest.h (added)<br>
+++ cfe/trunk/unittests/Rename/<wbr>ClangRenameTest.h Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,112 @@<br>
+//===-- ClangRenameTests.cpp - clang-rename unit tests --------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "unittests/Tooling/<wbr>RewriterTestContext.h"<br>
+#include "clang/ASTMatchers/<wbr>ASTMatchFinder.h"<br>
+#include "clang/Basic/FileManager.h"<br>
+#include "clang/Basic/<wbr>FileSystemOptions.h"<br>
+#include "clang/Basic/<wbr>VirtualFileSystem.h"<br>
+#include "clang/Format/Format.h"<br>
+#include "clang/Frontend/<wbr>CompilerInstance.h"<br>
+#include "clang/Frontend/<wbr>PCHContainerOperations.h"<br>
+#include "clang/Tooling/Refactoring.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/RenamingAction.h"<br>
+#include "clang/Tooling/Refactoring/<wbr>Rename/USRFindingAction.h"<br>
+#include "clang/Tooling/Tooling.h"<br>
+#include "llvm/ADT/IntrusiveRefCntPtr.<wbr>h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Support/Format.h"<br>
+#include "llvm/Support/MemoryBuffer.h"<br>
+#include "gtest/gtest.h"<br>
+#include <memory><br>
+#include <string><br>
+#include <vector><br>
+<br>
+namespace clang {<br>
+namespace clang_rename {<br>
+namespace test {<br>
+<br>
+struct Case {<br>
+  std::string Before;<br>
+  std::string After;<br>
+  std::string OldName;<br>
+  std::string NewName;<br>
+};<br>
+<br>
+class ClangRenameTest : public testing::Test,<br>
+                        public testing::WithParamInterface<<wbr>Case> {<br>
+protected:<br>
+  void AppendToHeader(StringRef Code) { HeaderContent += Code.str(); }<br>
+<br>
+  std::string runClangRenameOnCode(llvm::<wbr>StringRef Code,<br>
+                                   llvm::StringRef OldName,<br>
+                                   llvm::StringRef NewName) {<br>
+    std::string NewCode;<br>
+    llvm::raw_string_ostream(<wbr>NewCode) << llvm::format(<br>
+        "#include \"%s\"\n%s", HeaderName.c_str(), Code.str().c_str());<br>
+    tooling::FileContentMappings FileContents = {{HeaderName, HeaderContent},<br>
+                                                 {CCName, NewCode}};<br>
+    clang::RewriterTestContext Context;<br>
+    Context.createInMemoryFile(<wbr>HeaderName, HeaderContent);<br>
+    clang::FileID InputFileID = Context.createInMemoryFile(<wbr>CCName, NewCode);<br>
+<br>
+    tooling::USRFindingAction FindingAction({}, {OldName}, false);<br>
+    std::unique_ptr<tooling::<wbr>FrontendActionFactory> USRFindingActionFactory =<br>
+        tooling::<wbr>newFrontendActionFactory(&<wbr>FindingAction);<br>
+<br>
+    if (!tooling::<wbr>runToolOnCodeWithArgs(<br>
+            USRFindingActionFactory-><wbr>create(), NewCode, {"-std=c++11"}, CCName,<br>
+            "clang-rename", std::make_shared<<wbr>PCHContainerOperations>(),<br>
+            FileContents))<br>
+      return "";<br>
+<br>
+    const std::vector<std::vector<std::<wbr>string>> &USRList =<br>
+        FindingAction.getUSRList();<br>
+    std::vector<std::string> NewNames = {NewName};<br>
+    std::map<std::string, tooling::Replacements> FileToReplacements;<br>
+    tooling::<wbr>QualifiedRenamingAction RenameAction(NewNames, USRList,<br>
+                                                  FileToReplacements);<br>
+    auto RenameActionFactory = tooling::<wbr>newFrontendActionFactory(&<wbr>RenameAction);<br>
+    if (!tooling::<wbr>runToolOnCodeWithArgs(<br>
+            RenameActionFactory->create(), NewCode, {"-std=c++11"}, CCName,<br>
+            "clang-rename", std::make_shared<<wbr>PCHContainerOperations>(),<br>
+            FileContents))<br>
+      return "";<br>
+<br>
+    formatAndApplyAllReplacements(<wbr>FileToReplacements, Context.Rewrite, "llvm");<br>
+    return Context.getRewrittenText(<wbr>InputFileID);<br>
+  }<br>
+<br>
+  void CompareSnippets(StringRef Expected, StringRef Actual) {<br>
+    std::string ExpectedCode;<br>
+    llvm::raw_string_ostream(<wbr>ExpectedCode) << llvm::format(<br>
+        "#include \"%s\"\n%s", HeaderName.c_str(), Expected.str().c_str());<br>
+    EXPECT_EQ(format(ExpectedCode)<wbr>, format(Actual));<br>
+  }<br>
+<br>
+  std::string format(llvm::StringRef Code) {<br>
+    tooling::Replacements Replaces = format::reformat(<br>
+        format::getLLVMStyle(), Code, {tooling::Range(0, Code.size())});<br>
+    auto ChangedCode = tooling::applyAllReplacements(<wbr>Code, Replaces);<br>
+    EXPECT_TRUE(static_cast<bool>(<wbr>ChangedCode));<br>
+    if (!ChangedCode) {<br>
+      llvm::errs() << llvm::toString(ChangedCode.<wbr>takeError());<br>
+      return "";<br>
+    }<br>
+    return *ChangedCode;<br>
+  }<br>
+<br>
+  std::string HeaderContent;<br>
+  std::string HeaderName = "header.h";<br>
+  std::string CCName = "input.cc";<br>
+};<br>
+<br>
+} // namespace test<br>
+} // namespace clang_rename<br>
+} // namesdpace clang<br>
<br>
Added: cfe/trunk/unittests/Rename/<wbr>RenameClassTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Rename/RenameClassTest.cpp?rev=306840&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/unittests/<wbr>Rename/RenameClassTest.cpp?<wbr>rev=306840&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/Rename/<wbr>RenameClassTest.cpp (added)<br>
+++ cfe/trunk/unittests/Rename/<wbr>RenameClassTest.cpp Fri Jun 30 09:36:09 2017<br>
@@ -0,0 +1,684 @@<br>
+//===-- RenameClassTest.cpp - unit tests for renaming classes -------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "ClangRenameTest.h"<br>
+<br>
+namespace clang {<br>
+namespace clang_rename {<br>
+namespace test {<br>
+namespace {<br>
+<br>
+class RenameClassTest : public ClangRenameTest {<br>
+public:<br>
+  RenameClassTest() {<br>
+    AppendToHeader(R"(<br>
+      namespace a {<br>
+        class Foo {<br>
+          public:<br>
+            struct Nested {<br>
+              enum NestedEnum {E1, E2};<br>
+            };<br>
+            void func() {}<br>
+          static int Constant;<br>
+        };<br>
+        class Goo {<br>
+          public:<br>
+            struct Nested {<br>
+              enum NestedEnum {E1, E2};<br>
+            };<br>
+        };<br>
+        int Foo::Constant = 1;<br>
+      } // namespace a<br>
+      namespace b {<br>
+      class Foo {};<br>
+      } // namespace b<br>
+<br>
+      #define MACRO(x) x<br>
+<br>
+      template<typename T> class ptr {};<br>
+    )");<br>
+  }<br>
+};<br>
+<br>
+INSTANTIATE_TEST_CASE_P(<br>
+    RenameClassTests, RenameClassTest,<br>
+    testing::ValuesIn(std::vector<<wbr>Case>({<br>
+        // basic classes<br>
+        {"a::Foo f;", "b::Bar f;", "", ""},<br>
+        {"void f(a::Foo f) {}", "void f(b::Bar f) {}", "", ""},<br>
+        {"void f(a::Foo *f) {}", "void f(b::Bar *f) {}", "", ""},<br>
+        {"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }",<br>
+         "", ""},<br>
+        {"namespace a {a::Foo f() { return Foo(); }}",<br>
+         "namespace a {b::Bar f() { return b::Bar(); }}", "", ""},<br>
+        {"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}", "", ""},<br>
+        {"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}", "", ""},<br>
+        {"namespace a { void f(Foo a1) {} }",<br>
+         "namespace a { void f(b::Bar a1) {} }", "", ""},<br>
+        {"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}", "", ""},<br>
+        {"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}", "", ""},<br>
+        {"a::Foo::Nested ns;", "b::Bar::Nested ns;", "", ""},<br>
+        {"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;", "", ""},<br>
+        {"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested",<br>
+         "a::Foo::Nested2"},<br>
+<br>
+        // use namespace and typedefs<br>
+        {"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;", "", ""},<br>
+        {"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}",<br>
+         "", ""},<br>
+        {"using a::Foo; namespace x { Foo gA; }",<br>
+         "using b::Bar; namespace x { Bar gA; }", "", ""},<br>
+        {"struct S { using T = a::Foo; T a_; };",<br>
+         "struct S { using T = b::Bar; T a_; };", "", ""},<br>
+        {"using T = a::Foo; T gA;", "using T = b::Bar; T gA;", "", ""},<br>
+        {"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;", "", ""},<br>
+        {"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;", "",<br>
+         ""},<br>
+<br>
+        // struct members and other oddities<br>
+        {"struct S : public a::Foo {};", "struct S : public b::Bar {};", "",<br>
+         ""},<br>
+        {"struct F { void f(a::Foo a1) {} };",<br>
+         "struct F { void f(b::Bar a1) {} };", "", ""},<br>
+        {"struct F { a::Foo a_; };", "struct F { b::Bar a_; };", "", ""},<br>
+        {"struct F { ptr<a::Foo> a_; };", "struct F { ptr<b::Bar> a_; };", "",<br>
+         ""},<br>
+<br>
+        {"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }",<br>
+         "", ""},<br>
+        {"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }",<br>
+         "", ""},<br>
+        {"void f() { a::Foo::Nested::NestedEnum e; }",<br>
+         "void f() { b::Bar::Nested::NestedEnum e; }", "", ""},<br>
+        {"void f() { auto e = a::Foo::Nested::NestedEnum::<wbr>E1; }",<br>
+         "void f() { auto e = b::Bar::Nested::NestedEnum::<wbr>E1; }", "", ""},<br>
+        {"void f() { auto e = a::Foo::Nested::E1; }",<br>
+         "void f() { auto e = b::Bar::Nested::E1; }", "", ""},<br>
+<br>
+        // templates<br>
+        {"template <typename T> struct Foo { T t; };\n"<br>
+         "void f() { Foo<a::Foo> foo; }",<br>
+         "template <typename T> struct Foo { T t; };\n"<br>
+         "void f() { Foo<b::Bar> foo; }",<br>
+         "", ""},<br>
+        {"template <typename T> struct Foo { a::Foo a; };",<br>
+         "template <typename T> struct Foo { b::Bar a; };", "", ""},<br>
+        {"template <typename T> void f(T t) {}\n"<br>
+         "void g() { f<a::Foo>(a::Foo()); }",<br>
+         "template <typename T> void f(T t) {}\n"<br>
+         "void g() { f<b::Bar>(b::Bar()); }",<br>
+         "", ""},<br>
+        {"template <typename T> int f() { return 1; }\n"<br>
+         "template <> int f<a::Foo>() { return 2; }\n"<br>
+         "int g() { return f<a::Foo>(); }",<br>
+         "template <typename T> int f() { return 1; }\n"<br>
+         "template <> int f<b::Bar>() { return 2; }\n"<br>
+         "int g() { return f<b::Bar>(); }",<br>
+         "", ""},<br>
+        {"struct Foo { template <typename T> T foo(); };\n"<br>
+         "void g() { Foo f;  auto a = f.template foo<a::Foo>(); }",<br>
+         "struct Foo { template <typename T> T foo(); };\n"<br>
+         "void g() { Foo f;  auto a = f.template foo<b::Bar>(); }",<br>
+         "", ""},<br>
+<br>
+        // The following two templates are distilled from regressions found in<br>
+        // unique_ptr<> and type_traits.h<br>
+        {"template <typename T> struct outer {\n"<br>
+         "     typedef T type;\n"<br>
+         "     type Baz();\n"<br>
+         "    };\n"<br>
+         "    outer<a::Foo> g_A;",<br>
+         "template <typename T> struct outer {\n"<br>
+         "      typedef T type;\n"<br>
+         "      type Baz();\n"<br>
+         "    };\n"<br>
+         "    outer<b::Bar> g_A;",<br>
+         "", ""},<br>
+        {"template <typename T> struct nested { typedef T type; };\n"<br>
+         "template <typename T> struct outer { typename nested<T>::type Foo(); "<br>
+         "};\n"<br>
+         "outer<a::Foo> g_A;",<br>
+         "template <typename T> struct nested { typedef T type; };\n"<br>
+         "template <typename T> struct outer { typename nested<T>::type Foo(); "<br>
+         "};\n"<br>
+         "outer<b::Bar> g_A;",<br>
+         "", ""},<br>
+<br>
+        // macros<br>
+        {"#define FOO(T, t) T t\n"<br>
+         "void f() { FOO(a::Foo, a1); FOO(a::Foo, a2); }",<br>
+         "#define FOO(T, t) T t\n"<br>
+         "void f() { FOO(b::Bar, a1); FOO(b::Bar, a2); }",<br>
+         "", ""},<br>
+        {"#define FOO(n) a::Foo n\n"<br>
+         " void f() { FOO(a1); FOO(a2); }",<br>
+         "#define FOO(n) b::Bar n\n"<br>
+         " void f() { FOO(a1); FOO(a2); }",<br>
+         "", ""},<br>
+<br>
+        // Pointer to member functions<br>
+        {"auto gA = &a::Foo::func;", "auto gA = &b::Bar::func;", "", ""},<br>
+        {"using a::Foo; auto gA = &Foo::func;",<br>
+         "using b::Bar; auto gA = &b::Bar::func;", "", ""},<br>
+        {"using a::Foo; namespace x { auto gA = &Foo::func; }",<br>
+         "using b::Bar; namespace x { auto gA = &Bar::func; }", "", ""},<br>
+        {"typedef a::Foo T; auto gA = &T::func;",<br>
+         "typedef b::Bar T; auto gA = &T::func;", "", ""},<br>
+        {"auto gA = &MACRO(a::Foo)::func;", "auto gA = &MACRO(b::Bar)::func;",<br>
+         "", ""},<br>
+<br>
+        // Short match inside a namespace<br>
+        {"namespace a { void f(Foo a1) {} }",<br>
+         "namespace a { void f(b::Bar a1) {} }", "", ""},<br>
+<br>
+        // Correct match.<br>
+        {"using a::Foo; struct F { ptr<Foo> a_; };",<br>
+         "using b::Bar; struct F { ptr<Bar> a_; };", "", ""},<br>
+<br>
+        // avoid false positives<br>
+        {"void f(b::Foo a) {}", "void f(b::Foo a) {}", "", ""},<br>
+        {"namespace b { void f(Foo a) {} }", "namespace b { void f(Foo a) {} }",<br>
+         "", ""},<br>
+<br>
+        // friends, everyone needs friends.<br>
+        {"class Foo { int i; friend class a::Foo; };",<br>
+         "class Foo { int i; friend class b::Bar; };", "", ""},<br>
+    })), );<br>
+<br>
+TEST_P(RenameClassTest, RenameClasses) {<br>
+  auto Param = GetParam();<br>
+  std::string OldName = Param.OldName.empty() ? "a::Foo" : Param.OldName;<br>
+  std::string NewName = Param.NewName.empty() ? "b::Bar" : Param.NewName;<br>
+  std::string Actual = runClangRenameOnCode(Param.<wbr>Before, OldName, NewName);<br>
+  CompareSnippets(Param.After, Actual);<br>
+}<br>
+<br>
+class NamespaceDetectionTest : public ClangRenameTest {<br>
+protected:<br>
+  NamespaceDetectionTest() {<br>
+    AppendToHeader(R"(<br>
+         class Old {};<br>
+         namespace o1 {<br>
+         class Old {};<br>
+         namespace o2 {<br>
+         class Old {};<br>
+         namespace o3 {<br>
+         class Old {};<br>
+         }  // namespace o3<br>
+         }  // namespace o2<br>
+         }  // namespace o1<br>
+     )");<br>
+  }<br>
+};<br>
+<br>
+INSTANTIATE_TEST_CASE_P(<br>
+    RenameClassTest, NamespaceDetectionTest,<br>
+    ::testing::ValuesIn(std::<wbr>vector<Case>({<br>
+        // Test old and new namespace overlap.<br>
+        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",<br>
+         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",<br>
+         "o1::o2::o3::Old", "o1::o2::o3::New"},<br>
+        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",<br>
+         "namespace o1 { namespace o2 { namespace o3 { n3::New moo; } } }",<br>
+         "o1::o2::o3::Old", "o1::o2::n3::New"},<br>
+        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",<br>
+         "namespace o1 { namespace o2 { namespace o3 { n2::n3::New moo; } } }",<br>
+         "o1::o2::o3::Old", "o1::n2::n3::New"},<br>
+        {"namespace o1 { namespace o2 { Old moo; } }",<br>
+         "namespace o1 { namespace o2 { New moo; } }", "::o1::o2::Old",<br>
+         "::o1::o2::New"},<br>
+        {"namespace o1 { namespace o2 { Old moo; } }",<br>
+         "namespace o1 { namespace o2 { n2::New moo; } }", "::o1::o2::Old",<br>
+         "::o1::n2::New"},<br>
+        {"namespace o1 { namespace o2 { Old moo; } }",<br>
+         "namespace o1 { namespace o2 { ::n1::n2::New moo; } }",<br>
+         "::o1::o2::Old", "::n1::n2::New"},<br>
+        {"namespace o1 { namespace o2 { Old moo; } }",<br>
+         "namespace o1 { namespace o2 { n1::n2::New moo; } }", "::o1::o2::Old",<br>
+         "n1::n2::New"},<br>
+<br>
+        // Test old and new namespace with differing depths.<br>
+        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",<br>
+         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",<br>
+         "o1::o2::o3::Old", "::o1::New"},<br>
+        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",<br>
+         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",<br>
+         "o1::o2::o3::Old", "::o1::o2::New"},<br>
+        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",<br>
+         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",<br>
+         "o1::o2::o3::Old", "o1::New"},<br>
+        {"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",<br>
+         "namespace o1 { namespace o2 { namespace o3 { New moo; } } }",<br>
+         "o1::o2::o3::Old", "o1::o2::New"},<br>
+        {"Old moo;", "o1::New moo;", "::Old", "o1::New"},<br>
+        {"Old moo;", "o1::New moo;", "Old", "o1::New"},<br>
+        {"namespace o1 { ::Old moo; }", "namespace o1 { New moo; }", "Old",<br>
+         "o1::New"},<br>
+        {"namespace o1 { namespace o2 {  Old moo; } }",<br>
+         "namespace o1 { namespace o2 {  ::New moo; } }", "::o1::o2::Old",<br>
+         "::New"},<br>
+        {"namespace o1 { namespace o2 {  Old moo; } }",<br>
+         "namespace o1 { namespace o2 {  New moo; } }", "::o1::o2::Old", "New"},<br>
+<br>
+        // Test moving into the new namespace at different levels.<br>
+        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",<br>
+         "namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old",<br>
+         "::n1::n2::New"},<br>
+        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",<br>
+         "namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old",<br>
+         "n1::n2::New"},<br>
+        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",<br>
+         "namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old",<br>
+         "::n1::o2::New"},<br>
+        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",<br>
+         "namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old",<br>
+         "n1::o2::New"},<br>
+        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",<br>
+         "namespace n1 { namespace n2 { ::o1::o2::New moo; } }",<br>
+         "::o1::o2::Old", "::o1::o2::New"},<br>
+        {"namespace n1 { namespace n2 { o1::o2::Old moo; } }",<br>
+         "namespace n1 { namespace n2 { o1::o2::New moo; } }", "::o1::o2::Old",<br>
+         "o1::o2::New"},<br>
+<br>
+        // Test friends declarations.<br>
+        {"class Foo { friend class o1::Old; };",<br>
+         "class Foo { friend class o1::New; };", "o1::Old", "o1::New"},<br>
+        {"class Foo { int i; friend class o1::Old; };",<br>
+         "class Foo { int i; friend class ::o1::New; };", "::o1::Old",<br>
+         "::o1::New"},<br>
+        {"namespace o1 { class Foo { int i; friend class Old; }; }",<br>
+         "namespace o1 { class Foo { int i; friend class New; }; }", "o1::Old",<br>
+         "o1::New"},<br>
+        {"namespace o1 { class Foo { int i; friend class Old; }; }",<br>
+         "namespace o1 { class Foo { int i; friend class New; }; }",<br>
+         "::o1::Old", "::o1::New"},<br>
+    })), );<br>
+<br>
+TEST_P(<wbr>NamespaceDetectionTest, RenameClasses) {<br>
+  auto Param = GetParam();<br>
+  std::string Actual =<br>
+      runClangRenameOnCode(Param.<wbr>Before, Param.OldName, Param.NewName);<br>
+  CompareSnippets(Param.After, Actual);<br>
+}<br>
+<br>
+class TemplatedClassRenameTest : public ClangRenameTest {<br>
+protected:<br>
+  TemplatedClassRenameTest() {<br>
+    AppendToHeader(R"(<br>
+           template <typename T> struct Old {<br>
+             T t_;<br>
+             T f() { return T(); };<br>
+             static T s(T t) { return t; }<br>
+           };<br>
+           namespace ns {<br>
+           template <typename T> struct Old {<br>
+             T t_;<br>
+             T f() { return T(); };<br>
+             static T s(T t) { return t; }<br>
+           };<br>
+           }  // namespace ns<br>
+<br>
+           namespace o1 {<br>
+           namespace o2 {<br>
+           namespace o3 {<br>
+           template <typename T> struct Old {<br>
+             T t_;<br>
+             T f() { return T(); };<br>
+             static T s(T t) { return t; }<br>
+           };<br>
+           }  // namespace o3<br>
+           }  // namespace o2<br>
+           }  // namespace o1<br>
+       )");<br>
+  }<br>
+};<br>
+<br>
+INSTANTIATE_TEST_CASE_P(<br>
+    RenameClassTests, TemplatedClassRenameTest,<br>
+    ::testing::ValuesIn(std::<wbr>vector<Case>({<br>
+        {"Old<int> gI; Old<bool> gB;", "New<int> gI; New<bool> gB;", "Old",<br>
+         "New"},<br>
+        {"ns::Old<int> gI; ns::Old<bool> gB;",<br>
+         "ns::New<int> gI; ns::New<bool> gB;", "ns::Old", "ns::New"},<br>
+        {"auto gI = &Old<int>::f; auto gB = &Old<bool>::f;",<br>
+         "auto gI = &New<int>::f; auto gB = &New<bool>::f;", "Old", "New"},<br>
+        {"auto gI = &ns::Old<int>::f;", "auto gI = &ns::New<int>::f;",<br>
+         "ns::Old", "ns::New"},<br>
+<br>
+        {"int gI = Old<int>::s(0); bool gB = Old<bool>::s(false);",<br>
+         "int gI = New<int>::s(0); bool gB = New<bool>::s(false);", "Old",<br>
+         "New"},<br>
+        {"int gI = ns::Old<int>::s(0); bool gB = ns::Old<bool>::s(false);",<br>
+         "int gI = ns::New<int>::s(0); bool gB = ns::New<bool>::s(false);",<br>
+         "ns::Old", "ns::New"},<br>
+<br>
+        {"struct S { Old<int*> o_; };", "struct S { New<int*> o_; };", "Old",<br>
+         "New"},<br>
+        {"struct S { ns::Old<int*> o_; };", "struct S { ns::New<int*> o_; };",<br>
+         "ns::Old", "ns::New"},<br>
+<br>
+        {"auto a = reinterpret_cast<Old<int>*>(<wbr>new Old<int>);",<br>
+         "auto a = reinterpret_cast<New<int>*>(<wbr>new New<int>);", "Old", "New"},<br>
+        {"auto a = reinterpret_cast<ns::Old<int>*<wbr>>(new ns::Old<int>);",<br>
+         "auto a = reinterpret_cast<ns::New<int>*<wbr>>(new ns::New<int>);",<br>
+         "ns::Old", "ns::New"},<br>
+        {"auto a = reinterpret_cast<const Old<int>*>(new Old<int>);",<br>
+         "auto a = reinterpret_cast<const New<int>*>(new New<int>);", "Old",<br>
+         "New"},<br>
+        {"auto a = reinterpret_cast<const ns::Old<int>*>(new ns::Old<int>);",<br>
+         "auto a = reinterpret_cast<const ns::New<int>*>(new ns::New<int>);",<br>
+         "ns::Old", "ns::New"},<br>
+<br>
+        {"Old<bool>& foo();", "New<bool>& foo();", "Old", "New"},<br>
+        {"ns::Old<bool>& foo();", "ns::New<bool>& foo();", "ns::Old",<br>
+         "ns::New"},<br>
+        {"o1::o2::o3::Old<bool>& foo();", "o1::o2::o3::New<bool>& foo();",<br>
+         "o1::o2::o3::Old", "o1::o2::o3::New"},<br>
+        {"namespace ns { Old<bool>& foo(); }",<br>
+         "namespace ns { New<bool>& foo(); }", "ns::Old", "ns::New"},<br>
+        {"const Old<bool>& foo();", "const New<bool>& foo();", "Old", "New"},<br>
+        {"const ns::Old<bool>& foo();", "const ns::New<bool>& foo();",<br>
+         "ns::Old", "ns::New"},<br>
+<br>
+        // FIXME: figure out why this only works when Moo gets<br>
+        // specialized at some point.<br>
+        {"template <typename T> struct Moo { Old<T> o_; }; Moo<int> m;",<br>
+         "template <typename T> struct Moo { New<T> o_; }; Moo<int> m;", "Old",<br>
+         "New"},<br>
+        {"template <typename T> struct Moo { ns::Old<T> o_; }; Moo<int> m;",<br>
+         "template <typename T> struct Moo { ns::New<T> o_; }; Moo<int> m;",<br>
+         "ns::Old", "ns::New"},<br>
+    })), );<br>
+<br>
+TEST_P(<wbr>TemplatedClassRenameTest, RenameTemplateClasses) {<br>
+  auto Param = GetParam();<br>
+  std::string Actual =<br>
+      runClangRenameOnCode(Param.<wbr>Before, Param.OldName, Param.NewName);<br>
+  CompareSnippets(Param.After, Actual);<br>
+}<br>
+<br>
+TEST_F(ClangRenameTest, RenameClassWithOutOfLineMember<wbr>s) {<br>
+  std::string Before = R"(<br>
+      class Old {<br>
+       public:<br>
+        Old();<br>
+        ~Old();<br>
+<br>
+        Old* next();<br>
+<br>
+       private:<br>
+        Old* next_;<br>
+      };<br>
+<br>
+      Old::Old() {}<br>
+      Old::~Old() {}<br>
+      Old* Old::next() { return next_; }<br>
+    )";<br>
+  std::string Expected = R"(<br>
+      class New {<br>
+       public:<br>
+        New();<br>
+        ~New();<br>
+<br>
+        New* next();<br>
+<br>
+       private:<br>
+        New* next_;<br>
+      };<br>
+<br>
+      New::New() {}<br>
+      New::~New() {}<br>
+      New* New::next() { return next_; }<br>
+    )";<br>
+  std::string After = runClangRenameOnCode(Before, "Old", "New");<br>
+  CompareSnippets(Expected, After);<br>
+}<br>
+<br>
+TEST_F(ClangRenameTest, RenameClassWithInlineMembers) {<br>
+  std::string Before = R"(<br>
+      class Old {<br>
+       public:<br>
+        Old() {}<br>
+        ~Old() {}<br>
+<br>
+        Old* next() { return next_; }<br>
+<br>
+       private:<br>
+        Old* next_;<br>
+      };<br>
+    )";<br>
+  std::string Expected = R"(<br>
+      class New {<br>
+       public:<br>
+        New() {}<br>
+        ~New() {}<br>
+<br>
+        New* next() { return next_; }<br>
+<br>
+       private:<br>
+        New* next_;<br>
+      };<br>
+    )";<br>
+  std::string After = runClangRenameOnCode(Before, "Old", "New");<br>
+  CompareSnippets(Expected, After);<br>
+}<br>
+<br>
+// FIXME: no prefix qualifiers being added to the class definition and<br>
+// constructor.<br>
+TEST_F(ClangRenameTest, RenameClassWithNamespaceWithIn<wbr>lineMembers) {<br>
+  std::string Before = R"(<br>
+      namespace ns {<br>
+      class Old {<br>
+       public:<br>
+        Old() {}<br>
+        ~Old() {}<br>
+<br>
+        Old* next() { return next_; }<br>
+<br>
+       private:<br>
+        Old* next_;<br>
+      };<br>
+      }  // namespace ns<br>
+    )";<br>
+  std::string Expected = R"(<br>
+      namespace ns {<br>
+      class ns::New {<br>
+       public:<br>
+        ns::New() {}<br>
+        ~New() {}<br>
+<br>
+        New* next() { return next_; }<br>
+<br>
+       private:<br>
+        New* next_;<br>
+      };<br>
+      }  // namespace ns<br>
+    )";<br>
+  std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");<br>
+  CompareSnippets(Expected, After);<br>
+}<br>
+<br>
+// FIXME: no prefix qualifiers being added to the class definition and<br>
+// constructor.<br>
+TEST_F(ClangRenameTest, RenameClassWithNamespaceWithOu<wbr>tOfInlineMembers) {<br>
+  std::string Before = R"(<br>
+      namespace ns {<br>
+      class Old {<br>
+       public:<br>
+        Old();<br>
+        ~Old();<br>
+<br>
+        Old* next();<br>
+<br>
+       private:<br>
+        Old* next_;<br>
+      };<br>
+<br>
+      Old::Old() {}<br>
+      Old::~Old() {}<br>
+      Old* Old::next() { return next_; }<br>
+      }  // namespace ns<br>
+    )";<br>
+  std::string Expected = R"(<br>
+      namespace ns {<br>
+      class ns::New {<br>
+       public:<br>
+        ns::New();<br>
+        ~New();<br>
+<br>
+        New* next();<br>
+<br>
+       private:<br>
+        New* next_;<br>
+      };<br>
+<br>
+      New::ns::New() {}<br>
+      New::~New() {}<br>
+      New* New::next() { return next_; }<br>
+      }  // namespace ns<br>
+    )";<br>
+  std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");<br>
+  CompareSnippets(Expected, After);<br>
+}<br>
+<br>
+// FIXME: no prefix qualifiers being added to the definition.<br>
+TEST_F(ClangRenameTest, RenameClassInInheritedConstruc<wbr>tor) {<br>
+  // `using Base::Base;` will generate an implicit constructor containing usage<br>
+  // of `::ns::Old` which should not be matched.<br>
+  std::string Before = R"(<br>
+      namespace ns {<br>
+      class Old {<br>
+        int x;<br>
+      };<br>
+      class Base {<br>
+       protected:<br>
+        Old *moo_;<br>
+       public:<br>
+        Base(Old *moo) : moo_(moo) {}<br>
+      };<br>
+      class Derived : public Base {<br>
+       public:<br>
+         using Base::Base;<br>
+      };<br>
+      }  // namespace ns<br>
+      int main() {<br>
+        ::ns::Old foo;<br>
+        ::ns::Derived d(&foo);<br>
+        return 0;<br>
+      })";<br>
+  std::string Expected = R"(<br>
+      namespace ns {<br>
+      class ns::New {<br>
+        int x;<br>
+      };<br>
+      class Base {<br>
+       protected:<br>
+        New *moo_;<br>
+       public:<br>
+        Base(New *moo) : moo_(moo) {}<br>
+      };<br>
+      class Derived : public Base {<br>
+       public:<br>
+         using Base::Base;<br>
+      };<br>
+      }  // namespace ns<br>
+      int main() {<br>
+        ::ns::New foo;<br>
+        ::ns::Derived d(&foo);<br>
+        return 0;<br>
+      })";<br>
+  std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");<br>
+  CompareSnippets(Expected, After);<br>
+}<br>
+<br>
+TEST_F(ClangRenameTest, DontRenameReferencesInImplicit<wbr>Function) {<br>
+  std::string Before = R"(<br>
+      namespace ns {<br>
+      class Old {<br>
+      };<br>
+      } // namespace ns<br>
+      struct S {<br>
+        int y;<br>
+        ns::Old old;<br>
+      };<br>
+      void f() {<br>
+        S s1, s2, s3;<br>
+        // This causes an implicit assignment operator to be created.<br>
+        s1 = s2 = s3;<br>
+      }<br>
+      )";<br>
+  std::string Expected = R"(<br>
+      namespace ns {<br>
+      class ::new_ns::New {<br>
+      };<br>
+      } // namespace ns<br>
+      struct S {<br>
+        int y;<br>
+        ::new_ns::New old;<br>
+      };<br>
+      void f() {<br>
+        S s1, s2, s3;<br>
+        // This causes an implicit assignment operator to be created.<br>
+        s1 = s2 = s3;<br>
+      }<br>
+      )";<br>
+  std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New");<br>
+  CompareSnippets(Expected, After);<br>
+}<br>
+<br>
+// FIXME: no prefix qualifiers being adding to the definition.<br>
+TEST_F(ClangRenameTest, ReferencesInLambdaFunctionPara<wbr>meters) {<br>
+  std::string Before = R"(<br>
+      template <class T><br>
+      class function;<br>
+      template <class R, class... ArgTypes><br>
+      class function<R(ArgTypes...)> {<br>
+      public:<br>
+        template <typename Functor><br>
+        function(Functor f) {}<br>
+<br>
+        function() {}<br>
+<br>
+        R operator()(ArgTypes...) const {}<br>
+      };<br>
+<br>
+      namespace ns {<br>
+      class Old {};<br>
+      void f() {<br>
+        function<void(Old)> func;<br>
+      }<br>
+      }  // namespace ns)";<br>
+  std::string Expected = R"(<br>
+      template <class T><br>
+      class function;<br>
+      template <class R, class... ArgTypes><br>
+      class function<R(ArgTypes...)> {<br>
+      public:<br>
+        template <typename Functor><br>
+        function(Functor f) {}<br>
+<br>
+        function() {}<br>
+<br>
+        R operator()(ArgTypes...) const {}<br>
+      };<br>
+<br>
+      namespace ns {<br>
+      class ::new_ns::New {};<br>
+      void f() {<br>
+        function<void(::new_ns::New)> func;<br>
+      }<br>
+      }  // namespace ns)";<br>
+  std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New");<br>
+  CompareSnippets(Expected, After);<br>
+}<br>
+<br>
+} // anonymous namespace<br>
+} // namespace test<br>
+} // namespace clang_rename<br>
+} // namesdpace clang<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>