blob: fc8dfca38a91afb3f517c154deec1d4576aaa066 [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
48 // Expression visitors:
49
50 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
51 const auto *Decl = Expr->getFoundDecl();
52
53 checkNestedNameSpecifierLoc(Expr->getQualifierLoc());
54 if (getUSRForDecl(Decl) == USR) {
55 LocationsFound.push_back(Expr->getLocation());
56 }
57
58 return true;
59 }
60
61 bool VisitMemberExpr(const MemberExpr *Expr) {
62 const auto *Decl = Expr->getFoundDecl().getDecl();
63 if (getUSRForDecl(Decl) == USR) {
64 LocationsFound.push_back(Expr->getMemberLoc());
65 }
66 return true;
67 }
68
69 // Non-visitors:
70
71 // \brief Returns a list of unique locations. Duplicate or overlapping
72 // locations are erroneous and should be reported!
73 const std::vector<clang::SourceLocation> &getLocationsFound() const {
74 return LocationsFound;
75 }
76
77private:
78 // Namespace traversal:
79 void checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
80 while (NameLoc) {
81 const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace();
82 if (Decl && getUSRForDecl(Decl) == USR)
83 LocationsFound.push_back(NameLoc.getLocalBeginLoc());
84 NameLoc = NameLoc.getPrefix();
85 }
86 }
87
88 // All the locations of the USR were found.
89 const std::string USR;
90 std::vector<clang::SourceLocation> LocationsFound;
91};
92} // namespace
93
94std::vector<SourceLocation> getLocationsOfUSR(const std::string USR,
95 Decl *Decl) {
96 USRLocFindingASTVisitor visitor(USR);
97
98 visitor.TraverseDecl(Decl);
99 return visitor.getLocationsFound();
100}
101
102} // namespace rename
103} // namespace clang