blob: c7bf1068fa7c123c2c0d73ff55a5511b4875cc9e [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
Manuel Klimekde237262014-08-20 01:39:05 +000060 // Expression visitors:
61
62 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
63 const auto *Decl = Expr->getFoundDecl();
64
65 checkNestedNameSpecifierLoc(Expr->getQualifierLoc());
66 if (getUSRForDecl(Decl) == USR) {
67 LocationsFound.push_back(Expr->getLocation());
68 }
69
70 return true;
71 }
72
73 bool VisitMemberExpr(const MemberExpr *Expr) {
74 const auto *Decl = Expr->getFoundDecl().getDecl();
75 if (getUSRForDecl(Decl) == USR) {
76 LocationsFound.push_back(Expr->getMemberLoc());
77 }
78 return true;
79 }
80
81 // Non-visitors:
82
83 // \brief Returns a list of unique locations. Duplicate or overlapping
84 // locations are erroneous and should be reported!
85 const std::vector<clang::SourceLocation> &getLocationsFound() const {
86 return LocationsFound;
87 }
88
89private:
90 // Namespace traversal:
91 void checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
92 while (NameLoc) {
93 const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace();
94 if (Decl && getUSRForDecl(Decl) == USR)
95 LocationsFound.push_back(NameLoc.getLocalBeginLoc());
96 NameLoc = NameLoc.getPrefix();
97 }
98 }
99
100 // All the locations of the USR were found.
101 const std::string USR;
102 std::vector<clang::SourceLocation> LocationsFound;
103};
104} // namespace
105
106std::vector<SourceLocation> getLocationsOfUSR(const std::string USR,
107 Decl *Decl) {
108 USRLocFindingASTVisitor visitor(USR);
109
110 visitor.TraverseDecl(Decl);
111 return visitor.getLocationsFound();
112}
113
114} // namespace rename
115} // namespace clang