blob: f2d154eb277ffcc6f3154bf926b0b14df5916859 [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;
Miklos Vajna64776822016-05-11 08:08:07 +000063 if (Initializer->getSourceOrder() == -1) {
64 // Ignore implicit initializers.
65 continue;
66 }
67
Miklos Vajna65f088f2016-05-07 14:32:59 +000068 if (const clang::FieldDecl *FieldDecl = Initializer->getAnyMember()) {
69 if (getUSRForDecl(FieldDecl) == USR) {
70 // The initializer refers to a field that is to be renamed.
71 LocationsFound.push_back(Initializer->getSourceLocation());
72 }
73 }
74 }
75 return true;
76 }
77
Manuel Klimekde237262014-08-20 01:39:05 +000078 // Expression visitors:
79
80 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
81 const auto *Decl = Expr->getFoundDecl();
82
83 checkNestedNameSpecifierLoc(Expr->getQualifierLoc());
84 if (getUSRForDecl(Decl) == USR) {
85 LocationsFound.push_back(Expr->getLocation());
86 }
87
88 return true;
89 }
90
91 bool VisitMemberExpr(const MemberExpr *Expr) {
92 const auto *Decl = Expr->getFoundDecl().getDecl();
93 if (getUSRForDecl(Decl) == USR) {
94 LocationsFound.push_back(Expr->getMemberLoc());
95 }
96 return true;
97 }
98
99 // Non-visitors:
100
101 // \brief Returns a list of unique locations. Duplicate or overlapping
102 // locations are erroneous and should be reported!
103 const std::vector<clang::SourceLocation> &getLocationsFound() const {
104 return LocationsFound;
105 }
106
107private:
108 // Namespace traversal:
109 void checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
110 while (NameLoc) {
111 const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace();
112 if (Decl && getUSRForDecl(Decl) == USR)
113 LocationsFound.push_back(NameLoc.getLocalBeginLoc());
114 NameLoc = NameLoc.getPrefix();
115 }
116 }
117
118 // All the locations of the USR were found.
119 const std::string USR;
120 std::vector<clang::SourceLocation> LocationsFound;
121};
122} // namespace
123
124std::vector<SourceLocation> getLocationsOfUSR(const std::string USR,
125 Decl *Decl) {
126 USRLocFindingASTVisitor visitor(USR);
127
128 visitor.TraverseDecl(Decl);
129 return visitor.getLocationsFound();
130}
131
132} // namespace rename
133} // namespace clang