1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
//===--- tools/extra/clang-rename/USRLocFinder.cpp - Clang rename tool ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Mehtods for finding all instances of a USR. Our strategy is very
/// simple; we just compare the USR at every relevant AST node with the one
/// provided.
///
//===----------------------------------------------------------------------===//
#include "USRLocFinder.h"
#include "USRFinder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include <cstddef>
#include <set>
#include <string>
#include <vector>
using namespace llvm;
namespace clang {
namespace rename {
namespace {
// \brief This visitor recursively searches for all instances of a USR in a
// translation unit and stores them for later usage.
class USRLocFindingASTVisitor
: public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
public:
explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
StringRef PrevName,
const ASTContext &Context)
: USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
}
// Declaration visitors:
bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
for (const auto *Initializer : ConstructorDecl->inits()) {
// Ignore implicit initializers.
if (!Initializer->isWritten())
continue;
if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end())
LocationsFound.push_back(Initializer->getSourceLocation());
}
}
return true;
}
bool VisitNamedDecl(const NamedDecl *Decl) {
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
checkAndAddLocation(Decl->getLocation());
return true;
}
// Expression visitors:
bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
const NamedDecl *Decl = Expr->getFoundDecl();
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
const SourceManager &Manager = Decl->getASTContext().getSourceManager();
SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
checkAndAddLocation(Location);
}
return true;
}
bool VisitMemberExpr(const MemberExpr *Expr) {
const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
const SourceManager &Manager = Decl->getASTContext().getSourceManager();
SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
checkAndAddLocation(Location);
}
return true;
}
// Other visitors:
bool VisitTypeLoc(const TypeLoc Loc) {
if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
USRSet.end())
checkAndAddLocation(Loc.getBeginLoc());
if (const auto *TemplateTypeParm =
dyn_cast<TemplateTypeParmType>(Loc.getType())) {
if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
USRSet.end())
checkAndAddLocation(Loc.getBeginLoc());
}
return true;
}
// Non-visitors:
// \brief Returns a list of unique locations. Duplicate or overlapping
// locations are erroneous and should be reported!
const std::vector<clang::SourceLocation> &getLocationsFound() const {
return LocationsFound;
}
// Namespace traversal:
void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
while (NameLoc) {
const NamespaceDecl *Decl =
NameLoc.getNestedNameSpecifier()->getAsNamespace();
if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
checkAndAddLocation(NameLoc.getLocalBeginLoc());
NameLoc = NameLoc.getPrefix();
}
}
private:
void checkAndAddLocation(SourceLocation Loc) {
const SourceLocation BeginLoc = Loc;
const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
StringRef TokenName =
Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
Context.getSourceManager(), Context.getLangOpts());
size_t Offset = TokenName.find(PrevName);
// The token of the source location we find actually has the old
// name.
if (Offset != StringRef::npos)
LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
}
const std::set<std::string> USRSet;
const std::string PrevName;
std::vector<clang::SourceLocation> LocationsFound;
const ASTContext &Context;
};
} // namespace
std::vector<SourceLocation>
getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
Decl *Decl) {
USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
Visitor.TraverseDecl(Decl);
NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
for (const auto &Location : Finder.getNestedNameSpecifierLocations())
Visitor.handleNestedNameSpecifierLoc(Location);
return Visitor.getLocationsFound();
}
} // namespace rename
} // namespace clang
|