clang-tools  3.8.0
USRLocFinder.cpp
Go to the documentation of this file.
1 //===--- 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 
25 using namespace llvm;
26 
27 namespace clang {
28 namespace rename {
29 
30 namespace {
31 // \brief This visitor recursively searches for all instances of a USR in a
32 // translation unit and stores them for later usage.
33 class USRLocFindingASTVisitor
34  : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
35 public:
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 
77 private:
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 
94 std::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
std::string getUSRForDecl(const Decl *Decl)
Definition: USRFinder.cpp:151
const std::string USR
Methods for determining the USR of a symbol at a location in source code.
Provides functionality for finding all instances of a USR in a given AST.
std::vector< clang::SourceLocation > LocationsFound
std::vector< SourceLocation > getLocationsOfUSR(const std::string USR, Decl *Decl)