blob: acb47bb41f6353da7fa6ee0414884d697faf870a [file] [log] [blame]
Manuel Klimekde237262014-08-20 01:39:05 +00001//===--- tools/extra/clang-rename/USRLocFinder.cpp - Clang rename tool ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Mehtods for finding all instances of a USR. Our strategy is very
12/// simple; we just compare the USR at every relevant AST node with the one
13/// provided.
14///
15//===----------------------------------------------------------------------===//
16
17#include "USRLocFinder.h"
18#include "USRFinder.h"
19#include "clang/AST/ASTContext.h"
20#include "clang/AST/RecursiveASTVisitor.h"
21#include "clang/Basic/SourceLocation.h"
22#include "clang/Index/USRGeneration.h"
23#include "llvm/ADT/SmallVector.h"
24
25using namespace llvm;
26
27namespace clang {
28namespace rename {
29
30namespace {
31// \brief This visitor recursively searches for all instances of a USR in a
32// translation unit and stores them for later usage.
33class USRLocFindingASTVisitor
34 : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
35public:
36 explicit USRLocFindingASTVisitor(const std::string USR) : USR(USR) {
37 }
38
39 // Declaration visitors:
40
41 bool VisitNamedDecl(const NamedDecl *Decl) {
42 if (getUSRForDecl(Decl) == USR) {
43 LocationsFound.push_back(Decl->getLocation());
44 }
45 return true;
46 }
47
Manuel Klimek13e2c1a2016-05-04 09:45:44 +000048 bool VisitVarDecl(clang::VarDecl *Decl) {
49 clang::QualType Type = Decl->getType();
50 const clang::RecordDecl *RecordDecl = Type->getPointeeCXXRecordDecl();
51 if (RecordDecl) {
52 if (getUSRForDecl(RecordDecl) == USR) {
53 // The declaration refers to a type that is to be renamed.
54 LocationsFound.push_back(Decl->getTypeSpecStartLoc());
55 }
56 }
57 return true;
58 }
59
Miklos Vajna65f088f2016-05-07 14:32:59 +000060 bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
61 for (clang::CXXConstructorDecl::init_const_iterator it = ConstructorDecl->init_begin(); it != ConstructorDecl->init_end(); ++it) {
62 const clang::CXXCtorInitializer* Initializer = *it;
63 if (const clang::FieldDecl *FieldDecl = Initializer->getAnyMember()) {
64 if (getUSRForDecl(FieldDecl) == USR) {
65 // The initializer refers to a field that is to be renamed.
66 LocationsFound.push_back(Initializer->getSourceLocation());
67 }
68 }
69 }
70 return true;
71 }
72
Manuel Klimekde237262014-08-20 01:39:05 +000073 // Expression visitors:
74
75 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
76 const auto *Decl = Expr->getFoundDecl();
77
78 checkNestedNameSpecifierLoc(Expr->getQualifierLoc());
79 if (getUSRForDecl(Decl) == USR) {
80 LocationsFound.push_back(Expr->getLocation());
81 }
82
83 return true;
84 }
85
86 bool VisitMemberExpr(const MemberExpr *Expr) {
87 const auto *Decl = Expr->getFoundDecl().getDecl();
88 if (getUSRForDecl(Decl) == USR) {
89 LocationsFound.push_back(Expr->getMemberLoc());
90 }
91 return true;
92 }
93
94 // Non-visitors:
95
96 // \brief Returns a list of unique locations. Duplicate or overlapping
97 // locations are erroneous and should be reported!
98 const std::vector<clang::SourceLocation> &getLocationsFound() const {
99 return LocationsFound;
100 }
101
102private:
103 // Namespace traversal:
104 void checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
105 while (NameLoc) {
106 const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace();
107 if (Decl && getUSRForDecl(Decl) == USR)
108 LocationsFound.push_back(NameLoc.getLocalBeginLoc());
109 NameLoc = NameLoc.getPrefix();
110 }
111 }
112
113 // All the locations of the USR were found.
114 const std::string USR;
115 std::vector<clang::SourceLocation> LocationsFound;
116};
117} // namespace
118
119std::vector<SourceLocation> getLocationsOfUSR(const std::string USR,
120 Decl *Decl) {
121 USRLocFindingASTVisitor visitor(USR);
122
123 visitor.TraverseDecl(Decl);
124 return visitor.getLocationsFound();
125}
126
127} // namespace rename
128} // namespace clang