blob: 60bc1c27c07efcff485420c7a1f20046ed83fdf3 [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"
Miklos Vajna1d48e502016-05-13 09:17:32 +000023#include "clang/Lex/Lexer.h"
Manuel Klimekde237262014-08-20 01:39:05 +000024#include "llvm/ADT/SmallVector.h"
25
26using namespace llvm;
27
28namespace clang {
29namespace rename {
30
31namespace {
32// \brief This visitor recursively searches for all instances of a USR in a
33// translation unit and stores them for later usage.
34class USRLocFindingASTVisitor
35 : public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
36public:
Kirill Bobyrev83d5d562016-07-29 10:16:45 +000037 explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
38 StringRef PrevName,
Kirill Bobyreva3432fa2016-07-22 13:41:09 +000039 const ASTContext &Context)
Kirill Bobyrev83d5d562016-07-29 10:16:45 +000040 : USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
41 }
Manuel Klimekde237262014-08-20 01:39:05 +000042
43 // Declaration visitors:
44
Miklos Vajna65f088f2016-05-07 14:32:59 +000045 bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
Kirill Bobyrev7fa33952016-08-09 10:03:33 +000046 for (const auto *Initializer : ConstructorDecl->inits()) {
Kirill Bobyrev87697782016-09-04 22:50:41 +000047 // Ignore implicit initializers.
48 if (!Initializer->isWritten())
Miklos Vajna64776822016-05-11 08:08:07 +000049 continue;
Kirill Bobyrev31fd7fb2016-08-09 07:14:48 +000050 if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
Kirill Bobyrev87697782016-09-04 22:50:41 +000051 if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end())
Kirill Bobyrev31fd7fb2016-08-09 07:14:48 +000052 LocationsFound.push_back(Initializer->getSourceLocation());
Miklos Vajna65f088f2016-05-07 14:32:59 +000053 }
54 }
55 return true;
56 }
57
Kirill Bobyreva3432fa2016-07-22 13:41:09 +000058 bool VisitNamedDecl(const NamedDecl *Decl) {
Kirill Bobyrev87697782016-09-04 22:50:41 +000059 if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
Kirill Bobyreva3432fa2016-07-22 13:41:09 +000060 checkAndAddLocation(Decl->getLocation());
Miklos Vajna7712bf32016-06-15 18:35:41 +000061 return true;
62 }
63
Manuel Klimekde237262014-08-20 01:39:05 +000064 // Expression visitors:
65
66 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
Kirill Bobyrev6b7d8c22016-08-15 23:20:05 +000067 const NamedDecl *Decl = Expr->getFoundDecl();
Manuel Klimekde237262014-08-20 01:39:05 +000068
Kirill Bobyrev83d5d562016-07-29 10:16:45 +000069 if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
Miklos Vajna10e25742016-05-24 19:08:53 +000070 const SourceManager &Manager = Decl->getASTContext().getSourceManager();
71 SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
Kirill Bobyreva3432fa2016-07-22 13:41:09 +000072 checkAndAddLocation(Location);
Manuel Klimekde237262014-08-20 01:39:05 +000073 }
74
75 return true;
76 }
77
78 bool VisitMemberExpr(const MemberExpr *Expr) {
Kirill Bobyrev6b7d8c22016-08-15 23:20:05 +000079 const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
Kirill Bobyrev83d5d562016-07-29 10:16:45 +000080 if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
Miklos Vajnaed28d412016-05-20 11:43:59 +000081 const SourceManager &Manager = Decl->getASTContext().getSourceManager();
82 SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
Kirill Bobyreva3432fa2016-07-22 13:41:09 +000083 checkAndAddLocation(Location);
Manuel Klimekde237262014-08-20 01:39:05 +000084 }
85 return true;
86 }
87
Kirill Bobyreva3432fa2016-07-22 13:41:09 +000088 // Other visitors:
89
90 bool VisitTypeLoc(const TypeLoc Loc) {
Kirill Bobyrev83d5d562016-07-29 10:16:45 +000091 if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
Kirill Bobyrev87697782016-09-04 22:50:41 +000092 USRSet.end())
Kirill Bobyreva3432fa2016-07-22 13:41:09 +000093 checkAndAddLocation(Loc.getBeginLoc());
Kirill Bobyrev9e0dab92016-08-02 09:38:38 +000094 if (const auto *TemplateTypeParm =
95 dyn_cast<TemplateTypeParmType>(Loc.getType())) {
96 if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
Kirill Bobyrev87697782016-09-04 22:50:41 +000097 USRSet.end())
Kirill Bobyrev9e0dab92016-08-02 09:38:38 +000098 checkAndAddLocation(Loc.getBeginLoc());
Kirill Bobyrev9e0dab92016-08-02 09:38:38 +000099 }
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000100 return true;
101 }
102
Manuel Klimekde237262014-08-20 01:39:05 +0000103 // Non-visitors:
104
105 // \brief Returns a list of unique locations. Duplicate or overlapping
106 // locations are erroneous and should be reported!
107 const std::vector<clang::SourceLocation> &getLocationsFound() const {
108 return LocationsFound;
109 }
110
Manuel Klimekde237262014-08-20 01:39:05 +0000111 // Namespace traversal:
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000112 void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
Manuel Klimekde237262014-08-20 01:39:05 +0000113 while (NameLoc) {
Kirill Bobyrev6b7d8c22016-08-15 23:20:05 +0000114 const NamespaceDecl *Decl =
115 NameLoc.getNestedNameSpecifier()->getAsNamespace();
Kirill Bobyrev87697782016-09-04 22:50:41 +0000116 if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000117 checkAndAddLocation(NameLoc.getLocalBeginLoc());
Manuel Klimekde237262014-08-20 01:39:05 +0000118 NameLoc = NameLoc.getPrefix();
119 }
120 }
121
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000122private:
123 void checkAndAddLocation(SourceLocation Loc) {
Kirill Bobyrev6b7d8c22016-08-15 23:20:05 +0000124 const SourceLocation BeginLoc = Loc;
125 const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
Kirill Bobyrev83d5d562016-07-29 10:16:45 +0000126 BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000127 StringRef TokenName =
128 Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
129 Context.getSourceManager(), Context.getLangOpts());
130 size_t Offset = TokenName.find(PrevName);
Kirill Bobyrev87697782016-09-04 22:50:41 +0000131
132 // The token of the source location we find actually has the old
133 // name.
134 if (Offset != StringRef::npos)
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000135 LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000136 }
137
Kirill Bobyrev83d5d562016-07-29 10:16:45 +0000138 const std::set<std::string> USRSet;
Miklos Vajnaa7445f12016-05-17 18:17:16 +0000139 const std::string PrevName;
Manuel Klimekde237262014-08-20 01:39:05 +0000140 std::vector<clang::SourceLocation> LocationsFound;
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000141 const ASTContext &Context;
Manuel Klimekde237262014-08-20 01:39:05 +0000142};
143} // namespace
144
Kirill Bobyrev83d5d562016-07-29 10:16:45 +0000145std::vector<SourceLocation>
146getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
147 Decl *Decl) {
148 USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
Kirill Bobyrev32db7692016-07-15 11:29:16 +0000149 Visitor.TraverseDecl(Decl);
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000150 NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
Kirill Bobyrev87697782016-09-04 22:50:41 +0000151
152 for (const auto &Location : Finder.getNestedNameSpecifierLocations())
Kirill Bobyreva3432fa2016-07-22 13:41:09 +0000153 Visitor.handleNestedNameSpecifierLoc(Location);
Kirill Bobyrev87697782016-09-04 22:50:41 +0000154
Kirill Bobyrev32db7692016-07-15 11:29:16 +0000155 return Visitor.getLocationsFound();
Manuel Klimekde237262014-08-20 01:39:05 +0000156}
157
158} // namespace rename
159} // namespace clang