2014-08-20 09:39:05 +08:00
|
|
|
//===--- 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"
|
2016-05-13 17:17:32 +08:00
|
|
|
#include "clang/Lex/Lexer.h"
|
2014-08-20 09:39:05 +08:00
|
|
|
#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:
|
2016-07-29 18:16:45 +08:00
|
|
|
explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
|
|
|
|
StringRef PrevName,
|
2016-07-22 21:41:09 +08:00
|
|
|
const ASTContext &Context)
|
2016-07-29 18:16:45 +08:00
|
|
|
: USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
|
|
|
|
}
|
2014-08-20 09:39:05 +08:00
|
|
|
|
|
|
|
// Declaration visitors:
|
|
|
|
|
2016-05-07 22:32:59 +08:00
|
|
|
bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
|
2016-08-09 18:03:33 +08:00
|
|
|
for (const auto *Initializer : ConstructorDecl->inits()) {
|
|
|
|
if (!Initializer->isWritten()) {
|
2016-05-11 16:08:07 +08:00
|
|
|
// Ignore implicit initializers.
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-09 15:14:48 +08:00
|
|
|
if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
|
2016-07-29 18:16:45 +08:00
|
|
|
if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end()) {
|
2016-08-09 15:14:48 +08:00
|
|
|
LocationsFound.push_back(Initializer->getSourceLocation());
|
2016-05-07 22:32:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-22 21:41:09 +08:00
|
|
|
bool VisitNamedDecl(const NamedDecl *Decl) {
|
2016-07-29 18:16:45 +08:00
|
|
|
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
|
2016-07-22 21:41:09 +08:00
|
|
|
checkAndAddLocation(Decl->getLocation());
|
2016-06-16 02:35:41 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-20 09:39:05 +08:00
|
|
|
// Expression visitors:
|
|
|
|
|
|
|
|
bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
|
2016-08-16 07:20:05 +08:00
|
|
|
const NamedDecl *Decl = Expr->getFoundDecl();
|
2014-08-20 09:39:05 +08:00
|
|
|
|
2016-07-29 18:16:45 +08:00
|
|
|
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
|
2016-05-25 03:08:53 +08:00
|
|
|
const SourceManager &Manager = Decl->getASTContext().getSourceManager();
|
|
|
|
SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
|
2016-07-22 21:41:09 +08:00
|
|
|
checkAndAddLocation(Location);
|
2014-08-20 09:39:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VisitMemberExpr(const MemberExpr *Expr) {
|
2016-08-16 07:20:05 +08:00
|
|
|
const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
|
2016-07-29 18:16:45 +08:00
|
|
|
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
|
2016-05-20 19:43:59 +08:00
|
|
|
const SourceManager &Manager = Decl->getASTContext().getSourceManager();
|
|
|
|
SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
|
2016-07-22 21:41:09 +08:00
|
|
|
checkAndAddLocation(Location);
|
2016-06-03 04:00:22 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-22 21:41:09 +08:00
|
|
|
// Other visitors:
|
|
|
|
|
|
|
|
bool VisitTypeLoc(const TypeLoc Loc) {
|
2016-07-29 18:16:45 +08:00
|
|
|
if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
|
|
|
|
USRSet.end()) {
|
2016-07-22 21:41:09 +08:00
|
|
|
checkAndAddLocation(Loc.getBeginLoc());
|
|
|
|
}
|
2016-08-02 17:38:38 +08:00
|
|
|
if (const auto *TemplateTypeParm =
|
|
|
|
dyn_cast<TemplateTypeParmType>(Loc.getType())) {
|
|
|
|
if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
|
|
|
|
USRSet.end()) {
|
|
|
|
checkAndAddLocation(Loc.getBeginLoc());
|
|
|
|
}
|
|
|
|
}
|
2016-07-22 21:41:09 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-20 09:39:05 +08:00
|
|
|
// 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:
|
2016-07-22 21:41:09 +08:00
|
|
|
void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
|
2014-08-20 09:39:05 +08:00
|
|
|
while (NameLoc) {
|
2016-08-16 07:20:05 +08:00
|
|
|
const NamespaceDecl *Decl =
|
|
|
|
NameLoc.getNestedNameSpecifier()->getAsNamespace();
|
2016-07-29 18:16:45 +08:00
|
|
|
if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
|
2016-07-22 21:41:09 +08:00
|
|
|
checkAndAddLocation(NameLoc.getLocalBeginLoc());
|
|
|
|
}
|
2014-08-20 09:39:05 +08:00
|
|
|
NameLoc = NameLoc.getPrefix();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-22 21:41:09 +08:00
|
|
|
private:
|
|
|
|
void checkAndAddLocation(SourceLocation Loc) {
|
2016-08-16 07:20:05 +08:00
|
|
|
const SourceLocation BeginLoc = Loc;
|
|
|
|
const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
|
2016-07-29 18:16:45 +08:00
|
|
|
BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
|
2016-07-22 21:41:09 +08:00
|
|
|
StringRef TokenName =
|
|
|
|
Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
|
|
|
|
Context.getSourceManager(), Context.getLangOpts());
|
|
|
|
size_t Offset = TokenName.find(PrevName);
|
|
|
|
if (Offset != StringRef::npos) {
|
|
|
|
// The token of the source location we find actually has the old
|
|
|
|
// name.
|
|
|
|
LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-29 18:16:45 +08:00
|
|
|
const std::set<std::string> USRSet;
|
2016-05-18 02:17:16 +08:00
|
|
|
const std::string PrevName;
|
2014-08-20 09:39:05 +08:00
|
|
|
std::vector<clang::SourceLocation> LocationsFound;
|
2016-07-22 21:41:09 +08:00
|
|
|
const ASTContext &Context;
|
2014-08-20 09:39:05 +08:00
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
2016-07-29 18:16:45 +08:00
|
|
|
std::vector<SourceLocation>
|
|
|
|
getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
|
|
|
|
Decl *Decl) {
|
|
|
|
USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
|
2016-07-15 19:29:16 +08:00
|
|
|
Visitor.TraverseDecl(Decl);
|
2016-07-22 21:41:09 +08:00
|
|
|
NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
|
|
|
|
for (const auto &Location : Finder.getNestedNameSpecifierLocations()) {
|
|
|
|
Visitor.handleNestedNameSpecifierLoc(Location);
|
|
|
|
}
|
2016-07-15 19:29:16 +08:00
|
|
|
return Visitor.getLocationsFound();
|
2014-08-20 09:39:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace rename
|
|
|
|
} // namespace clang
|