Fixed in <span style="color:rgb(0,0,0);line-height:normal">r215857. Sorry :(</span><br><br><div class="gmail_quote">On Sun Aug 17 2014 at 11:44:23 PM Rafael Espíndola <<a href="mailto:rafael.espindola@gmail.com">rafael.espindola@gmail.com</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Looks like this is failing on msvc:<br>
<br>
<a href="http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/9983/steps/build_clang_tools/logs/stdio" target="_blank">http://bb.pgr.jp/builders/<u></u>ninja-clang-i686-msc17-R/<u></u>builds/9983/steps/build_clang_<u></u>tools/logs/stdio</a><br>

<br>
On 17 August 2014 14:00, Manuel Klimek <<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>> wrote:<br>
> Author: klimek<br>
> Date: Sun Aug 17 13:00:59 2014<br>
> New Revision: 215839<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=215839&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=215839&view=rev</a><br>
> Log:<br>
> First version of a clang-rename tool.<br>
><br>
> Summary:<br>
> Note that this code is still grossly under-tested - the next steps will<br>
> be to add significantly better test coverage.<br>
><br>
> Patch by Matthew Plant.<br>
><br>
> Test Plan:<br>
><br>
> Reviewers:<br>
><br>
> Subscribers:<br>
><br>
> Added:<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/CMakeLists.txt<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/ClangRename.cpp<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/Makefile<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.cpp<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.h<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.cpp<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.h<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.cpp<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.h<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.cpp<br>
>     clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.h<br>
>     clang-tools-extra/trunk/test/<u></u>clang-rename/<br>
>     clang-tools-extra/trunk/test/<u></u>clang-rename/VarTest.cpp<br>
>     clang-tools-extra/trunk/<u></u>unittests/clang-rename/<br>
>     clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>CMakeLists.txt<br>
>     clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>Makefile<br>
>     clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>USRLocFindingTest.cpp<br>
> Modified:<br>
>     clang-tools-extra/trunk/<u></u>CMakeLists.txt<br>
>     clang-tools-extra/trunk/<u></u>Makefile<br>
>     clang-tools-extra/trunk/test/<u></u>CMakeLists.txt<br>
>     clang-tools-extra/trunk/<u></u>unittests/CMakeLists.txt<br>
><br>
> Modified: clang-tools-extra/trunk/<u></u>CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/CMakeLists.txt?rev=215839&r1=215838&r2=215839&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/CMakeLists.txt?rev=<u></u>215839&r1=215838&r2=215839&<u></u>view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/<u></u>CMakeLists.txt (original)<br>
> +++ clang-tools-extra/trunk/<u></u>CMakeLists.txt Sun Aug 17 13:00:59 2014<br>
> @@ -1,5 +1,6 @@<br>
>  add_subdirectory(clang-apply-<u></u>replacements)<br>
>  add_subdirectory(clang-<u></u>modernize)<br>
> +add_subdirectory(clang-<u></u>rename)<br>
>  add_subdirectory(modularize)<br>
>  add_subdirectory(module-map-<u></u>checker)<br>
>  add_subdirectory(remove-cstr-<u></u>calls)<br>
><br>
> Modified: clang-tools-extra/trunk/<u></u>Makefile<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/Makefile?rev=215839&r1=215838&r2=215839&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/Makefile?rev=215839&r1=<u></u>215838&r2=215839&view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/<u></u>Makefile (original)<br>
> +++ clang-tools-extra/trunk/<u></u>Makefile Sun Aug 17 13:00:59 2014<br>
> @@ -13,8 +13,8 @@ include $(CLANG_LEVEL)/../../Makefile.<u></u>co<br>
><br>
>  PARALLEL_DIRS := remove-cstr-calls tool-template modularize \<br>
>   module-map-checker pp-trace<br>
> -DIRS := clang-apply-replacements clang-modernize clang-tidy clang-query \<br>
> -       unittests<br>
> +DIRS := clang-apply-replacements clang-modernize clang-rename clang-tidy \<br>
> +       clang-query unittests<br>
><br>
>  include $(CLANG_LEVEL)/Makefile<br>
><br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/CMakeLists.txt?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/CMakeLists.<u></u>txt?rev=215839&view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/CMakeLists.txt (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/CMakeLists.txt Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,29 @@<br>
> +set(LLVM_LINK_COMPONENTS support)<br>
> +<br>
> +add_clang_executable(clang-<u></u>rename<br>
> +  ClangRename.cpp<br>
> +  USRFinder.cpp<br>
> +  USRFindingAction.cpp<br>
> +  USRLocFinder.cpp<br>
> +  RenamingAction.cpp<br>
> +  )<br>
> +<br>
> +target_link_libraries(clang-<u></u>rename<br>
> +  clangAnalysis<br>
> +  clangAST<br>
> +  clangBasic<br>
> +  clangDriver<br>
> +  clangEdit<br>
> +  clangFrontend<br>
> +  clangFrontendTool<br>
> +  clangIndex<br>
> +  clangLex<br>
> +  clangParse<br>
> +  clangRewrite<br>
> +  clangRewriteFrontend<br>
> +  clangSerialization<br>
> +  clangSema<br>
> +  clangTooling<br>
> +  )<br>
> +<br>
> +install(TARGETS clang-rename RUNTIME DESTINATION bin)<br>
> \ No newline at end of file<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/ClangRename.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/ClangRename.cpp?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/<u></u>ClangRename.cpp?rev=215839&<u></u>view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/ClangRename.cpp (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/ClangRename.cpp Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,151 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief This file implements a clang-rename tool that automatically finds and<br>
> +/// renames symbols in C++ code.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#include "USRFindingAction.h"<br>
> +#include "RenamingAction.h"<br>
> +#include "clang/AST/ASTConsumer.h"<br>
> +#include "clang/AST/ASTContext.h"<br>
> +#include "clang/Basic/FileManager.h"<br>
> +#include "clang/Basic/LangOptions.h"<br>
> +#include "clang/Basic/TargetInfo.h"<br>
> +#include "clang/Basic/TargetOptions.h"<br>
> +#include "clang/Frontend/<u></u>CommandLineSourceLoc.h"<br>
> +#include "clang/Frontend/<u></u>CompilerInstance.h"<br>
> +#include "clang/Frontend/<u></u>FrontendAction.h"<br>
> +#include "clang/Frontend/<u></u>TextDiagnosticPrinter.h"<br>
> +#include "clang/Lex/Preprocessor.h"<br>
> +#include "clang/Lex/Lexer.h"<br>
> +#include "clang/Parse/Parser.h"<br>
> +#include "clang/Parse/ParseAST.h"<br>
> +#include "clang/Rewrite/Core/Rewriter.<u></u>h"<br>
> +#include "clang/Tooling/<u></u>CommonOptionsParser.h"<br>
> +#include "clang/Tooling/Refactoring.h"<br>
> +#include "clang/Tooling/Tooling.h"<br>
> +#include "llvm/ADT/IntrusiveRefCntPtr.<u></u>h"<br>
> +#include "llvm/Support/Host.h"<br>
> +#include <stdio.h><br>
> +#include <stdlib.h><br>
> +#include <time.h><br>
> +#include <ctype.h><br>
> +#include <string><br>
> +#include <vector><br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +cl::OptionCategory ClangRenameCategory("Clang-<u></u>rename options");<br>
> +<br>
> +static cl::opt<std::string><br>
> +NewName(<br>
> +    "new-name",<br>
> +    cl::desc("The new name to change the symbol to."),<br>
> +    cl::cat(ClangRenameCategory));<br>
> +static cl::opt<unsigned><br>
> +SymbolOffset(<br>
> +    "offset",<br>
> +    cl::desc("Locates the symbol by offset as opposed to <line>:<column>."),<br>
> +    cl::cat(ClangRenameCategory));<br>
> +static cl::opt<bool><br>
> +Inplace(<br>
> +    "i",<br>
> +    cl::desc("Overwrite edited <file>s."),<br>
> +    cl::cat(ClangRenameCategory));<br>
> +static cl::opt<bool><br>
> +PrintName(<br>
> +    "pn",<br>
> +    cl::desc("Print the found symbol's name prior to renaming to stderr."),<br>
> +    cl::cat(ClangRenameCategory));<br>
> +static cl::opt<bool><br>
> +PrintLocations(<br>
> +    "pl",<br>
> +    cl::desc("Print the locations affected by renaming to stderr."),<br>
> +    cl::cat(ClangRenameCategory));<br>
> +<br>
> +#define CLANG_RENAME_VERSION "0.0.1"<br>
> +<br>
> +static void PrintVersion() {<br>
> +  outs() << "clang-rename version " << CLANG_RENAME_VERSION << "\n";<br>
> +}<br>
> +<br>
> +using namespace clang;<br>
> +<br>
> +const char RenameUsage[] = "A tool to rename symbols in C/C++ code.\n\<br>
> +clang-rename renames every occurrence of a symbol found at <offset> in\n\<br>
> +<source0>. If -i is specified, the edited files are overwritten to disk.\n\<br>
> +Otherwise, the results are written to stdout.\n";<br>
> +<br>
> +int main(int argc, const char **argv) {<br>
> +  cl::SetVersionPrinter(<u></u>PrintVersion);<br>
> +  tooling::CommonOptionsParser OP(argc, argv, ClangRenameCategory, RenameUsage);<br>
> +<br>
> +  // Check the arguments for correctness.<br>
> +<br>
> +  if (NewName.empty()) {<br>
> +    errs() << "clang-rename: no new name provided.\n\n";<br>
> +    cl::PrintHelpMessage();<br>
> +    exit(1);<br>
> +  }<br>
> +<br>
> +  // Get the USRs.<br>
> +  auto Files = OP.getSourcePathList();<br>
> +  tooling::RefactoringTool Tool(OP.getCompilations(), Files);<br>
> +  rename::USRFindingAction USRAction(SymbolOffset);<br>
> +<br>
> +  // Find the USRs.<br>
> +  Tool.run(tooling::<u></u>newFrontendActionFactory(&<u></u>USRAction).get());<br>
> +  const auto &USRs = USRAction.getUSRs();<br>
> +  const auto &PrevName = USRAction.getUSRSpelling();<br>
> +<br>
> +  if (PrevName.empty())<br>
> +    // An error should have already been printed.<br>
> +    exit(1);<br>
> +<br>
> +  if (PrintName)<br>
> +    errs() << "clang-rename: found name: " << PrevName;<br>
> +<br>
> +  // Perform the renaming.<br>
> +  rename::RenamingAction RenameAction(NewName, PrevName, USRs,<br>
> +                                      Tool.getReplacements(), PrintLocations);<br>
> +  auto Factory = tooling::<u></u>newFrontendActionFactory(&<u></u>RenameAction);<br>
> +  int res;<br>
> +<br>
> +  if (Inplace) {<br>
> +    res = Tool.runAndSave(Factory.get())<u></u>;<br>
> +  } else {<br>
> +    res = Tool.run(Factory.get());<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<<u></u>DiagnosticOptions> DiagOpts =<br>
> +        new DiagnosticOptions();<br>
> +    TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);<br>
> +    DiagnosticsEngine Diagnostics(<br>
> +        IntrusiveRefCntPtr<<u></u>DiagnosticIDs>(new DiagnosticIDs()),<br>
> +        &*DiagOpts, &DiagnosticPrinter, false);<br>
> +    auto &FileMgr = Tool.getFiles();<br>
> +    SourceManager Sources(Diagnostics, FileMgr);<br>
> +    Rewriter Rewrite(Sources, DefaultLangOptions);<br>
> +<br>
> +    Tool.applyAllReplacements(<u></u>Rewrite);<br>
> +    for (const auto &File : Files) {<br>
> +      const auto *Entry = FileMgr.getFile(File);<br>
> +      auto ID = Sources.translateFile(Entry);<br>
> +      Rewrite.getEditBuffer(ID).<u></u>write(outs());<br>
> +    }<br>
> +  }<br>
> +<br>
> +  exit(res);<br>
> +}<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/Makefile<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/Makefile?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/Makefile?<u></u>rev=215839&view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/Makefile (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/Makefile Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,16 @@<br>
> +##===- tools/extra/clang-rename/<u></u>Makefile -------------------*- Makefile -*-===##<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>
> +##===------------------------<u></u>------------------------------<u></u>----------------===##<br>
> +<br>
> +CLANG_LEVEL := ../../..<br>
> +TOOLNAME = clang-rename<br>
> +include $(CLANG_LEVEL)/../../Makefile.<u></u>config<br>
> +<br>
> +DIRS = test<br>
> +<br>
> +include $(CLANG_LEVEL)/Makefile<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/RenamingAction.cpp?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/<u></u>RenamingAction.cpp?rev=215839&<u></u>view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.cpp (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.cpp Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,90 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>RenamingAction.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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief Provides an action to rename every symbol at a point.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#include "RenamingAction.h"<br>
> +#include "USRLocFinder.h"<br>
> +#include "clang/AST/ASTConsumer.h"<br>
> +#include "clang/AST/ASTContext.h"<br>
> +#include "clang/Basic/FileManager.h"<br>
> +#include "clang/Frontend/<u></u>CompilerInstance.h"<br>
> +#include "clang/Frontend/<u></u>FrontendAction.h"<br>
> +#include "clang/Lex/Preprocessor.h"<br>
> +#include "clang/Lex/Lexer.h"<br>
> +#include "clang/Tooling/<u></u>CommonOptionsParser.h"<br>
> +#include "clang/Tooling/Refactoring.h"<br>
> +#include "clang/Tooling/Tooling.h"<br>
> +#include <stdio.h><br>
> +#include <stdlib.h><br>
> +#include <ctype.h><br>
> +#include <string><br>
> +#include <vector><br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +namespace clang {<br>
> +namespace rename {<br>
> +<br>
> +class RenamingASTConsumer : public ASTConsumer {<br>
> +public:<br>
> +  RenamingASTConsumer(const std::string &NewName,<br>
> +                      const std::string &PrevName,<br>
> +                      const std::vector<std::string> &USRs,<br>
> +                      tooling::Replacements &Replaces,<br>
> +                      bool PrintLocations)<br>
> +      : NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces),<br>
> +        PrintLocations(PrintLocations) {<br>
> +  }<br>
> +<br>
> +  void HandleTranslationUnit(<u></u>ASTContext &Context) override {<br>
> +    const auto &SourceMgr = Context.getSourceManager();<br>
> +    std::vector<SourceLocation> RenamingCandidates;<br>
> +    std::vector<SourceLocation> NewCandidates;<br>
> +<br>
> +    for (const auto &USR : USRs) {<br>
> +      NewCandidates = getLocationsOfUSR(USR, Context.<u></u>getTranslationUnitDecl());<br>
> +      RenamingCandidates.insert(<u></u>RenamingCandidates.end(), NewCandidates.begin(),<br>
> +                                NewCandidates.end());<br>
> +      NewCandidates.clear();<br>
> +    }<br>
> +<br>
> +    auto PrevNameLen = PrevName.length();<br>
> +    if (PrintLocations)<br>
> +      for (const auto &Loc : RenamingCandidates) {<br>
> +        FullSourceLoc FullLoc(Loc, SourceMgr);<br>
> +        errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc)<br>
> +               << ":" << FullLoc.getSpellingLineNumber(<u></u>) << ":"<br>
> +               << FullLoc.<u></u>getSpellingColumnNumber() << "\n";<br>
> +        Replaces.insert(tooling::<u></u>Replacement(SourceMgr, Loc, PrevNameLen,<br>
> +                                             NewName));<br>
> +      }<br>
> +    else<br>
> +      for (const auto &Loc : RenamingCandidates)<br>
> +        Replaces.insert(tooling::<u></u>Replacement(SourceMgr, Loc, PrevNameLen,<br>
> +                                             NewName));<br>
> +  }<br>
> +<br>
> +private:<br>
> +  const std::string &NewName, &PrevName;<br>
> +  const std::vector<std::string> &USRs;<br>
> +  tooling::Replacements &Replaces;<br>
> +  bool PrintLocations;<br>
> +};<br>
> +<br>
> +std::unique_ptr<ASTConsumer> RenamingAction::<u></u>newASTConsumer() {<br>
> +  return llvm::make_unique<<u></u>RenamingASTConsumer>(NewName, PrevName, USRs,<br>
> +                                                Replaces, PrintLocations);<br>
> +}<br>
> +<br>
> +}<br>
> +}<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/RenamingAction.h?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/<u></u>RenamingAction.h?rev=215839&<u></u>view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.h (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/RenamingAction.h Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,47 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>RenamingAction.h - 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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief Provides an action to rename every symbol at a point.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_RENAMING_ACTION_H_<br>
> +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_RENAMING_ACTION_H_<br>
> +<br>
> +#include "clang/Tooling/Refactoring.h"<br>
> +<br>
> +namespace clang {<br>
> +class ASTConsumer;<br>
> +class CompilerInstance;<br>
> +<br>
> +namespace rename {<br>
> +<br>
> +class RenamingAction {<br>
> +public:<br>
> +  RenamingAction(const std::string &NewName, const std::string &PrevName,<br>
> +                 const std::vector<std::string> &USRs,<br>
> +                 tooling::Replacements &Replaces, bool PrintLocations = false)<br>
> +      : NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces),<br>
> +        PrintLocations(PrintLocations) {<br>
> +  }<br>
> +<br>
> +  std::unique_ptr<ASTConsumer> newASTConsumer();<br>
> +<br>
> +private:<br>
> +  const std::string &NewName, &PrevName;<br>
> +  const std::vector<std::string> &USRs;<br>
> +  tooling::Replacements &Replaces;<br>
> +  bool PrintLocations;<br>
> +};<br>
> +<br>
> +}<br>
> +}<br>
> +<br>
> +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_RENAMING_ACTION_H_<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFinder.cpp?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/USRFinder.<u></u>cpp?rev=215839&view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.cpp (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.cpp Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,162 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>USRFinder.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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file Implements a recursive AST visitor that finds the USR of a symbol at a<br>
> +/// point.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#include "USRFinder.h"<br>
> +#include "clang/AST/AST.h"<br>
> +#include "clang/AST/ASTContext.h"<br>
> +#include "clang/AST/<u></u>RecursiveASTVisitor.h"<br>
> +#include "clang/Lex/Lexer.h"<br>
> +#include "clang/Index/USRGeneration.h"<br>
> +#include "llvm/ADT/SmallVector.h"<br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +namespace clang {<br>
> +namespace rename {<br>
> +<br>
> +// NamedDeclFindingASTVisitor recursively visits each AST node to find the<br>
> +// symbol underneath the cursor.<br>
> +// FIXME: move to seperate .h/.cc file if this gets too large.<br>
> +namespace {<br>
> +class NamedDeclFindingASTVisitor<br>
> +    : public clang::RecursiveASTVisitor<<u></u>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(<u></u>const SourceManager &SourceMgr,<br>
> +                                      const SourceLocation Point)<br>
> +      : Result(nullptr), SourceMgr(SourceMgr),<br>
> +        Point(Point) {<br>
> +  }<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 setResult(Decl, Decl->getLocation(),<br>
> +                     Decl->getNameAsString().<u></u>length());<br>
> +  }<br>
> +<br>
> +  // Expression visitors:<br>
> +<br>
> +  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {<br>
> +    // Check the namespace specifier first.<br>
> +    if (!checkNestedNameSpecifierLoc(<u></u>Expr->getQualifierLoc()))<br>
> +      return false;<br>
> +<br>
> +    const auto *Decl = Expr->getFoundDecl();<br>
> +    return setResult(Decl, Expr->getLocation(),<br>
> +                     Decl->getNameAsString().<u></u>length());<br>
> +  }<br>
> +<br>
> +  bool VisitMemberExpr(const MemberExpr *Expr) {<br>
> +    const auto *Decl = Expr->getFoundDecl().getDecl()<u></u>;<br>
> +    return setResult(Decl, Expr->getMemberLoc(),<br>
> +                     Decl->getNameAsString().<u></u>length());<br>
> +  }<br>
> +<br>
> +  // Other:<br>
> +<br>
> +  const NamedDecl *getNamedDecl() {<br>
> +    return Result;<br>
> +  }<br>
> +<br>
> +private:<br>
> +  // \brief Determines if a namespace qualifier contains the point.<br>
> +  // \returns false on success and sets Result.<br>
> +  bool checkNestedNameSpecifierLoc(<u></u>NestedNameSpecifierLoc NameLoc) {<br>
> +    while (NameLoc) {<br>
> +      const auto *Decl = NameLoc.<u></u>getNestedNameSpecifier()-><u></u>getAsNamespace();<br>
> +      if (Decl && !setResult(Decl, NameLoc.getLocalBeginLoc(),<br>
> +                             Decl->getNameAsString().<u></u>length()))<br>
> +        return false;<br>
> +      NameLoc = NameLoc.getPrefix();<br>
> +    }<br>
> +    return true;<br>
> +  }<br>
> +<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 (!Start.isValid() || !Start.isFileID() || !End.isValid() ||<br>
> +        !End.isFileID() || !isPointWithin(Start, End)) {<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,<br>
> +                 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>
> +           (SourceMgr.<u></u>isBeforeInTranslationUnit(<u></u>Start, Point) &&<br>
> +            SourceMgr.<u></u>isBeforeInTranslationUnit(<u></u>Point, End));<br>
> +  }<br>
> +<br>
> +  const NamedDecl *Result;<br>
> +  const SourceManager &SourceMgr;<br>
> +  const SourceLocation Point; // The location to find the NamedDecl.<br>
> +};<br>
> +}<br>
> +<br>
> +const NamedDecl *getNamedDeclAt(const ASTContext &Context,<br>
> +                                const SourceLocation Point) {<br>
> +  const auto &SourceMgr = Context.getSourceManager();<br>
> +  const auto SearchFile = SourceMgr.getFilename(Point);<br>
> +<br>
> +  NamedDeclFindingASTVisitor Visitor(SourceMgr, Point);<br>
> +<br>
> +  // We only want to search the decls that exist in the same file as the point.<br>
> +  auto Decls = Context.<u></u>getTranslationUnitDecl()-><u></u>decls();<br>
> +  for (auto &CurrDecl : Decls) {<br>
> +    const auto FileLoc = CurrDecl->getLocStart();<br>
> +    const auto FileName = SourceMgr.getFilename(FileLoc)<u></u>;<br>
> +    // FIXME: Add test.<br>
> +    if (FileName == SearchFile) {<br>
> +      Visitor.TraverseDecl(CurrDecl)<u></u>;<br>
> +      if (const NamedDecl *Result = Visitor.getNamedDecl()) {<br>
> +        return Result;<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +<br>
> +  return nullptr;<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(<u></u>Decl, Buff))<br>
> +    return "";<br>
> +<br>
> +  return std::string(Buff.data(), Buff.size());<br>
> +}<br>
> +<br>
> +} // namespace clang<br>
> +} // namespace rename<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFinder.h?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/USRFinder.<u></u>h?rev=215839&view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.h (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/USRFinder.h Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,39 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>USRFinder.h - 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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief Methods for determining the USR of a symbol at a location in source<br>
> +/// code.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_FINDER_H<br>
> +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_FINDER_H<br>
> +<br>
> +#include <string><br>
> +<br>
> +namespace clang {<br>
> +class ASTContext;<br>
> +class Decl;<br>
> +class SourceLocation;<br>
> +class NamedDecl;<br>
> +<br>
> +namespace rename {<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>
> +// Converts a Decl into a USR.<br>
> +std::string getUSRForDecl(const Decl *Decl);<br>
> +<br>
> +}<br>
> +}<br>
> +<br>
> +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_FINDER_H<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/<u></u>USRFindingAction.cpp?rev=<u></u>215839&view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.cpp (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.cpp Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,118 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>USRFindingAction.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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief Provides an action to rename every symbol at a point.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#include "USRFindingAction.h"<br>
> +#include "USRFinder.h"<br>
> +#include "clang/AST/AST.h"<br>
> +#include "clang/AST/ASTConsumer.h"<br>
> +#include "clang/AST/ASTContext.h"<br>
> +#include "clang/Basic/FileManager.h"<br>
> +#include "clang/Frontend/<u></u>CompilerInstance.h"<br>
> +#include "clang/Frontend/<u></u>FrontendAction.h"<br>
> +#include "clang/Lex/Preprocessor.h"<br>
> +#include "clang/Lex/Lexer.h"<br>
> +#include "clang/Tooling/<u></u>CommonOptionsParser.h"<br>
> +#include "clang/Tooling/Refactoring.h"<br>
> +#include "clang/Tooling/Tooling.h"<br>
> +#include <stdio.h><br>
> +#include <stdlib.h><br>
> +#include <ctype.h><br>
> +#include <string><br>
> +#include <vector><br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +namespace clang {<br>
> +namespace rename {<br>
> +<br>
> +// Get the USRs for the constructors of the class.<br>
> +static std::vector<std::string> getAllConstructorUSRs(<br>
> +    const CXXRecordDecl *Decl) {<br>
> +  std::vector<std::string> USRs;<br>
> +<br>
> +  // We need to get the definition of the record (as opposed to any forward<br>
> +  // declarations) in order to find the constructor and destructor.<br>
> +  const auto *RecordDecl = Decl->getDefinition();<br>
> +<br>
> +  // Iterate over all the constructors and add their USRs.<br>
> +  for (const auto &CtorDecl : RecordDecl->ctors())<br>
> +    USRs.push_back(getUSRForDecl(<u></u>CtorDecl));<br>
> +<br>
> +  // Ignore destructors. GetLocationsOfUSR will find the declaration of and<br>
> +  // explicit calls to a destructor through TagTypeLoc (and it is better for the<br>
> +  // purpose of renaming).<br>
> +  //<br>
> +  // For example, in the following code segment,<br>
> +  //  1  class C {<br>
> +  //  2    ~C();<br>
> +  //  3  };<br>
> +  // At line 3, there is a NamedDecl starting from '~' and a TagTypeLoc starting<br>
> +  // from 'C'.<br>
> +<br>
> +  return USRs;<br>
> +}<br>
> +<br>
> +struct NamedDeclFindingConsumer : public ASTConsumer {<br>
> +  void HandleTranslationUnit(<u></u>ASTContext &Context) override {<br>
> +    const auto &SourceMgr = Context.getSourceManager();<br>
> +    // The file we look for the USR in will always be the main source file.<br>
> +    const auto Point = SourceMgr.<u></u>getLocForStartOfFile(<br>
> +        SourceMgr.getMainFileID()).<u></u>getLocWithOffset(SymbolOffset)<u></u>;<br>
> +    if (!Point.isValid())<br>
> +      return;<br>
> +    const NamedDecl *FoundDecl = getNamedDeclAt(Context, Point);<br>
> +    if (FoundDecl == nullptr) {<br>
> +      FullSourceLoc FullLoc(Point, SourceMgr);<br>
> +      errs() << "clang-rename: could not find symbol at "<br>
> +             << SourceMgr.getFilename(Point) << ":"<br>
> +             << FullLoc.getSpellingLineNumber(<u></u>) << ":"<br>
> +             << FullLoc.<u></u>getSpellingColumnNumber() << " (offset " << SymbolOffset<br>
> +             << ").\n";<br>
> +      return;<br>
> +    }<br>
> +<br>
> +    // If the decl is a constructor or destructor, we want to instead take the<br>
> +    // decl of the parent record.<br>
> +    if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(<u></u>FoundDecl))<br>
> +      FoundDecl = CtorDecl->getParent();<br>
> +    else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(<u></u>FoundDecl))<br>
> +      FoundDecl = DtorDecl->getParent();<br>
> +<br>
> +    // If the decl is in any way relatedpp to a class, we want to make sure we<br>
> +    // search for the constructor and destructor as well as everything else.<br>
> +    if (const auto *Record = dyn_cast<CXXRecordDecl>(<u></u>FoundDecl))<br>
> +      *USRs = getAllConstructorUSRs(Record);<br>
> +<br>
> +    USRs->push_back(getUSRForDecl(<u></u>FoundDecl));<br>
> +    *SpellingName = FoundDecl->getNameAsString();<br>
> +  }<br>
> +<br>
> +  unsigned SymbolOffset;<br>
> +  std::string *SpellingName;<br>
> +  std::vector<std::string> *USRs;<br>
> +};<br>
> +<br>
> +std::unique_ptr<ASTConsumer><br>
> +USRFindingAction::<u></u>newASTConsumer() {<br>
> +  std::unique_ptr<<u></u>NamedDeclFindingConsumer> Consumer(<br>
> +      new NamedDeclFindingConsumer);<br>
> +  SpellingName = "";<br>
> +  Consumer->SymbolOffset = SymbolOffset;<br>
> +  Consumer->USRs = &USRs;<br>
> +  Consumer->SpellingName = &SpellingName;<br>
> +  return std::move(Consumer);<br>
> +}<br>
> +<br>
> +} // namespace rename<br>
> +} // namespace clang<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFindingAction.h?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/<u></u>USRFindingAction.h?rev=215839&<u></u>view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.h (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/USRFindingAction.h Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,50 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>USRFindingAction.h - 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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief Provides an action to find all relevent USRs at a point.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_FINDING_ACTION_H_<br>
> +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_FINDING_ACTION_H_<br>
> +<br>
> +#include "clang/Frontend/<u></u>FrontendAction.h"<br>
> +<br>
> +namespace clang {<br>
> +class ASTConsumer;<br>
> +class CompilerInstance;<br>
> +class NamedDecl;<br>
> +<br>
> +namespace rename {<br>
> +<br>
> +struct USRFindingAction {<br>
> +  USRFindingAction(unsigned Offset) : SymbolOffset(Offset) {<br>
> +  }<br>
> +  std::unique_ptr<ASTConsumer> newASTConsumer();<br>
> +<br>
> +  // \brief get the spelling of the USR(s) as it would appear in source files.<br>
> +  const std::string &getUSRSpelling() {<br>
> +    return SpellingName;<br>
> +  }<br>
> +<br>
> +  const std::vector<std::string> &getUSRs() {<br>
> +    return USRs;<br>
> +  }<br>
> +<br>
> +private:<br>
> +  unsigned SymbolOffset;<br>
> +  std::string SpellingName;<br>
> +  std::vector<std::string> USRs;<br>
> +};<br>
> +<br>
> +}<br>
> +}<br>
> +<br>
> +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_FINDING_ACTION_H_<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRLocFinder.cpp?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/<u></u>USRLocFinder.cpp?rev=215839&<u></u>view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.cpp (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.cpp Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,103 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>USRLocFinder.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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief Mehtods 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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#include "USRLocFinder.h"<br>
> +#include "USRFinder.h"<br>
> +#include "clang/AST/ASTContext.h"<br>
> +#include "clang/AST/<u></u>RecursiveASTVisitor.h"<br>
> +#include "clang/Basic/SourceLocation.h"<br>
> +#include "clang/Index/USRGeneration.h"<br>
> +#include "llvm/ADT/SmallVector.h"<br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +namespace clang {<br>
> +namespace rename {<br>
> +<br>
> +namespace {<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<<u></u>USRLocFindingASTVisitor> {<br>
> +public:<br>
> +  explicit USRLocFindingASTVisitor(const std::string USR) : USR(USR) {<br>
> +  }<br>
> +<br>
> +  // Declaration visitors:<br>
> +<br>
> +  bool VisitNamedDecl(const NamedDecl *Decl) {<br>
> +    if (getUSRForDecl(Decl) == USR) {<br>
> +      LocationsFound.push_back(Decl-<u></u>>getLocation());<br>
> +    }<br>
> +    return true;<br>
> +  }<br>
> +<br>
> +  // Expression visitors:<br>
> +<br>
> +  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {<br>
> +    const auto *Decl = Expr->getFoundDecl();<br>
> +<br>
> +    checkNestedNameSpecifierLoc(<u></u>Expr->getQualifierLoc());<br>
> +    if (getUSRForDecl(Decl) == USR) {<br>
> +      LocationsFound.push_back(Expr-<u></u>>getLocation());<br>
> +    }<br>
> +<br>
> +    return true;<br>
> +  }<br>
> +<br>
> +  bool VisitMemberExpr(const MemberExpr *Expr) {<br>
> +    const auto *Decl = Expr->getFoundDecl().getDecl()<u></u>;<br>
> +    if (getUSRForDecl(Decl) == USR) {<br>
> +      LocationsFound.push_back(Expr-<u></u>>getMemberLoc());<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::<u></u>SourceLocation> &getLocationsFound() const {<br>
> +    return LocationsFound;<br>
> +  }<br>
> +<br>
> +private:<br>
> +  // Namespace traversal:<br>
> +  void checkNestedNameSpecifierLoc(<u></u>NestedNameSpecifierLoc NameLoc) {<br>
> +    while (NameLoc) {<br>
> +      const auto *Decl = NameLoc.<u></u>getNestedNameSpecifier()-><u></u>getAsNamespace();<br>
> +      if (Decl && getUSRForDecl(Decl) == USR)<br>
> +        LocationsFound.push_back(<u></u>NameLoc.getLocalBeginLoc());<br>
> +      NameLoc = NameLoc.getPrefix();<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // All the locations of the USR were found.<br>
> +  const std::string USR;<br>
> +  std::vector<clang::<u></u>SourceLocation> LocationsFound;<br>
> +};<br>
> +} // namespace<br>
> +<br>
> +std::vector<SourceLocation> getLocationsOfUSR(const std::string USR,<br>
> +                                              Decl *Decl) {<br>
> +  USRLocFindingASTVisitor visitor(USR);<br>
> +<br>
> +  visitor.TraverseDecl(Decl);<br>
> +  return visitor.getLocationsFound();<br>
> +}<br>
> +<br>
> +} // namespace rename<br>
> +} // namespace clang<br>
><br>
> Added: clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRLocFinder.h?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/clang-rename/<u></u>USRLocFinder.h?rev=215839&<u></u>view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.h (added)<br>
> +++ clang-tools-extra/trunk/clang-<u></u>rename/USRLocFinder.h Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,35 @@<br>
> +//===--- tools/extra/clang-rename/<u></u>USRLocFinder.h - 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>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief Provides functionality for finding all instances of a USR in a given<br>
> +/// AST.<br>
> +///<br>
> +//===------------------------<u></u>------------------------------<u></u>----------------===//<br>
> +<br>
> +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_LOC_FINDER_H<br>
> +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_LOC_FINDER_H<br>
> +<br>
> +#include <string><br>
> +#include <vector><br>
> +<br>
> +namespace clang {<br>
> +<br>
> +class Decl;<br>
> +class SourceLocation;<br>
> +<br>
> +namespace rename {<br>
> +<br>
> +// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!<br>
> +std::vector<SourceLocation> getLocationsOfUSR(const std::string usr,<br>
> +                                              Decl *decl);<br>
> +}<br>
> +}<br>
> +<br>
> +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_<u></u>RENAME_USR_LOC_FINDER_H<br>
><br>
> Modified: clang-tools-extra/trunk/test/<u></u>CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/CMakeLists.txt?rev=215839&r1=215838&r2=215839&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/test/CMakeLists.txt?rev=<u></u>215839&r1=215838&r2=215839&<u></u>view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/test/<u></u>CMakeLists.txt (original)<br>
> +++ clang-tools-extra/trunk/test/<u></u>CMakeLists.txt Sun Aug 17 13:00:59 2014<br>
> @@ -37,6 +37,7 @@ set(CLANG_TOOLS_TEST_DEPS<br>
>    # Individual tools we test.<br>
>    clang-apply-replacements<br>
>    clang-modernize<br>
> +  clang-rename<br>
>    clang-query<br>
>    clang-tidy<br>
>    modularize<br>
><br>
> Added: clang-tools-extra/trunk/test/<u></u>clang-rename/VarTest.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-rename/VarTest.cpp?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/test/clang-rename/<u></u>VarTest.cpp?rev=215839&view=<u></u>auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/test/<u></u>clang-rename/VarTest.cpp (added)<br>
> +++ clang-tools-extra/trunk/test/<u></u>clang-rename/VarTest.cpp Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,24 @@<br>
> +namespace A {<br>
> +int foo;  // CHECK: int hector;<br>
> +}<br>
> +int foo;  // CHECK: int foo;<br>
> +int bar = foo; // CHECK: bar = foo;<br>
> +int baz = A::foo; // CHECK: baz = A::hector;<br>
> +void fun1() {<br>
> +  struct {<br>
> +    int foo; // CHECK: int foo;<br>
> +  } b = { 100 };<br>
> +  int foo = 100; // CHECK: int foo<br>
> +  baz = foo; // CHECK: baz = foo;<br>
> +  {<br>
> +    extern int foo; // CHECK: int foo;<br>
> +    baz = foo; // CHECK: baz = foo;<br>
> +    foo = A::foo + baz; // CHECK: foo = A::hector + baz;<br>
> +    A::foo = b.foo; // CHECK: A::hector = b.foo;<br>
> +  }<br>
> +  foo = b.foo; // CHECK: foo = b.foo;<br>
> +}<br>
> +// REQUIRES: shell<br>
> +// RUN: cat %s > %t.cpp<br>
> +// RUN: clang-rename -offset=$(grep -FUbo 'foo;' %t.cpp | head -1 | cut -d: -f1) -new-name=hector %t.cpp -i --<br>
> +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s<br>
><br>
> Modified: clang-tools-extra/trunk/<u></u>unittests/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/CMakeLists.txt?rev=215839&r1=215838&r2=215839&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/unittests/CMakeLists.<u></u>txt?rev=215839&r1=215838&r2=<u></u>215839&view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/<u></u>unittests/CMakeLists.txt (original)<br>
> +++ clang-tools-extra/trunk/<u></u>unittests/CMakeLists.txt Sun Aug 17 13:00:59 2014<br>
> @@ -7,5 +7,6 @@ endfunction()<br>
><br>
>  add_subdirectory(clang-apply-<u></u>replacements)<br>
>  add_subdirectory(clang-<u></u>modernize)<br>
> +add_subdirectory(clang-<u></u>rename)<br>
>  add_subdirectory(clang-query)<br>
>  add_subdirectory(clang-tidy)<br>
><br>
> Added: clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-rename/CMakeLists.txt?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/unittests/clang-rename/<u></u>CMakeLists.txt?rev=215839&<u></u>view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>CMakeLists.txt (added)<br>
> +++ clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>CMakeLists.txt Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,33 @@<br>
> +set(LLVM_LINK_COMPONENTS<br>
> +  support<br>
> +  )<br>
> +<br>
> +get_filename_component(CLANG_<u></u>RENAME_SOURCE_DIR<br>
> +  ${CMAKE_CURRENT_SOURCE_DIR}/..<u></u>/../clang-rename REALPATH)<br>
> +include_directories(<br>
> +  ${CLANG_RENAME_SOURCE_DIR}<br>
> +  )<br>
> +<br>
> +add_extra_unittest(<u></u>ClangRenameTests<br>
> +  USRLocFindingTest.cpp<br>
> +  ${CLANG_RENAME_SOURCE_DIR}/<u></u>USRFinder.cpp<br>
> +  ${CLANG_RENAME_SOURCE_DIR}/<u></u>USRFindingAction.cpp<br>
> +  )<br>
> +<br>
> +target_link_libraries(<u></u>ClangRenameTests<br>
> +  clangAnalysis<br>
> +  clangAST<br>
> +  clangBasic<br>
> +  clangDriver<br>
> +  clangEdit<br>
> +  clangFrontend<br>
> +  clangFrontendTool<br>
> +  clangIndex<br>
> +  clangLex<br>
> +  clangParse<br>
> +  clangRewrite<br>
> +  clangRewriteFrontend<br>
> +  clangSerialization<br>
> +  clangSema<br>
> +  clangTooling<br>
> +  )<br>
> \ No newline at end of file<br>
><br>
> Added: clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>Makefile<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-rename/Makefile?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/unittests/clang-rename/<u></u>Makefile?rev=215839&view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>Makefile (added)<br>
> +++ clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>Makefile Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,24 @@<br>
> +##===- unittests/clang-rename/<u></u>Makefile ---------------------*- Makefile -*-===##<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>
> +##===------------------------<u></u>------------------------------<u></u>----------------===##<br>
> +<br>
> +CLANG_LEVEL = ../../../..<br>
> +include $(CLANG_LEVEL)/../../Makefile.<u></u>config<br>
> +<br>
> +TESTNAME = ClangRenameTests<br>
> +LINK_COMPONENTS := asmparser bitreader support MC MCParser option \<br>
> +                TransformUtils<br>
> +USEDLIBS = clangAnalysis.a clangAST.a clangBasic.a clangDriver.a clangEdit.a \<br>
> +          clangFrontend.a clangFrontendTool.a clangIndex.a clangLex.a \<br>
> +          clangParse.a clangRewrite.a clangRewriteFrontend.a \<br>
> +          clangSerialization.a clangSema.a clangTooling.a<br>
> +<br>
> +include $(CLANG_LEVEL)/Makefile<br>
> +MAKEFILE_UNITTEST_NO_INCLUDE_<u></u>COMMON := 1<br>
> +CPP.Flags += -I(PROJ_SRC_DIR)/../../clang-<u></u>rename<br>
> +include $(LLVM_SRC_ROOT)/unittests/<u></u>Makefile.unittest<br>
><br>
> Added: clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>USRLocFindingTest.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-rename/USRLocFindingTest.cpp?rev=215839&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/clang-tools-extra/<u></u>trunk/unittests/clang-rename/<u></u>USRLocFindingTest.cpp?rev=<u></u>215839&view=auto</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>USRLocFindingTest.cpp (added)<br>
> +++ clang-tools-extra/trunk/<u></u>unittests/clang-rename/<u></u>USRLocFindingTest.cpp Sun Aug 17 13:00:59 2014<br>
> @@ -0,0 +1,77 @@<br>
> +#include "USRFindingAction.h"<br>
> +#include "gtest/gtest.h"<br>
> +#include "clang/Tooling/Tooling.h"<br>
> +#include <stdio.h><br>
> +#include <set><br>
> +#include <map><br>
> +#include <vector><br>
> +<br>
> +namespace clang {<br>
> +namespace rename {<br>
> +namespace test {<br>
> +<br>
> +// Determines if the symbol group invariants hold. To recap, those invariants<br>
> +// are:<br>
> +//  (1) All symbols in the same symbol group share the same USR.<br>
> +//  (2) Two symbols from two different groups do not share the same USR.<br>
> +static void testOffsetGroups(const char *Code,<br>
> +                             const std::vector<std::vector<<u></u>unsigned>> Groups) {<br>
> +  std::set<std::string> AllUSRs, CurrUSR;<br>
> +<br>
> +  for (const auto &Group : Groups) {<br>
> +    // Groups the invariants do not hold then the value of USR is also invalid,<br>
> +    // but at that point the test has already failed and USR ceases to be<br>
> +    // useful.<br>
> +    std::string USR;<br>
> +    for (const auto &Offset : Group) {<br>
> +      USRFindingAction Action(Offset);<br>
> +      auto Factory = tooling::<u></u>newFrontendActionFactory(&<u></u>Action);<br>
> +      EXPECT_TRUE(tooling::<u></u>runToolOnCode(Factory->create(<u></u>), Code));<br>
> +      const auto &USRs = Action.getUSRs();<br>
> +      EXPECT_EQ(1u, USRs.size());<br>
> +      USR = USRs[0];<br>
> +      CurrUSR.insert(USR);<br>
> +    }<br>
> +    EXPECT_EQ(1u, CurrUSR.size());<br>
> +    CurrUSR.clear();<br>
> +    AllUSRs.insert(USR);<br>
> +  }<br>
> +<br>
> +  EXPECT_EQ(Groups.size(), AllUSRs.size());<br>
> +}<br>
> +<br>
> +<br>
> +TEST(USRLocFinding, FindsVarUSR) {<br>
> +  const char VarTest[] = "\n\<br>
> +namespace A {\n\<br>
> +int foo;\n\<br>
> +}\n\<br>
> +int foo;\n\<br>
> +int bar = foo;\n\<br>
> +int baz = A::foo;\n\<br>
> +void fun1() {\n\<br>
> +  struct {\n\<br>
> +    int foo;\n\<br>
> +  } b = { 100 };\n\<br>
> +  int foo = 100;\n\<br>
> +  baz = foo;\n\<br>
> +  {\n\<br>
> +    extern int foo;\n\<br>
> +    baz = foo;\n\<br>
> +    foo = A::foo + baz;\n\<br>
> +    A::foo = b.foo;\n\<br>
> +  }\n\<br>
> + foo = b.foo;\n\<br>
> +}\n";<br>
> +  std::vector<std::vector<<u></u>unsigned>> VarTestOffsets = {<br>
> +    { 19, 63, 205, 223 },<br>
> +    { 30, 45, 172, 187 },<br>
> +    { 129, 148, 242 },<br>
> +  };<br>
> +<br>
> +  testOffsetGroups(VarTest, VarTestOffsets);<br>
> +}<br>
> +<br>
> +}<br>
> +}<br>
> +}<br>
><br>
><br>
> ______________________________<u></u>_________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-commits</a><br>
</blockquote></div>