clang 10.0.0git

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