Looks like this is failing on msvc: http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/9983/steps/build_clang_tools/logs/stdio
On 17 August 2014 14:00, Manuel Klimek <[email protected]> wrote: > Author: klimek > Date: Sun Aug 17 13:00:59 2014 > New Revision: 215839 > > URL: http://llvm.org/viewvc/llvm-project?rev=215839&view=rev > Log: > First version of a clang-rename tool. > > Summary: > Note that this code is still grossly under-tested - the next steps will > be to add significantly better test coverage. > > Patch by Matthew Plant. > > Test Plan: > > Reviewers: > > Subscribers: > > Added: > clang-tools-extra/trunk/clang-rename/ > clang-tools-extra/trunk/clang-rename/CMakeLists.txt > clang-tools-extra/trunk/clang-rename/ClangRename.cpp > clang-tools-extra/trunk/clang-rename/Makefile > clang-tools-extra/trunk/clang-rename/RenamingAction.cpp > clang-tools-extra/trunk/clang-rename/RenamingAction.h > clang-tools-extra/trunk/clang-rename/USRFinder.cpp > clang-tools-extra/trunk/clang-rename/USRFinder.h > clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp > clang-tools-extra/trunk/clang-rename/USRFindingAction.h > clang-tools-extra/trunk/clang-rename/USRLocFinder.cpp > clang-tools-extra/trunk/clang-rename/USRLocFinder.h > clang-tools-extra/trunk/test/clang-rename/ > clang-tools-extra/trunk/test/clang-rename/VarTest.cpp > clang-tools-extra/trunk/unittests/clang-rename/ > clang-tools-extra/trunk/unittests/clang-rename/CMakeLists.txt > clang-tools-extra/trunk/unittests/clang-rename/Makefile > clang-tools-extra/trunk/unittests/clang-rename/USRLocFindingTest.cpp > Modified: > clang-tools-extra/trunk/CMakeLists.txt > clang-tools-extra/trunk/Makefile > clang-tools-extra/trunk/test/CMakeLists.txt > clang-tools-extra/trunk/unittests/CMakeLists.txt > > Modified: clang-tools-extra/trunk/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/CMakeLists.txt?rev=215839&r1=215838&r2=215839&view=diff > ============================================================================== > --- clang-tools-extra/trunk/CMakeLists.txt (original) > +++ clang-tools-extra/trunk/CMakeLists.txt Sun Aug 17 13:00:59 2014 > @@ -1,5 +1,6 @@ > add_subdirectory(clang-apply-replacements) > add_subdirectory(clang-modernize) > +add_subdirectory(clang-rename) > add_subdirectory(modularize) > add_subdirectory(module-map-checker) > add_subdirectory(remove-cstr-calls) > > Modified: clang-tools-extra/trunk/Makefile > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/Makefile?rev=215839&r1=215838&r2=215839&view=diff > ============================================================================== > --- clang-tools-extra/trunk/Makefile (original) > +++ clang-tools-extra/trunk/Makefile Sun Aug 17 13:00:59 2014 > @@ -13,8 +13,8 @@ include $(CLANG_LEVEL)/../../Makefile.co > > PARALLEL_DIRS := remove-cstr-calls tool-template modularize \ > module-map-checker pp-trace > -DIRS := clang-apply-replacements clang-modernize clang-tidy clang-query \ > - unittests > +DIRS := clang-apply-replacements clang-modernize clang-rename clang-tidy \ > + clang-query unittests > > include $(CLANG_LEVEL)/Makefile > > > Added: clang-tools-extra/trunk/clang-rename/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/CMakeLists.txt?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/CMakeLists.txt (added) > +++ clang-tools-extra/trunk/clang-rename/CMakeLists.txt Sun Aug 17 13:00:59 > 2014 > @@ -0,0 +1,29 @@ > +set(LLVM_LINK_COMPONENTS support) > + > +add_clang_executable(clang-rename > + ClangRename.cpp > + USRFinder.cpp > + USRFindingAction.cpp > + USRLocFinder.cpp > + RenamingAction.cpp > + ) > + > +target_link_libraries(clang-rename > + clangAnalysis > + clangAST > + clangBasic > + clangDriver > + clangEdit > + clangFrontend > + clangFrontendTool > + clangIndex > + clangLex > + clangParse > + clangRewrite > + clangRewriteFrontend > + clangSerialization > + clangSema > + clangTooling > + ) > + > +install(TARGETS clang-rename RUNTIME DESTINATION bin) > \ No newline at end of file > > Added: clang-tools-extra/trunk/clang-rename/ClangRename.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/ClangRename.cpp?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/ClangRename.cpp (added) > +++ clang-tools-extra/trunk/clang-rename/ClangRename.cpp Sun Aug 17 13:00:59 > 2014 > @@ -0,0 +1,151 @@ > +//===--- tools/extra/clang-rename/ClangRename.cpp - Clang rename tool > -----===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief This file implements a clang-rename tool that automatically finds > and > +/// renames symbols in C++ code. > +/// > +//===----------------------------------------------------------------------===// > + > +#include "USRFindingAction.h" > +#include "RenamingAction.h" > +#include "clang/AST/ASTConsumer.h" > +#include "clang/AST/ASTContext.h" > +#include "clang/Basic/FileManager.h" > +#include "clang/Basic/LangOptions.h" > +#include "clang/Basic/TargetInfo.h" > +#include "clang/Basic/TargetOptions.h" > +#include "clang/Frontend/CommandLineSourceLoc.h" > +#include "clang/Frontend/CompilerInstance.h" > +#include "clang/Frontend/FrontendAction.h" > +#include "clang/Frontend/TextDiagnosticPrinter.h" > +#include "clang/Lex/Preprocessor.h" > +#include "clang/Lex/Lexer.h" > +#include "clang/Parse/Parser.h" > +#include "clang/Parse/ParseAST.h" > +#include "clang/Rewrite/Core/Rewriter.h" > +#include "clang/Tooling/CommonOptionsParser.h" > +#include "clang/Tooling/Refactoring.h" > +#include "clang/Tooling/Tooling.h" > +#include "llvm/ADT/IntrusiveRefCntPtr.h" > +#include "llvm/Support/Host.h" > +#include <stdio.h> > +#include <stdlib.h> > +#include <time.h> > +#include <ctype.h> > +#include <string> > +#include <vector> > + > +using namespace llvm; > + > +cl::OptionCategory ClangRenameCategory("Clang-rename options"); > + > +static cl::opt<std::string> > +NewName( > + "new-name", > + cl::desc("The new name to change the symbol to."), > + cl::cat(ClangRenameCategory)); > +static cl::opt<unsigned> > +SymbolOffset( > + "offset", > + cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), > + cl::cat(ClangRenameCategory)); > +static cl::opt<bool> > +Inplace( > + "i", > + cl::desc("Overwrite edited <file>s."), > + cl::cat(ClangRenameCategory)); > +static cl::opt<bool> > +PrintName( > + "pn", > + cl::desc("Print the found symbol's name prior to renaming to stderr."), > + cl::cat(ClangRenameCategory)); > +static cl::opt<bool> > +PrintLocations( > + "pl", > + cl::desc("Print the locations affected by renaming to stderr."), > + cl::cat(ClangRenameCategory)); > + > +#define CLANG_RENAME_VERSION "0.0.1" > + > +static void PrintVersion() { > + outs() << "clang-rename version " << CLANG_RENAME_VERSION << "\n"; > +} > + > +using namespace clang; > + > +const char RenameUsage[] = "A tool to rename symbols in C/C++ code.\n\ > +clang-rename renames every occurrence of a symbol found at <offset> in\n\ > +<source0>. If -i is specified, the edited files are overwritten to disk.\n\ > +Otherwise, the results are written to stdout.\n"; > + > +int main(int argc, const char **argv) { > + cl::SetVersionPrinter(PrintVersion); > + tooling::CommonOptionsParser OP(argc, argv, ClangRenameCategory, > RenameUsage); > + > + // Check the arguments for correctness. > + > + if (NewName.empty()) { > + errs() << "clang-rename: no new name provided.\n\n"; > + cl::PrintHelpMessage(); > + exit(1); > + } > + > + // Get the USRs. > + auto Files = OP.getSourcePathList(); > + tooling::RefactoringTool Tool(OP.getCompilations(), Files); > + rename::USRFindingAction USRAction(SymbolOffset); > + > + // Find the USRs. > + Tool.run(tooling::newFrontendActionFactory(&USRAction).get()); > + const auto &USRs = USRAction.getUSRs(); > + const auto &PrevName = USRAction.getUSRSpelling(); > + > + if (PrevName.empty()) > + // An error should have already been printed. > + exit(1); > + > + if (PrintName) > + errs() << "clang-rename: found name: " << PrevName; > + > + // Perform the renaming. > + rename::RenamingAction RenameAction(NewName, PrevName, USRs, > + Tool.getReplacements(), > PrintLocations); > + auto Factory = tooling::newFrontendActionFactory(&RenameAction); > + int res; > + > + if (Inplace) { > + res = Tool.runAndSave(Factory.get()); > + } else { > + res = Tool.run(Factory.get()); > + > + // Write every file to stdout. Right now we just barf the files without > any > + // indication of which files start where, other than that we print the > files > + // in the same order we see them. > + LangOptions DefaultLangOptions; > + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = > + new DiagnosticOptions(); > + TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); > + DiagnosticsEngine Diagnostics( > + IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), > + &*DiagOpts, &DiagnosticPrinter, false); > + auto &FileMgr = Tool.getFiles(); > + SourceManager Sources(Diagnostics, FileMgr); > + Rewriter Rewrite(Sources, DefaultLangOptions); > + > + Tool.applyAllReplacements(Rewrite); > + for (const auto &File : Files) { > + const auto *Entry = FileMgr.getFile(File); > + auto ID = Sources.translateFile(Entry); > + Rewrite.getEditBuffer(ID).write(outs()); > + } > + } > + > + exit(res); > +} > > Added: clang-tools-extra/trunk/clang-rename/Makefile > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/Makefile?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/Makefile (added) > +++ clang-tools-extra/trunk/clang-rename/Makefile Sun Aug 17 13:00:59 2014 > @@ -0,0 +1,16 @@ > +##===- tools/extra/clang-rename/Makefile -------------------*- Makefile > -*-===## > +# > +# The LLVM Compiler Infrastructure > +# > +# This file is distributed under the University of Illinois Open Source > +# License. See LICENSE.TXT for details. > +# > +##===----------------------------------------------------------------------===## > + > +CLANG_LEVEL := ../../.. > +TOOLNAME = clang-rename > +include $(CLANG_LEVEL)/../../Makefile.config > + > +DIRS = test > + > +include $(CLANG_LEVEL)/Makefile > > Added: clang-tools-extra/trunk/clang-rename/RenamingAction.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/RenamingAction.cpp?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/RenamingAction.cpp (added) > +++ clang-tools-extra/trunk/clang-rename/RenamingAction.cpp Sun Aug 17 > 13:00:59 2014 > @@ -0,0 +1,90 @@ > +//===--- tools/extra/clang-rename/RenamingAction.cpp - Clang rename tool > --===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief Provides an action to rename every symbol at a point. > +/// > +//===----------------------------------------------------------------------===// > + > +#include "RenamingAction.h" > +#include "USRLocFinder.h" > +#include "clang/AST/ASTConsumer.h" > +#include "clang/AST/ASTContext.h" > +#include "clang/Basic/FileManager.h" > +#include "clang/Frontend/CompilerInstance.h" > +#include "clang/Frontend/FrontendAction.h" > +#include "clang/Lex/Preprocessor.h" > +#include "clang/Lex/Lexer.h" > +#include "clang/Tooling/CommonOptionsParser.h" > +#include "clang/Tooling/Refactoring.h" > +#include "clang/Tooling/Tooling.h" > +#include <stdio.h> > +#include <stdlib.h> > +#include <ctype.h> > +#include <string> > +#include <vector> > + > +using namespace llvm; > + > +namespace clang { > +namespace rename { > + > +class RenamingASTConsumer : public ASTConsumer { > +public: > + RenamingASTConsumer(const std::string &NewName, > + const std::string &PrevName, > + const std::vector<std::string> &USRs, > + tooling::Replacements &Replaces, > + bool PrintLocations) > + : NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces), > + PrintLocations(PrintLocations) { > + } > + > + void HandleTranslationUnit(ASTContext &Context) override { > + const auto &SourceMgr = Context.getSourceManager(); > + std::vector<SourceLocation> RenamingCandidates; > + std::vector<SourceLocation> NewCandidates; > + > + for (const auto &USR : USRs) { > + NewCandidates = getLocationsOfUSR(USR, > Context.getTranslationUnitDecl()); > + RenamingCandidates.insert(RenamingCandidates.end(), > NewCandidates.begin(), > + NewCandidates.end()); > + NewCandidates.clear(); > + } > + > + auto PrevNameLen = PrevName.length(); > + if (PrintLocations) > + for (const auto &Loc : RenamingCandidates) { > + FullSourceLoc FullLoc(Loc, SourceMgr); > + errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc) > + << ":" << FullLoc.getSpellingLineNumber() << ":" > + << FullLoc.getSpellingColumnNumber() << "\n"; > + Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen, > + NewName)); > + } > + else > + for (const auto &Loc : RenamingCandidates) > + Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen, > + NewName)); > + } > + > +private: > + const std::string &NewName, &PrevName; > + const std::vector<std::string> &USRs; > + tooling::Replacements &Replaces; > + bool PrintLocations; > +}; > + > +std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() { > + return llvm::make_unique<RenamingASTConsumer>(NewName, PrevName, USRs, > + Replaces, PrintLocations); > +} > + > +} > +} > > Added: clang-tools-extra/trunk/clang-rename/RenamingAction.h > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/RenamingAction.h?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/RenamingAction.h (added) > +++ clang-tools-extra/trunk/clang-rename/RenamingAction.h Sun Aug 17 13:00:59 > 2014 > @@ -0,0 +1,47 @@ > +//===--- tools/extra/clang-rename/RenamingAction.h - Clang rename tool > ----===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief Provides an action to rename every symbol at a point. > +/// > +//===----------------------------------------------------------------------===// > + > +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H_ > +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H_ > + > +#include "clang/Tooling/Refactoring.h" > + > +namespace clang { > +class ASTConsumer; > +class CompilerInstance; > + > +namespace rename { > + > +class RenamingAction { > +public: > + RenamingAction(const std::string &NewName, const std::string &PrevName, > + const std::vector<std::string> &USRs, > + tooling::Replacements &Replaces, bool PrintLocations = > false) > + : NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces), > + PrintLocations(PrintLocations) { > + } > + > + std::unique_ptr<ASTConsumer> newASTConsumer(); > + > +private: > + const std::string &NewName, &PrevName; > + const std::vector<std::string> &USRs; > + tooling::Replacements &Replaces; > + bool PrintLocations; > +}; > + > +} > +} > + > +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H_ > > Added: clang-tools-extra/trunk/clang-rename/USRFinder.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFinder.cpp?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/USRFinder.cpp (added) > +++ clang-tools-extra/trunk/clang-rename/USRFinder.cpp Sun Aug 17 13:00:59 > 2014 > @@ -0,0 +1,162 @@ > +//===--- tools/extra/clang-rename/USRFinder.cpp - Clang rename tool > -------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file Implements a recursive AST visitor that finds the USR of a symbol > at a > +/// point. > +/// > +//===----------------------------------------------------------------------===// > + > +#include "USRFinder.h" > +#include "clang/AST/AST.h" > +#include "clang/AST/ASTContext.h" > +#include "clang/AST/RecursiveASTVisitor.h" > +#include "clang/Lex/Lexer.h" > +#include "clang/Index/USRGeneration.h" > +#include "llvm/ADT/SmallVector.h" > + > +using namespace llvm; > + > +namespace clang { > +namespace rename { > + > +// NamedDeclFindingASTVisitor recursively visits each AST node to find the > +// symbol underneath the cursor. > +// FIXME: move to seperate .h/.cc file if this gets too large. > +namespace { > +class NamedDeclFindingASTVisitor > + : public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> { > +public: > + // \brief Finds the NamedDecl at a point in the source. > + // \param Point the location in the source to search for the NamedDecl. > + explicit NamedDeclFindingASTVisitor(const SourceManager &SourceMgr, > + const SourceLocation Point) > + : Result(nullptr), SourceMgr(SourceMgr), > + Point(Point) { > + } > + > + // Declaration visitors: > + > + // \brief Checks if the point falls within the NameDecl. This covers every > + // declaration of a named entity that we may come across. Usually, just > + // checking if the point lies within the length of the name of the > declaration > + // and the start location is sufficient. > + bool VisitNamedDecl(const NamedDecl *Decl) { > + return setResult(Decl, Decl->getLocation(), > + Decl->getNameAsString().length()); > + } > + > + // Expression visitors: > + > + bool VisitDeclRefExpr(const DeclRefExpr *Expr) { > + // Check the namespace specifier first. > + if (!checkNestedNameSpecifierLoc(Expr->getQualifierLoc())) > + return false; > + > + const auto *Decl = Expr->getFoundDecl(); > + return setResult(Decl, Expr->getLocation(), > + Decl->getNameAsString().length()); > + } > + > + bool VisitMemberExpr(const MemberExpr *Expr) { > + const auto *Decl = Expr->getFoundDecl().getDecl(); > + return setResult(Decl, Expr->getMemberLoc(), > + Decl->getNameAsString().length()); > + } > + > + // Other: > + > + const NamedDecl *getNamedDecl() { > + return Result; > + } > + > +private: > + // \brief Determines if a namespace qualifier contains the point. > + // \returns false on success and sets Result. > + bool checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) { > + while (NameLoc) { > + const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace(); > + if (Decl && !setResult(Decl, NameLoc.getLocalBeginLoc(), > + Decl->getNameAsString().length())) > + return false; > + NameLoc = NameLoc.getPrefix(); > + } > + return true; > + } > + > + // \brief Sets Result to Decl if the Point is within Start and End. > + // \returns false on success. > + bool setResult(const NamedDecl *Decl, SourceLocation Start, > + SourceLocation End) { > + if (!Start.isValid() || !Start.isFileID() || !End.isValid() || > + !End.isFileID() || !isPointWithin(Start, End)) { > + return true; > + } > + Result = Decl; > + return false; > + } > + > + // \brief Sets Result to Decl if Point is within Loc and Loc + Offset. > + // \returns false on success. > + bool setResult(const NamedDecl *Decl, SourceLocation Loc, > + unsigned Offset) { > + // FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc). > + return Offset == 0 || > + setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1)); > + } > + > + // \brief Determines if the Point is within Start and End. > + bool isPointWithin(const SourceLocation Start, const SourceLocation End) { > + // FIXME: Add tests for Point == End. > + return Point == Start || Point == End || > + (SourceMgr.isBeforeInTranslationUnit(Start, Point) && > + SourceMgr.isBeforeInTranslationUnit(Point, End)); > + } > + > + const NamedDecl *Result; > + const SourceManager &SourceMgr; > + const SourceLocation Point; // The location to find the NamedDecl. > +}; > +} > + > +const NamedDecl *getNamedDeclAt(const ASTContext &Context, > + const SourceLocation Point) { > + const auto &SourceMgr = Context.getSourceManager(); > + const auto SearchFile = SourceMgr.getFilename(Point); > + > + NamedDeclFindingASTVisitor Visitor(SourceMgr, Point); > + > + // We only want to search the decls that exist in the same file as the > point. > + auto Decls = Context.getTranslationUnitDecl()->decls(); > + for (auto &CurrDecl : Decls) { > + const auto FileLoc = CurrDecl->getLocStart(); > + const auto FileName = SourceMgr.getFilename(FileLoc); > + // FIXME: Add test. > + if (FileName == SearchFile) { > + Visitor.TraverseDecl(CurrDecl); > + if (const NamedDecl *Result = Visitor.getNamedDecl()) { > + return Result; > + } > + } > + } > + > + return nullptr; > +} > + > +std::string getUSRForDecl(const Decl *Decl) { > + llvm::SmallVector<char, 128> Buff; > + > + // FIXME: Add test for the nullptr case. > + if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff)) > + return ""; > + > + return std::string(Buff.data(), Buff.size()); > +} > + > +} // namespace clang > +} // namespace rename > > Added: clang-tools-extra/trunk/clang-rename/USRFinder.h > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFinder.h?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/USRFinder.h (added) > +++ clang-tools-extra/trunk/clang-rename/USRFinder.h Sun Aug 17 13:00:59 2014 > @@ -0,0 +1,39 @@ > +//===--- tools/extra/clang-rename/USRFinder.h - Clang rename tool > ---------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief Methods for determining the USR of a symbol at a location in > source > +/// code. > +/// > +//===----------------------------------------------------------------------===// > +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H > +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H > + > +#include <string> > + > +namespace clang { > +class ASTContext; > +class Decl; > +class SourceLocation; > +class NamedDecl; > + > +namespace rename { > + > +// Given an AST context and a point, returns a NamedDecl identifying the > symbol > +// at the point. Returns null if nothing is found at the point. > +const NamedDecl *getNamedDeclAt(const ASTContext &Context, > + const SourceLocation Point); > + > +// Converts a Decl into a USR. > +std::string getUSRForDecl(const Decl *Decl); > + > +} > +} > + > +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H > > Added: clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp (added) > +++ clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp Sun Aug 17 > 13:00:59 2014 > @@ -0,0 +1,118 @@ > +//===--- tools/extra/clang-rename/USRFindingAction.cpp - Clang rename tool > ===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief Provides an action to rename every symbol at a point. > +/// > +//===----------------------------------------------------------------------===// > + > +#include "USRFindingAction.h" > +#include "USRFinder.h" > +#include "clang/AST/AST.h" > +#include "clang/AST/ASTConsumer.h" > +#include "clang/AST/ASTContext.h" > +#include "clang/Basic/FileManager.h" > +#include "clang/Frontend/CompilerInstance.h" > +#include "clang/Frontend/FrontendAction.h" > +#include "clang/Lex/Preprocessor.h" > +#include "clang/Lex/Lexer.h" > +#include "clang/Tooling/CommonOptionsParser.h" > +#include "clang/Tooling/Refactoring.h" > +#include "clang/Tooling/Tooling.h" > +#include <stdio.h> > +#include <stdlib.h> > +#include <ctype.h> > +#include <string> > +#include <vector> > + > +using namespace llvm; > + > +namespace clang { > +namespace rename { > + > +// Get the USRs for the constructors of the class. > +static std::vector<std::string> getAllConstructorUSRs( > + const CXXRecordDecl *Decl) { > + std::vector<std::string> USRs; > + > + // We need to get the definition of the record (as opposed to any forward > + // declarations) in order to find the constructor and destructor. > + const auto *RecordDecl = Decl->getDefinition(); > + > + // Iterate over all the constructors and add their USRs. > + for (const auto &CtorDecl : RecordDecl->ctors()) > + USRs.push_back(getUSRForDecl(CtorDecl)); > + > + // Ignore destructors. GetLocationsOfUSR will find the declaration of and > + // explicit calls to a destructor through TagTypeLoc (and it is better for > the > + // purpose of renaming). > + // > + // For example, in the following code segment, > + // 1 class C { > + // 2 ~C(); > + // 3 }; > + // At line 3, there is a NamedDecl starting from '~' and a TagTypeLoc > starting > + // from 'C'. > + > + return USRs; > +} > + > +struct NamedDeclFindingConsumer : public ASTConsumer { > + void HandleTranslationUnit(ASTContext &Context) override { > + const auto &SourceMgr = Context.getSourceManager(); > + // The file we look for the USR in will always be the main source file. > + const auto Point = SourceMgr.getLocForStartOfFile( > + SourceMgr.getMainFileID()).getLocWithOffset(SymbolOffset); > + if (!Point.isValid()) > + return; > + const NamedDecl *FoundDecl = getNamedDeclAt(Context, Point); > + if (FoundDecl == nullptr) { > + FullSourceLoc FullLoc(Point, SourceMgr); > + errs() << "clang-rename: could not find symbol at " > + << SourceMgr.getFilename(Point) << ":" > + << FullLoc.getSpellingLineNumber() << ":" > + << FullLoc.getSpellingColumnNumber() << " (offset " << > SymbolOffset > + << ").\n"; > + return; > + } > + > + // If the decl is a constructor or destructor, we want to instead take > the > + // decl of the parent record. > + if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl)) > + FoundDecl = CtorDecl->getParent(); > + else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl)) > + FoundDecl = DtorDecl->getParent(); > + > + // If the decl is in any way relatedpp to a class, we want to make sure > we > + // search for the constructor and destructor as well as everything else. > + if (const auto *Record = dyn_cast<CXXRecordDecl>(FoundDecl)) > + *USRs = getAllConstructorUSRs(Record); > + > + USRs->push_back(getUSRForDecl(FoundDecl)); > + *SpellingName = FoundDecl->getNameAsString(); > + } > + > + unsigned SymbolOffset; > + std::string *SpellingName; > + std::vector<std::string> *USRs; > +}; > + > +std::unique_ptr<ASTConsumer> > +USRFindingAction::newASTConsumer() { > + std::unique_ptr<NamedDeclFindingConsumer> Consumer( > + new NamedDeclFindingConsumer); > + SpellingName = ""; > + Consumer->SymbolOffset = SymbolOffset; > + Consumer->USRs = &USRs; > + Consumer->SpellingName = &SpellingName; > + return std::move(Consumer); > +} > + > +} // namespace rename > +} // namespace clang > > Added: clang-tools-extra/trunk/clang-rename/USRFindingAction.h > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFindingAction.h?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/USRFindingAction.h (added) > +++ clang-tools-extra/trunk/clang-rename/USRFindingAction.h Sun Aug 17 > 13:00:59 2014 > @@ -0,0 +1,50 @@ > +//===--- tools/extra/clang-rename/USRFindingAction.h - Clang rename tool > --===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief Provides an action to find all relevent USRs at a point. > +/// > +//===----------------------------------------------------------------------===// > + > +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H_ > +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H_ > + > +#include "clang/Frontend/FrontendAction.h" > + > +namespace clang { > +class ASTConsumer; > +class CompilerInstance; > +class NamedDecl; > + > +namespace rename { > + > +struct USRFindingAction { > + USRFindingAction(unsigned Offset) : SymbolOffset(Offset) { > + } > + std::unique_ptr<ASTConsumer> newASTConsumer(); > + > + // \brief get the spelling of the USR(s) as it would appear in source > files. > + const std::string &getUSRSpelling() { > + return SpellingName; > + } > + > + const std::vector<std::string> &getUSRs() { > + return USRs; > + } > + > +private: > + unsigned SymbolOffset; > + std::string SpellingName; > + std::vector<std::string> USRs; > +}; > + > +} > +} > + > +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H_ > > Added: clang-tools-extra/trunk/clang-rename/USRLocFinder.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRLocFinder.cpp?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/USRLocFinder.cpp (added) > +++ clang-tools-extra/trunk/clang-rename/USRLocFinder.cpp Sun Aug 17 13:00:59 > 2014 > @@ -0,0 +1,103 @@ > +//===--- tools/extra/clang-rename/USRLocFinder.cpp - Clang rename tool > ----===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief Mehtods for finding all instances of a USR. Our strategy is very > +/// simple; we just compare the USR at every relevant AST node with the one > +/// provided. > +/// > +//===----------------------------------------------------------------------===// > + > +#include "USRLocFinder.h" > +#include "USRFinder.h" > +#include "clang/AST/ASTContext.h" > +#include "clang/AST/RecursiveASTVisitor.h" > +#include "clang/Basic/SourceLocation.h" > +#include "clang/Index/USRGeneration.h" > +#include "llvm/ADT/SmallVector.h" > + > +using namespace llvm; > + > +namespace clang { > +namespace rename { > + > +namespace { > +// \brief This visitor recursively searches for all instances of a USR in a > +// translation unit and stores them for later usage. > +class USRLocFindingASTVisitor > + : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> { > +public: > + explicit USRLocFindingASTVisitor(const std::string USR) : USR(USR) { > + } > + > + // Declaration visitors: > + > + bool VisitNamedDecl(const NamedDecl *Decl) { > + if (getUSRForDecl(Decl) == USR) { > + LocationsFound.push_back(Decl->getLocation()); > + } > + return true; > + } > + > + // Expression visitors: > + > + bool VisitDeclRefExpr(const DeclRefExpr *Expr) { > + const auto *Decl = Expr->getFoundDecl(); > + > + checkNestedNameSpecifierLoc(Expr->getQualifierLoc()); > + if (getUSRForDecl(Decl) == USR) { > + LocationsFound.push_back(Expr->getLocation()); > + } > + > + return true; > + } > + > + bool VisitMemberExpr(const MemberExpr *Expr) { > + const auto *Decl = Expr->getFoundDecl().getDecl(); > + if (getUSRForDecl(Decl) == USR) { > + LocationsFound.push_back(Expr->getMemberLoc()); > + } > + return true; > + } > + > + // Non-visitors: > + > + // \brief Returns a list of unique locations. Duplicate or overlapping > + // locations are erroneous and should be reported! > + const std::vector<clang::SourceLocation> &getLocationsFound() const { > + return LocationsFound; > + } > + > +private: > + // Namespace traversal: > + void checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) { > + while (NameLoc) { > + const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace(); > + if (Decl && getUSRForDecl(Decl) == USR) > + LocationsFound.push_back(NameLoc.getLocalBeginLoc()); > + NameLoc = NameLoc.getPrefix(); > + } > + } > + > + // All the locations of the USR were found. > + const std::string USR; > + std::vector<clang::SourceLocation> LocationsFound; > +}; > +} // namespace > + > +std::vector<SourceLocation> getLocationsOfUSR(const std::string USR, > + Decl *Decl) { > + USRLocFindingASTVisitor visitor(USR); > + > + visitor.TraverseDecl(Decl); > + return visitor.getLocationsFound(); > +} > + > +} // namespace rename > +} // namespace clang > > Added: clang-tools-extra/trunk/clang-rename/USRLocFinder.h > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRLocFinder.h?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/clang-rename/USRLocFinder.h (added) > +++ clang-tools-extra/trunk/clang-rename/USRLocFinder.h Sun Aug 17 13:00:59 > 2014 > @@ -0,0 +1,35 @@ > +//===--- tools/extra/clang-rename/USRLocFinder.h - Clang rename tool > ------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +/// > +/// \file > +/// \brief Provides functionality for finding all instances of a USR in a > given > +/// AST. > +/// > +//===----------------------------------------------------------------------===// > + > +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H > +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H > + > +#include <string> > +#include <vector> > + > +namespace clang { > + > +class Decl; > +class SourceLocation; > + > +namespace rename { > + > +// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree! > +std::vector<SourceLocation> getLocationsOfUSR(const std::string usr, > + Decl *decl); > +} > +} > + > +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H > > Modified: clang-tools-extra/trunk/test/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/CMakeLists.txt?rev=215839&r1=215838&r2=215839&view=diff > ============================================================================== > --- clang-tools-extra/trunk/test/CMakeLists.txt (original) > +++ clang-tools-extra/trunk/test/CMakeLists.txt Sun Aug 17 13:00:59 2014 > @@ -37,6 +37,7 @@ set(CLANG_TOOLS_TEST_DEPS > # Individual tools we test. > clang-apply-replacements > clang-modernize > + clang-rename > clang-query > clang-tidy > modularize > > Added: clang-tools-extra/trunk/test/clang-rename/VarTest.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-rename/VarTest.cpp?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/test/clang-rename/VarTest.cpp (added) > +++ clang-tools-extra/trunk/test/clang-rename/VarTest.cpp Sun Aug 17 13:00:59 > 2014 > @@ -0,0 +1,24 @@ > +namespace A { > +int foo; // CHECK: int hector; > +} > +int foo; // CHECK: int foo; > +int bar = foo; // CHECK: bar = foo; > +int baz = A::foo; // CHECK: baz = A::hector; > +void fun1() { > + struct { > + int foo; // CHECK: int foo; > + } b = { 100 }; > + int foo = 100; // CHECK: int foo > + baz = foo; // CHECK: baz = foo; > + { > + extern int foo; // CHECK: int foo; > + baz = foo; // CHECK: baz = foo; > + foo = A::foo + baz; // CHECK: foo = A::hector + baz; > + A::foo = b.foo; // CHECK: A::hector = b.foo; > + } > + foo = b.foo; // CHECK: foo = b.foo; > +} > +// REQUIRES: shell > +// RUN: cat %s > %t.cpp > +// RUN: clang-rename -offset=$(grep -FUbo 'foo;' %t.cpp | head -1 | cut -d: > -f1) -new-name=hector %t.cpp -i -- > +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s > > Modified: clang-tools-extra/trunk/unittests/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/CMakeLists.txt?rev=215839&r1=215838&r2=215839&view=diff > ============================================================================== > --- clang-tools-extra/trunk/unittests/CMakeLists.txt (original) > +++ clang-tools-extra/trunk/unittests/CMakeLists.txt Sun Aug 17 13:00:59 2014 > @@ -7,5 +7,6 @@ endfunction() > > add_subdirectory(clang-apply-replacements) > add_subdirectory(clang-modernize) > +add_subdirectory(clang-rename) > add_subdirectory(clang-query) > add_subdirectory(clang-tidy) > > Added: clang-tools-extra/trunk/unittests/clang-rename/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-rename/CMakeLists.txt?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/unittests/clang-rename/CMakeLists.txt (added) > +++ clang-tools-extra/trunk/unittests/clang-rename/CMakeLists.txt Sun Aug 17 > 13:00:59 2014 > @@ -0,0 +1,33 @@ > +set(LLVM_LINK_COMPONENTS > + support > + ) > + > +get_filename_component(CLANG_RENAME_SOURCE_DIR > + ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-rename REALPATH) > +include_directories( > + ${CLANG_RENAME_SOURCE_DIR} > + ) > + > +add_extra_unittest(ClangRenameTests > + USRLocFindingTest.cpp > + ${CLANG_RENAME_SOURCE_DIR}/USRFinder.cpp > + ${CLANG_RENAME_SOURCE_DIR}/USRFindingAction.cpp > + ) > + > +target_link_libraries(ClangRenameTests > + clangAnalysis > + clangAST > + clangBasic > + clangDriver > + clangEdit > + clangFrontend > + clangFrontendTool > + clangIndex > + clangLex > + clangParse > + clangRewrite > + clangRewriteFrontend > + clangSerialization > + clangSema > + clangTooling > + ) > \ No newline at end of file > > Added: clang-tools-extra/trunk/unittests/clang-rename/Makefile > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-rename/Makefile?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/unittests/clang-rename/Makefile (added) > +++ clang-tools-extra/trunk/unittests/clang-rename/Makefile Sun Aug 17 > 13:00:59 2014 > @@ -0,0 +1,24 @@ > +##===- unittests/clang-rename/Makefile ---------------------*- Makefile > -*-===## > +# > +# The LLVM Compiler Infrastructure > +# > +# This file is distributed under the University of Illinois Open Source > +# License. See LICENSE.TXT for details. > +# > +##===----------------------------------------------------------------------===## > + > +CLANG_LEVEL = ../../../.. > +include $(CLANG_LEVEL)/../../Makefile.config > + > +TESTNAME = ClangRenameTests > +LINK_COMPONENTS := asmparser bitreader support MC MCParser option \ > + TransformUtils > +USEDLIBS = clangAnalysis.a clangAST.a clangBasic.a clangDriver.a clangEdit.a > \ > + clangFrontend.a clangFrontendTool.a clangIndex.a clangLex.a \ > + clangParse.a clangRewrite.a clangRewriteFrontend.a \ > + clangSerialization.a clangSema.a clangTooling.a > + > +include $(CLANG_LEVEL)/Makefile > +MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1 > +CPP.Flags += -I(PROJ_SRC_DIR)/../../clang-rename > +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest > > Added: clang-tools-extra/trunk/unittests/clang-rename/USRLocFindingTest.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-rename/USRLocFindingTest.cpp?rev=215839&view=auto > ============================================================================== > --- clang-tools-extra/trunk/unittests/clang-rename/USRLocFindingTest.cpp > (added) > +++ clang-tools-extra/trunk/unittests/clang-rename/USRLocFindingTest.cpp Sun > Aug 17 13:00:59 2014 > @@ -0,0 +1,77 @@ > +#include "USRFindingAction.h" > +#include "gtest/gtest.h" > +#include "clang/Tooling/Tooling.h" > +#include <stdio.h> > +#include <set> > +#include <map> > +#include <vector> > + > +namespace clang { > +namespace rename { > +namespace test { > + > +// Determines if the symbol group invariants hold. To recap, those invariants > +// are: > +// (1) All symbols in the same symbol group share the same USR. > +// (2) Two symbols from two different groups do not share the same USR. > +static void testOffsetGroups(const char *Code, > + const std::vector<std::vector<unsigned>> > Groups) { > + std::set<std::string> AllUSRs, CurrUSR; > + > + for (const auto &Group : Groups) { > + // Groups the invariants do not hold then the value of USR is also > invalid, > + // but at that point the test has already failed and USR ceases to be > + // useful. > + std::string USR; > + for (const auto &Offset : Group) { > + USRFindingAction Action(Offset); > + auto Factory = tooling::newFrontendActionFactory(&Action); > + EXPECT_TRUE(tooling::runToolOnCode(Factory->create(), Code)); > + const auto &USRs = Action.getUSRs(); > + EXPECT_EQ(1u, USRs.size()); > + USR = USRs[0]; > + CurrUSR.insert(USR); > + } > + EXPECT_EQ(1u, CurrUSR.size()); > + CurrUSR.clear(); > + AllUSRs.insert(USR); > + } > + > + EXPECT_EQ(Groups.size(), AllUSRs.size()); > +} > + > + > +TEST(USRLocFinding, FindsVarUSR) { > + const char VarTest[] = "\n\ > +namespace A {\n\ > +int foo;\n\ > +}\n\ > +int foo;\n\ > +int bar = foo;\n\ > +int baz = A::foo;\n\ > +void fun1() {\n\ > + struct {\n\ > + int foo;\n\ > + } b = { 100 };\n\ > + int foo = 100;\n\ > + baz = foo;\n\ > + {\n\ > + extern int foo;\n\ > + baz = foo;\n\ > + foo = A::foo + baz;\n\ > + A::foo = b.foo;\n\ > + }\n\ > + foo = b.foo;\n\ > +}\n"; > + std::vector<std::vector<unsigned>> VarTestOffsets = { > + { 19, 63, 205, 223 }, > + { 30, 45, 172, 187 }, > + { 129, 148, 242 }, > + }; > + > + testOffsetGroups(VarTest, VarTestOffsets); > +} > + > +} > +} > +} > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
