clang 8.0.0

USRLocFinder.cpp
Go to the documentation of this file.
1 //===--- USRLocFinder.cpp - Clang refactoring library ---------------------===//
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 /// Methods 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 "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/RecursiveASTVisitor.h"
20 #include "clang/Basic/LLVM.h"
21 #include "clang/Basic/SourceLocation.h"
22 #include "clang/Basic/SourceManager.h"
23 #include "clang/Lex/Lexer.h"
24 #include "clang/Tooling/Core/Lookup.h"
25 #include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
26 #include "clang/Tooling/Refactoring/Rename/SymbolName.h"
27 #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
28 #include "llvm/ADT/StringRef.h"
29 #include "llvm/Support/Casting.h"
30 #include <cstddef>
31 #include <set>
32 #include <string>
33 #include <vector>
34
35 using namespace llvm;
36
37 namespace clang {
38 namespace tooling {
39
40 namespace {
41
42 // Returns true if the given Loc is valid for edit. We don't edit the
43 // SourceLocations that are valid or in temporary buffer.
44 bool IsValidEditLoc(const clang::SourceManager& SM, clang::SourceLocation Loc) {
45 if (Loc.isInvalid())
46 return false;
47 const clang::FullSourceLoc FullLoc(Loc, SM);
48 std::pair<clang::FileID, unsigned> FileIdAndOffset =
49 FullLoc.getSpellingLoc().getDecomposedLoc();
50 return SM.getFileEntryForID(FileIdAndOffset.first) != nullptr;
51 }
52
53 // This visitor recursively searches for all instances of a USR in a
54 // translation unit and stores them for later usage.
55 class USRLocFindingASTVisitor
56 : public RecursiveSymbolVisitor<USRLocFindingASTVisitor> {
57 public:
58 explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
59 StringRef PrevName,
60 const ASTContext &Context)
61 : RecursiveSymbolVisitor(Context.getSourceManager(),
62 Context.getLangOpts()),
63 USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
64 }
65
66 bool visitSymbolOccurrence(const NamedDecl *ND,
67 ArrayRef<SourceRange> NameRanges) {
68 if (USRSet.find(getUSRForDecl(ND)) != USRSet.end()) {
69 assert(NameRanges.size() == 1 &&
70 "Multiple name pieces are not supported yet!");
71 SourceLocation Loc = NameRanges[0].getBegin();
72 const SourceManager &SM = Context.getSourceManager();
73 // TODO: Deal with macro occurrences correctly.
74 if (Loc.isMacroID())
75 Loc = SM.getSpellingLoc(Loc);
76 checkAndAddLocation(Loc);
77 }
78 return true;
79 }
80
81 // Non-visitors:
82
83 /// Returns a set of unique symbol occurrences. Duplicate or
84 /// overlapping occurrences are erroneous and should be reported!
85 SymbolOccurrences takeOccurrences() { return std::move(Occurrences); }
86
87 private:
88 void checkAndAddLocation(SourceLocation Loc) {
89 const SourceLocation BeginLoc = Loc;
90 const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
91 BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
92 StringRef TokenName =
93 Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
94 Context.getSourceManager(), Context.getLangOpts());
95 size_t Offset = TokenName.find(PrevName.getNamePieces()[0]);
96
97 // The token of the source location we find actually has the old
98 // name.
99 if (Offset != StringRef::npos)
100 Occurrences.emplace_back(PrevName, SymbolOccurrence::MatchingSymbol,
101 BeginLoc.getLocWithOffset(Offset));
102 }
103
104 const std::set<std::string> USRSet;
105 const SymbolName PrevName;
106 SymbolOccurrences Occurrences;
107 const ASTContext &Context;
108 };
109
110 SourceLocation StartLocationForType(TypeLoc TL) {
111 // For elaborated types (e.g. `struct a::A`) we want the portion after the
112 // `struct` but including the namespace qualifier, `a::`.
113 if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
114 NestedNameSpecifierLoc NestedNameSpecifier =
115 ElaboratedTypeLoc.getQualifierLoc();
116 if (NestedNameSpecifier.getNestedNameSpecifier())
117 return NestedNameSpecifier.getBeginLoc();
118 TL = TL.getNextTypeLoc();
119 }
120 return TL.getBeginLoc();
121 }
122
123 SourceLocation EndLocationForType(TypeLoc TL) {
124 // Dig past any namespace or keyword qualifications.
125 while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
126 TL.getTypeLocClass() == TypeLoc::Qualified)
127 TL = TL.getNextTypeLoc();
128
129 // The location for template specializations (e.g. Foo<int>) includes the
130 // templated types in its location range. We want to restrict this to just
131 // before the `<` character.
132 if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
133 return TL.castAs<TemplateSpecializationTypeLoc>()
134 .getLAngleLoc()
135 .getLocWithOffset(-1);
136 }
137 return TL.getEndLoc();
138 }
139
140 NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
141 // Dig past any keyword qualifications.
142 while (TL.getTypeLocClass() == TypeLoc::Qualified)
143 TL = TL.getNextTypeLoc();
144
145 // For elaborated types (e.g. `struct a::A`) we want the portion after the
146 // `struct` but including the namespace qualifier, `a::`.
147 if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
148 return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
149 return nullptr;
150 }
151
152 // Find all locations identified by the given USRs for rename.
153 //
154 // This class will traverse the AST and find every AST node whose USR is in the
155 // given USRs' set.
156 class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
157 public:
158 RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
159 : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
160
161 // A structure records all information of a symbol reference being renamed.
162 // We try to add as few prefix qualifiers as possible.
163 struct RenameInfo {
164 // The begin location of a symbol being renamed.
165 SourceLocation Begin;
166 // The end location of a symbol being renamed.
167 SourceLocation End;
168 // The declaration of a symbol being renamed (can be nullptr).
169 const NamedDecl *FromDecl;
170 // The declaration in which the nested name is contained (can be nullptr).
171 const Decl *Context;
172 // The nested name being replaced (can be nullptr).
173 const NestedNameSpecifier *Specifier;
174 // Determine whether the prefix qualifiers of the NewName should be ignored.
175 // Normally, we set it to true for the symbol declaration and definition to
176 // avoid adding prefix qualifiers.
177 // For example, if it is true and NewName is "a::b::foo", then the symbol
178 // occurrence which the RenameInfo points to will be renamed to "foo".
179 bool IgnorePrefixQualifers;
180 };
181
182 bool VisitNamedDecl(const NamedDecl *Decl) {
183 // UsingDecl has been handled in other place.
184 if (llvm::isa<UsingDecl>(Decl))
185 return true;
186
187 // DestructorDecl has been handled in Typeloc.
188 if (llvm::isa<CXXDestructorDecl>(Decl))
189 return true;
190
191 if (Decl->isImplicit())
192 return true;
193
194 if (isInUSRSet(Decl)) {
195 // For the case of renaming an alias template, we actually rename the
196 // underlying alias declaration of the template.
197 if (const auto* TAT = dyn_cast<TypeAliasTemplateDecl>(Decl))
198 Decl = TAT->getTemplatedDecl();
199
200 auto StartLoc = Decl->getLocation();
201 auto EndLoc = StartLoc;
202 if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
203 RenameInfo Info = {StartLoc,
204 EndLoc,
205 /*FromDecl=*/nullptr,
206 /*Context=*/nullptr,
207 /*Specifier=*/nullptr,
208 /*IgnorePrefixQualifers=*/true};
209 RenameInfos.push_back(Info);
210 }
211 }
212 return true;
213 }
214
215 bool VisitMemberExpr(const MemberExpr *Expr) {
216 const NamedDecl *Decl = Expr->getFoundDecl();
217 auto StartLoc = Expr->getMemberLoc();
218 auto EndLoc = Expr->getMemberLoc();
219 if (isInUSRSet(Decl)) {
220 RenameInfos.push_back({StartLoc, EndLoc,
221 /*FromDecl=*/nullptr,
222 /*Context=*/nullptr,
223 /*Specifier=*/nullptr,
224 /*IgnorePrefixQualifiers=*/true});
225 }
226 return true;
227 }
228
229 bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
230 // Fix the constructor initializer when renaming class members.
231 for (const auto *Initializer : CD->inits()) {
232 // Ignore implicit initializers.
233 if (!Initializer->isWritten())
234 continue;
235
236 if (const FieldDecl *FD = Initializer->getMember()) {
237 if (isInUSRSet(FD)) {
238 auto Loc = Initializer->getSourceLocation();
239 RenameInfos.push_back({Loc, Loc,
240 /*FromDecl=*/nullptr,
241 /*Context=*/nullptr,
242 /*Specifier=*/nullptr,
243 /*IgnorePrefixQualifiers=*/true});
244 }
245 }
246 }
247 return true;
248 }
249
250 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
251 const NamedDecl *Decl = Expr->getFoundDecl();
252 // Get the underlying declaration of the shadow declaration introduced by a
253 // using declaration.
254 if (auto *UsingShadow = llvm::dyn_cast<UsingShadowDecl>(Decl)) {
255 Decl = UsingShadow->getTargetDecl();
256 }
257
258 auto StartLoc = Expr->getBeginLoc();
259 // For template function call expressions like `foo<int>()`, we want to
260 // restrict the end of location to just before the `<` character.
261 SourceLocation EndLoc = Expr->hasExplicitTemplateArgs()
262 ? Expr->getLAngleLoc().getLocWithOffset(-1)
263 : Expr->getEndLoc();
264
265 if (const auto *MD = llvm::dyn_cast<CXXMethodDecl>(Decl)) {
266 if (isInUSRSet(MD)) {
267 // Handle renaming static template class methods, we only rename the
268 // name without prefix qualifiers and restrict the source range to the
269 // name.
270 RenameInfos.push_back({EndLoc, EndLoc,
271 /*FromDecl=*/nullptr,
272 /*Context=*/nullptr,
273 /*Specifier=*/nullptr,
274 /*IgnorePrefixQualifiers=*/true});
275 return true;
276 }
277 }
278
279 // In case of renaming an enum declaration, we have to explicitly handle
280 // unscoped enum constants referenced in expressions (e.g.
281 // "auto r = ns1::ns2::Green" where Green is an enum constant of an unscoped
282 // enum decl "ns1::ns2::Color") as these enum constants cannot be caught by
283 // TypeLoc.
284 if (const auto *T = llvm::dyn_cast<EnumConstantDecl>(Decl)) {
285 // FIXME: Handle the enum constant without prefix qualifiers (`a = Green`)
286 // when renaming an unscoped enum declaration with a new namespace.
287 if (!Expr->hasQualifier())
288 return true;
289
290 if (const auto *ED =
291 llvm::dyn_cast_or_null<EnumDecl>(getClosestAncestorDecl(*T))) {
292 if (ED->isScoped())
293 return true;
294 Decl = ED;
295 }
296 // The current fix would qualify "ns1::ns2::Green" as
297 // "ns1::ns2::Color::Green".
298 //
299 // Get the EndLoc of the replacement by moving 1 character backward (
300 // to exclude the last '::').
301 //
302 // ns1::ns2::Green;
303 // ^ ^^
304 // BeginLoc |EndLoc of the qualifier
305 // new EndLoc
306 EndLoc = Expr->getQualifierLoc().getEndLoc().getLocWithOffset(-1);
307 assert(EndLoc.isValid() &&
308 "The enum constant should have prefix qualifers.");
309 }
310 if (isInUSRSet(Decl) &&
311 IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
312 RenameInfo Info = {StartLoc,
313 EndLoc,
314 Decl,
315 getClosestAncestorDecl(*Expr),
316 Expr->getQualifier(),
317 /*IgnorePrefixQualifers=*/false};
318 RenameInfos.push_back(Info);
319 }
320
321 return true;
322 }
323
324 bool VisitUsingDecl(const UsingDecl *Using) {
325 for (const auto *UsingShadow : Using->shadows()) {
326 if (isInUSRSet(UsingShadow->getTargetDecl())) {
327 UsingDecls.push_back(Using);
328 break;
329 }
330 }
331 return true;
332 }
333
334 bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
335 if (!NestedLoc.getNestedNameSpecifier()->getAsType())
336 return true;
337
338 if (const auto *TargetDecl =
339 getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
340 if (isInUSRSet(TargetDecl)) {
341 RenameInfo Info = {NestedLoc.getBeginLoc(),
342 EndLocationForType(NestedLoc.getTypeLoc()),
343 TargetDecl,
344 getClosestAncestorDecl(NestedLoc),
345 NestedLoc.getNestedNameSpecifier()->getPrefix(),
346 /*IgnorePrefixQualifers=*/false};
347 RenameInfos.push_back(Info);
348 }
349 }
350 return true;
351 }
352
353 bool VisitTypeLoc(TypeLoc Loc) {
354 auto Parents = Context.getParents(Loc);
355 TypeLoc ParentTypeLoc;
356 if (!Parents.empty()) {
357 // Handle cases of nested name specificier locations.
358 //
359 // The VisitNestedNameSpecifierLoc interface is not impelmented in
360 // RecursiveASTVisitor, we have to handle it explicitly.
361 if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
362 VisitNestedNameSpecifierLocations(*NSL);
363 return true;
364 }
365
366 if (const auto *TL = Parents[0].get<TypeLoc>())
367 ParentTypeLoc = *TL;
368 }
369
370 // Handle the outermost TypeLoc which is directly linked to the interesting
371 // declaration and don't handle nested name specifier locations.
372 if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
373 if (isInUSRSet(TargetDecl)) {
374 // Only handle the outermost typeLoc.
375 //
376 // For a type like "a::Foo", there will be two typeLocs for it.
377 // One ElaboratedType, the other is RecordType:
378 //
379 // ElaboratedType 0x33b9390 'a::Foo' sugar
380 // `-RecordType 0x338fef0 'class a::Foo'
381 // `-CXXRecord 0x338fe58 'Foo'
382 //
383 // Skip if this is an inner typeLoc.
384 if (!ParentTypeLoc.isNull() &&
385 isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
386 return true;
387
388 auto StartLoc = StartLocationForType(Loc);
389 auto EndLoc = EndLocationForType(Loc);
390 if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
391 RenameInfo Info = {StartLoc,
392 EndLoc,
393 TargetDecl,
394 getClosestAncestorDecl(Loc),
395 GetNestedNameForType(Loc),
396 /*IgnorePrefixQualifers=*/false};
397 RenameInfos.push_back(Info);
398 }
399 return true;
400 }
401 }
402
403 // Handle specific template class specialiation cases.
404 if (const auto *TemplateSpecType =
405 dyn_cast<TemplateSpecializationType>(Loc.getType())) {
406 TypeLoc TargetLoc = Loc;
407 if (!ParentTypeLoc.isNull()) {
408 if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
409 TargetLoc = ParentTypeLoc;
410 }
411
412 if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
413 TypeLoc TargetLoc = Loc;
414 // FIXME: Find a better way to handle this case.
415 // For the qualified template class specification type like
416 // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
417 // (ElaboratedType) of the TemplateSpecializationType in order to
418 // catch the prefix qualifiers "ns::".
419 if (!ParentTypeLoc.isNull() &&
420 llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
421 TargetLoc = ParentTypeLoc;
422
423 auto StartLoc = StartLocationForType(TargetLoc);
424 auto EndLoc = EndLocationForType(TargetLoc);
425 if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
426 RenameInfo Info = {
427 StartLoc,
428 EndLoc,
429 TemplateSpecType->getTemplateName().getAsTemplateDecl(),
430 getClosestAncestorDecl(
431 ast_type_traits::DynTypedNode::create(TargetLoc)),
432 GetNestedNameForType(TargetLoc),
433 /*IgnorePrefixQualifers=*/false};
434 RenameInfos.push_back(Info);
435 }
436 }
437 }
438 return true;
439 }
440
441 // Returns a list of RenameInfo.
442 const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
443
444 // Returns a list of using declarations which are needed to update.
445 const std::vector<const UsingDecl *> &getUsingDecls() const {
446 return UsingDecls;
447 }
448
449 private:
450 // Get the supported declaration from a given typeLoc. If the declaration type
451 // is not supported, returns nullptr.
452 const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
453 if (const auto* TT = Loc.getType()->getAs<clang::TypedefType>())
454 return TT->getDecl();
455 if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
456 return RD;
457 if (const auto *ED =
458 llvm::dyn_cast_or_null<EnumDecl>(Loc.getType()->getAsTagDecl()))
459 return ED;
460 return nullptr;
461 }
462
463 // Get the closest ancester which is a declaration of a given AST node.
464 template <typename ASTNodeType>
465 const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
466 auto Parents = Context.getParents(Node);
467 // FIXME: figure out how to handle it when there are multiple parents.
468 if (Parents.size() != 1)
469 return nullptr;
470 if (ast_type_traits::ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(
471 Parents[0].getNodeKind()))
472 return Parents[0].template get<Decl>();
473 return getClosestAncestorDecl(Parents[0]);
474 }
475
476 // Get the parent typeLoc of a given typeLoc. If there is no such parent,
477 // return nullptr.
478 const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
479 auto Parents = Context.getParents(Loc);
480 // FIXME: figure out how to handle it when there are multiple parents.
481 if (Parents.size() != 1)
482 return nullptr;
483 return Parents[0].get<TypeLoc>();
484 }
485
486 // Check whether the USR of a given Decl is in the USRSet.
487 bool isInUSRSet(const Decl *Decl) const {
488 auto USR = getUSRForDecl(Decl);
489 if (USR.empty())
490 return false;
491 return llvm::is_contained(USRSet, USR);
492 }
493
494 const std::set<std::string> USRSet;
495 ASTContext &Context;
496 std::vector<RenameInfo> RenameInfos;
497 // Record all interested using declarations which contains the using-shadow
498 // declarations of the symbol declarations being renamed.
499 std::vector<const UsingDecl *> UsingDecls;
500 };
501
502 } // namespace
503
504 SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
505 StringRef PrevName, Decl *Decl) {
506 USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
507 Visitor.TraverseDecl(Decl);
508 return Visitor.takeOccurrences();
509 }
510
511 std::vector<tooling::AtomicChange>
512 createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
513 llvm::StringRef NewName, Decl *TranslationUnitDecl) {
514 RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
515 Finder.TraverseDecl(TranslationUnitDecl);
516
517 const SourceManager &SM =
518 TranslationUnitDecl->getASTContext().getSourceManager();
519
520 std::vector<tooling::AtomicChange> AtomicChanges;
521 auto Replace = [&](SourceLocation Start, SourceLocation End,
522 llvm::StringRef Text) {
523 tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
524 llvm::Error Err = ReplaceChange.replace(
525 SM, CharSourceRange::getTokenRange(Start, End), Text);
526 if (Err) {
527 llvm::errs() << "Failed to add replacement to AtomicChange: "
528 << llvm::toString(std::move(Err)) << "\n";
529 return;
530 }
531 AtomicChanges.push_back(std::move(ReplaceChange));
532 };
533
534 for (const auto &RenameInfo : Finder.getRenameInfos()) {
535 std::string ReplacedName = NewName.str();
536 if (RenameInfo.IgnorePrefixQualifers) {
537 // Get the name without prefix qualifiers from NewName.
538 size_t LastColonPos = NewName.find_last_of(':');
539 if (LastColonPos != std::string::npos)
540 ReplacedName = NewName.substr(LastColonPos + 1);
541 } else {
542 if (RenameInfo.FromDecl && RenameInfo.Context) {
543 if (!llvm::isa<clang::TranslationUnitDecl>(
544 RenameInfo.Context->getDeclContext())) {
545 ReplacedName = tooling::replaceNestedName(
546 RenameInfo.Specifier, RenameInfo.Context->getDeclContext(),
547 RenameInfo.FromDecl,
548 NewName.startswith("::") ? NewName.str()
549 : ("::" + NewName).str());
550 } else {
551 // This fixes the case where type `T` is a parameter inside a function
552 // type (e.g. `std::function<void(T)>`) and the DeclContext of `T`
553 // becomes the translation unit. As a workaround, we simply use
554 // fully-qualified name here for all references whose `DeclContext` is
555 // the translation unit and ignore the possible existence of
556 // using-decls (in the global scope) that can shorten the replaced
557 // name.
558 llvm::StringRef ActualName = Lexer::getSourceText(
559 CharSourceRange::getTokenRange(
560 SourceRange(RenameInfo.Begin, RenameInfo.End)),
561 SM, TranslationUnitDecl->getASTContext().getLangOpts());
562 // Add the leading "::" back if the name written in the code contains
563 // it.
564 if (ActualName.startswith("::") && !NewName.startswith("::")) {
565 ReplacedName = "::" + NewName.str();
566 }
567 }
568 }
569 // If the NewName contains leading "::", add it back.
570 if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
571 ReplacedName = NewName.str();
572 }
573 Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
574 }
575
576 // Hanlde using declarations explicitly as "using a::Foo" don't trigger
577 // typeLoc for "a::Foo".
578 for (const auto *Using : Finder.getUsingDecls())
579 Replace(Using->getBeginLoc(), Using->getEndLoc(), "using " + NewName.str());
580
581 return AtomicChanges;
582 }
583
584 } // end namespace tooling
585 } // end namespace clang
clang::tooling::createRenameAtomicChanges
std::vector< tooling::AtomicChange > createRenameAtomicChanges(llvm::ArrayRef< std::string > USRs, llvm::StringRef NewName, Decl *TranslationUnitDecl)
Create atomic changes for renaming all symbol references which are identified by the USRs set to a gi...
Definition: USRLocFinder.cpp:512
ASTContext.h
Defines the clang::ASTContext interface.
clang::tooling::AtomicChange::replace
llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range, llvm::StringRef ReplacementText)
Adds a replacement that replaces the given Range with ReplacementText.
Definition: AtomicChange.cpp:253
IgnorePrefixQualifers
bool IgnorePrefixQualifers
Definition: USRLocFinder.cpp:179
llvm
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:30
clang::tooling::AtomicChanges
std::vector< AtomicChange > AtomicChanges
Definition: AtomicChange.h:141
clang::ElaboratedTypeLoc
Definition: TypeLoc.h:1934
SourceManager.h
Defines the SourceManager interface.
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
Specifier
const NestedNameSpecifier * Specifier
Definition: USRLocFinder.cpp:173
RecursiveSymbolVisitor.h
A wrapper class around RecursiveASTVisitor that visits each occurrences of a named symbol...
toString
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Definition: SanitizerArgs.cpp:775
LLVM.h
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
USRFinder.h
Methods for determining the USR of a symbol at a location in source code.
llvm::ArrayRef
Definition: LLVM.h:32
clang::tooling::replaceNestedName
std::string replaceNestedName(const NestedNameSpecifier *Use, const DeclContext *UseContext, const NamedDecl *FromDecl, StringRef ReplacementString)
Emulate a lookup to replace one nested name specifier with another using as few additional namespace ...
Definition: Lookup.cpp:149
llvm::str
return Out str()
SymbolName.h
Offset
unsigned Offset
Definition: Format.cpp:1631
USRLocFinder.h
Provides functionality for finding all instances of a USR in a given AST.
End
SourceLocation End
Definition: USRLocFinder.cpp:167
clang::SourceManager::getFileEntryForID
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
Definition: SourceManager.h:986
Begin
SourceLocation Begin
Definition: USRLocFinder.cpp:165
Lexer.h
RecursiveASTVisitor.h
SM
const SourceManager & SM
Definition: Format.cpp:1490
FromDecl
const NamedDecl * FromDecl
Definition: USRLocFinder.cpp:169
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::tooling::getUSRForDecl
std::string getUSRForDecl(const Decl *Decl)
Definition: USRFinder.cpp:135
clang::Decl::getASTContext
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:376
Node
ast_type_traits::DynTypedNode Node
Definition: ASTMatchFinder.cpp:61
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:22
clang::serialized_diags::create
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
Definition: SerializedDiagnosticPrinter.cpp:297
Lookup.h
clang::ASTContext::getSourceManager
SourceManager & getSourceManager()
Definition: ASTContext.h:662
clang::tooling::SymbolOccurrences
std::vector< SymbolOccurrence > SymbolOccurrences
Definition: SymbolOccurrences.h:86
SourceLocation.h
Defines the clang::SourceLocation class and associated facilities.
clang::SourceLocation::isInvalid
bool isInvalid() const
Definition: SourceLocation.h:109
clang::tooling::getOccurrencesOfUSRs
SymbolOccurrences getOccurrencesOfUSRs(ArrayRef< std::string > USRs, StringRef PrevName, Decl *Decl)
Finds the symbol occurrences for the symbol that&#39;s identified by the given USR set.
Definition: USRLocFinder.cpp:504
clang::FullSourceLoc
A SourceLocation and its associated SourceManager.
Definition: SourceLocation.h:340
clang::TranslationUnitDecl
The top declaration context.
Definition: Decl.h:108
clang::tooling::AtomicChange
An atomic change is used to create and group a set of source edits, e.g.
Definition: AtomicChange.h:37
clang::TypedefType
Definition: Type.h:4151
Text
StringRef Text
Definition: Format.cpp:1630
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:198
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:707
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:582