Index: clang-rename/USRFinder.h =================================================================== --- clang-rename/USRFinder.h +++ clang-rename/USRFinder.h @@ -25,10 +25,12 @@ 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. +// Given an AST context and a point (or fully qualified name), 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); + const SourceLocation Point, + const std::string &Name); // Converts a Decl into a USR. std::string getUSRForDecl(const Decl *Decl); Index: clang-rename/USRFinder.cpp =================================================================== --- clang-rename/USRFinder.cpp +++ clang-rename/USRFinder.cpp @@ -35,9 +35,10 @@ // \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) + const SourceLocation Point, + const std::string &Name) : Result(nullptr), SourceMgr(SourceMgr), - Point(Point) { + Point(Point), Name(Name) { } // Declaration visitors: @@ -93,9 +94,17 @@ // \returns false on success. bool setResult(const NamedDecl *Decl, SourceLocation Start, SourceLocation End) { - if (!Start.isValid() || !Start.isFileID() || !End.isValid() || - !End.isFileID() || !isPointWithin(Start, End)) { - return true; + if (Name.empty()) { + // Offset is used to find the declaration. + if (!Start.isValid() || !Start.isFileID() || !End.isValid() || + !End.isFileID() || !isPointWithin(Start, End)) { + return true; + } + } else { + // Fully qualified name is used to find the declaration. + if (Name != Decl->getQualifiedNameAsString()) { + return true; + } } Result = Decl; return false; @@ -121,15 +130,17 @@ const NamedDecl *Result; const SourceManager &SourceMgr; const SourceLocation Point; // The location to find the NamedDecl. + const std::string &Name; }; } const NamedDecl *getNamedDeclAt(const ASTContext &Context, - const SourceLocation Point) { + const SourceLocation Point, + const std::string &Name) { const auto &SourceMgr = Context.getSourceManager(); const auto SearchFile = SourceMgr.getFilename(Point); - NamedDeclFindingASTVisitor Visitor(SourceMgr, Point); + NamedDeclFindingASTVisitor Visitor(SourceMgr, Point, Name); // We only want to search the decls that exist in the same file as the point. auto Decls = Context.getTranslationUnitDecl()->decls(); Index: clang-rename/USRFindingAction.h =================================================================== --- clang-rename/USRFindingAction.h +++ clang-rename/USRFindingAction.h @@ -25,7 +25,7 @@ namespace rename { struct USRFindingAction { - USRFindingAction(unsigned Offset) : SymbolOffset(Offset) { + USRFindingAction(unsigned Offset, const std::string &Name) : SymbolOffset(Offset), OldName(Name) { } std::unique_ptr newASTConsumer(); @@ -40,6 +40,7 @@ private: unsigned SymbolOffset; + std::string OldName; std::string SpellingName; std::vector USRs; }; Index: clang-rename/USRFindingAction.cpp =================================================================== --- clang-rename/USRFindingAction.cpp +++ clang-rename/USRFindingAction.cpp @@ -68,7 +68,7 @@ SourceMgr.getMainFileID()).getLocWithOffset(SymbolOffset); if (!Point.isValid()) return; - const NamedDecl *FoundDecl = getNamedDeclAt(Context, Point); + const NamedDecl *FoundDecl = getNamedDeclAt(Context, Point, OldName); if (FoundDecl == nullptr) { FullSourceLoc FullLoc(Point, SourceMgr); errs() << "clang-rename: could not find symbol at " @@ -96,6 +96,7 @@ } unsigned SymbolOffset; + std::string OldName; std::string *SpellingName; std::vector *USRs; }; @@ -106,6 +107,7 @@ new NamedDeclFindingConsumer); SpellingName = ""; Consumer->SymbolOffset = SymbolOffset; + Consumer->OldName = OldName; Consumer->USRs = &USRs; Consumer->SpellingName = &SpellingName; return std::move(Consumer); Index: clang-rename/tool/ClangRename.cpp =================================================================== --- clang-rename/tool/ClangRename.cpp +++ clang-rename/tool/ClangRename.cpp @@ -52,6 +52,11 @@ "offset", cl::desc("Locates the symbol by offset as opposed to :."), cl::cat(ClangRenameCategory)); +static cl::opt +OldName( + "old-name", + cl::desc("The fully qualified name of the symbol, if -offset is not used."), + cl::cat(ClangRenameCategory)); static cl::opt Inplace( "i", @@ -96,7 +101,7 @@ // Get the USRs. auto Files = OP.getSourcePathList(); tooling::RefactoringTool Tool(OP.getCompilations(), Files); - rename::USRFindingAction USRAction(SymbolOffset); + rename::USRFindingAction USRAction(SymbolOffset, OldName); // Find the USRs. Tool.run(tooling::newFrontendActionFactory(&USRAction).get()); Index: test/clang-rename/ClassTestByName.cpp =================================================================== --- /dev/null +++ test/clang-rename/ClassTestByName.cpp @@ -0,0 +1,10 @@ +// RUN: cat %s > %t.cpp +// RUN: clang-rename -old-name=Cla -new-name=Hector %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s +class Cla { // CHECK: class Hector +}; + +int main() { + Cla *Pointer = 0; // CHECK: Hector *Pointer = 0; + return 0; +}