clang  14.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 
17 #include "clang/AST/ASTContext.h"
20 #include "clang/Basic/LLVM.h"
23 #include "clang/Lex/Lexer.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".
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 VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
230  for (const DesignatedInitExpr::Designator &D : E->designators()) {
231  if (D.isFieldDesignator() && D.getField()) {
232  const FieldDecl *Decl = D.getField();
233  if (isInUSRSet(Decl)) {
234  auto StartLoc = D.getFieldLoc();
235  auto EndLoc = D.getFieldLoc();
236  RenameInfos.push_back({StartLoc, EndLoc,
237  /*FromDecl=*/nullptr,
238  /*Context=*/nullptr,
239  /*Specifier=*/nullptr,
240  /*IgnorePrefixQualifiers=*/true});
241  }
242  }
243  }
244  return true;
245  }
246 
247  bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
248  // Fix the constructor initializer when renaming class members.
249  for (const auto *Initializer : CD->inits()) {
250  // Ignore implicit initializers.
251  if (!Initializer->isWritten())
252  continue;
253 
254  if (const FieldDecl *FD = Initializer->getMember()) {
255  if (isInUSRSet(FD)) {
256  auto Loc = Initializer->getSourceLocation();
257  RenameInfos.push_back({Loc, Loc,
258  /*FromDecl=*/nullptr,
259  /*Context=*/nullptr,
260  /*Specifier=*/nullptr,
261  /*IgnorePrefixQualifiers=*/true});
262  }
263  }
264  }
265  return true;
266  }
267 
268  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
269  const NamedDecl *Decl = Expr->getFoundDecl();
270  // Get the underlying declaration of the shadow declaration introduced by a
271  // using declaration.
272  if (auto *UsingShadow = llvm::dyn_cast<UsingShadowDecl>(Decl)) {
273  Decl = UsingShadow->getTargetDecl();
274  }
275 
276  auto StartLoc = Expr->getBeginLoc();
277  // For template function call expressions like `foo<int>()`, we want to
278  // restrict the end of location to just before the `<` character.
279  SourceLocation EndLoc = Expr->hasExplicitTemplateArgs()
280  ? Expr->getLAngleLoc().getLocWithOffset(-1)
281  : Expr->getEndLoc();
282 
283  if (const auto *MD = llvm::dyn_cast<CXXMethodDecl>(Decl)) {
284  if (isInUSRSet(MD)) {
285  // Handle renaming static template class methods, we only rename the
286  // name without prefix qualifiers and restrict the source range to the
287  // name.
288  RenameInfos.push_back({EndLoc, EndLoc,
289  /*FromDecl=*/nullptr,
290  /*Context=*/nullptr,
291  /*Specifier=*/nullptr,
292  /*IgnorePrefixQualifiers=*/true});
293  return true;
294  }
295  }
296 
297  // In case of renaming an enum declaration, we have to explicitly handle
298  // unscoped enum constants referenced in expressions (e.g.
299  // "auto r = ns1::ns2::Green" where Green is an enum constant of an unscoped
300  // enum decl "ns1::ns2::Color") as these enum constants cannot be caught by
301  // TypeLoc.
302  if (const auto *T = llvm::dyn_cast<EnumConstantDecl>(Decl)) {
303  // FIXME: Handle the enum constant without prefix qualifiers (`a = Green`)
304  // when renaming an unscoped enum declaration with a new namespace.
305  if (!Expr->hasQualifier())
306  return true;
307 
308  if (const auto *ED =
309  llvm::dyn_cast_or_null<EnumDecl>(getClosestAncestorDecl(*T))) {
310  if (ED->isScoped())
311  return true;
312  Decl = ED;
313  }
314  // The current fix would qualify "ns1::ns2::Green" as
315  // "ns1::ns2::Color::Green".
316  //
317  // Get the EndLoc of the replacement by moving 1 character backward (
318  // to exclude the last '::').
319  //
320  // ns1::ns2::Green;
321  // ^ ^^
322  // BeginLoc |EndLoc of the qualifier
323  // new EndLoc
324  EndLoc = Expr->getQualifierLoc().getEndLoc().getLocWithOffset(-1);
325  assert(EndLoc.isValid() &&
326  "The enum constant should have prefix qualifers.");
327  }
328  if (isInUSRSet(Decl) &&
329  IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
330  RenameInfo Info = {StartLoc,
331  EndLoc,
332  Decl,
333  getClosestAncestorDecl(*Expr),
334  Expr->getQualifier(),
335  /*IgnorePrefixQualifers=*/false};
336  RenameInfos.push_back(Info);
337  }
338 
339  return true;
340  }
341 
342  bool VisitUsingDecl(const UsingDecl *Using) {
343  for (const auto *UsingShadow : Using->shadows()) {
344  if (isInUSRSet(UsingShadow->getTargetDecl())) {
345  UsingDecls.push_back(Using);
346  break;
347  }
348  }
349  return true;
350  }
351 
352  bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
353  if (!NestedLoc.getNestedNameSpecifier()->getAsType())
354  return true;
355 
356  if (const auto *TargetDecl =
357  getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
358  if (isInUSRSet(TargetDecl)) {
359  RenameInfo Info = {NestedLoc.getBeginLoc(),
360  EndLocationForType(NestedLoc.getTypeLoc()),
361  TargetDecl,
362  getClosestAncestorDecl(NestedLoc),
363  NestedLoc.getNestedNameSpecifier()->getPrefix(),
364  /*IgnorePrefixQualifers=*/false};
365  RenameInfos.push_back(Info);
366  }
367  }
368  return true;
369  }
370 
371  bool VisitTypeLoc(TypeLoc Loc) {
372  auto Parents = Context.getParents(Loc);
373  TypeLoc ParentTypeLoc;
374  if (!Parents.empty()) {
375  // Handle cases of nested name specificier locations.
376  //
377  // The VisitNestedNameSpecifierLoc interface is not impelmented in
378  // RecursiveASTVisitor, we have to handle it explicitly.
379  if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
380  VisitNestedNameSpecifierLocations(*NSL);
381  return true;
382  }
383 
384  if (const auto *TL = Parents[0].get<TypeLoc>())
385  ParentTypeLoc = *TL;
386  }
387 
388  // Handle the outermost TypeLoc which is directly linked to the interesting
389  // declaration and don't handle nested name specifier locations.
390  if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
391  if (isInUSRSet(TargetDecl)) {
392  // Only handle the outermost typeLoc.
393  //
394  // For a type like "a::Foo", there will be two typeLocs for it.
395  // One ElaboratedType, the other is RecordType:
396  //
397  // ElaboratedType 0x33b9390 'a::Foo' sugar
398  // `-RecordType 0x338fef0 'class a::Foo'
399  // `-CXXRecord 0x338fe58 'Foo'
400  //
401  // Skip if this is an inner typeLoc.
402  if (!ParentTypeLoc.isNull() &&
403  isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
404  return true;
405 
406  auto StartLoc = StartLocationForType(Loc);
407  auto EndLoc = EndLocationForType(Loc);
408  if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
409  RenameInfo Info = {StartLoc,
410  EndLoc,
411  TargetDecl,
412  getClosestAncestorDecl(Loc),
413  GetNestedNameForType(Loc),
414  /*IgnorePrefixQualifers=*/false};
415  RenameInfos.push_back(Info);
416  }
417  return true;
418  }
419  }
420 
421  // Handle specific template class specialiation cases.
422  if (const auto *TemplateSpecType =
423  dyn_cast<TemplateSpecializationType>(Loc.getType())) {
424  TypeLoc TargetLoc = Loc;
425  if (!ParentTypeLoc.isNull()) {
426  if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
427  TargetLoc = ParentTypeLoc;
428  }
429 
430  if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
431  TypeLoc TargetLoc = Loc;
432  // FIXME: Find a better way to handle this case.
433  // For the qualified template class specification type like
434  // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
435  // (ElaboratedType) of the TemplateSpecializationType in order to
436  // catch the prefix qualifiers "ns::".
437  if (!ParentTypeLoc.isNull() &&
438  llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
439  TargetLoc = ParentTypeLoc;
440 
441  auto StartLoc = StartLocationForType(TargetLoc);
442  auto EndLoc = EndLocationForType(TargetLoc);
443  if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
444  RenameInfo Info = {
445  StartLoc,
446  EndLoc,
447  TemplateSpecType->getTemplateName().getAsTemplateDecl(),
448  getClosestAncestorDecl(DynTypedNode::create(TargetLoc)),
449  GetNestedNameForType(TargetLoc),
450  /*IgnorePrefixQualifers=*/false};
451  RenameInfos.push_back(Info);
452  }
453  }
454  }
455  return true;
456  }
457 
458  // Returns a list of RenameInfo.
459  const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
460 
461  // Returns a list of using declarations which are needed to update.
462  const std::vector<const UsingDecl *> &getUsingDecls() const {
463  return UsingDecls;
464  }
465 
466 private:
467  // Get the supported declaration from a given typeLoc. If the declaration type
468  // is not supported, returns nullptr.
469  const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
470  if (const auto* TT = Loc.getType()->getAs<clang::TypedefType>())
471  return TT->getDecl();
472  if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
473  return RD;
474  if (const auto *ED =
475  llvm::dyn_cast_or_null<EnumDecl>(Loc.getType()->getAsTagDecl()))
476  return ED;
477  return nullptr;
478  }
479 
480  // Get the closest ancester which is a declaration of a given AST node.
481  template <typename ASTNodeType>
482  const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
483  auto Parents = Context.getParents(Node);
484  // FIXME: figure out how to handle it when there are multiple parents.
485  if (Parents.size() != 1)
486  return nullptr;
487  if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(Parents[0].getNodeKind()))
488  return Parents[0].template get<Decl>();
489  return getClosestAncestorDecl(Parents[0]);
490  }
491 
492  // Get the parent typeLoc of a given typeLoc. If there is no such parent,
493  // return nullptr.
494  const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
495  auto Parents = Context.getParents(Loc);
496  // FIXME: figure out how to handle it when there are multiple parents.
497  if (Parents.size() != 1)
498  return nullptr;
499  return Parents[0].get<TypeLoc>();
500  }
501 
502  // Check whether the USR of a given Decl is in the USRSet.
503  bool isInUSRSet(const Decl *Decl) const {
504  auto USR = getUSRForDecl(Decl);
505  if (USR.empty())
506  return false;
507  return llvm::is_contained(USRSet, USR);
508  }
509 
510  const std::set<std::string> USRSet;
511  ASTContext &Context;
512  std::vector<RenameInfo> RenameInfos;
513  // Record all interested using declarations which contains the using-shadow
514  // declarations of the symbol declarations being renamed.
515  std::vector<const UsingDecl *> UsingDecls;
516 };
517 
518 } // namespace
519 
521  StringRef PrevName, Decl *Decl) {
522  USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
523  Visitor.TraverseDecl(Decl);
524  return Visitor.takeOccurrences();
525 }
526 
527 std::vector<tooling::AtomicChange>
529  llvm::StringRef NewName, Decl *TranslationUnitDecl) {
530  RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
531  Finder.TraverseDecl(TranslationUnitDecl);
532 
533  const SourceManager &SM =
535 
536  std::vector<tooling::AtomicChange> AtomicChanges;
537  auto Replace = [&](SourceLocation Start, SourceLocation End,
538  llvm::StringRef Text) {
539  tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
540  llvm::Error Err = ReplaceChange.replace(
541  SM, CharSourceRange::getTokenRange(Start, End), Text);
542  if (Err) {
543  llvm::errs() << "Failed to add replacement to AtomicChange: "
544  << llvm::toString(std::move(Err)) << "\n";
545  return;
546  }
547  AtomicChanges.push_back(std::move(ReplaceChange));
548  };
549 
550  for (const auto &RenameInfo : Finder.getRenameInfos()) {
551  std::string ReplacedName = NewName.str();
552  if (RenameInfo.IgnorePrefixQualifers) {
553  // Get the name without prefix qualifiers from NewName.
554  size_t LastColonPos = NewName.find_last_of(':');
555  if (LastColonPos != std::string::npos)
556  ReplacedName = std::string(NewName.substr(LastColonPos + 1));
557  } else {
558  if (RenameInfo.FromDecl && RenameInfo.Context) {
559  if (!llvm::isa<clang::TranslationUnitDecl>(
560  RenameInfo.Context->getDeclContext())) {
561  ReplacedName = tooling::replaceNestedName(
562  RenameInfo.Specifier, RenameInfo.Begin,
563  RenameInfo.Context->getDeclContext(), RenameInfo.FromDecl,
564  NewName.startswith("::") ? NewName.str()
565  : ("::" + NewName).str());
566  } else {
567  // This fixes the case where type `T` is a parameter inside a function
568  // type (e.g. `std::function<void(T)>`) and the DeclContext of `T`
569  // becomes the translation unit. As a workaround, we simply use
570  // fully-qualified name here for all references whose `DeclContext` is
571  // the translation unit and ignore the possible existence of
572  // using-decls (in the global scope) that can shorten the replaced
573  // name.
574  llvm::StringRef ActualName = Lexer::getSourceText(
575  CharSourceRange::getTokenRange(
576  SourceRange(RenameInfo.Begin, RenameInfo.End)),
578  // Add the leading "::" back if the name written in the code contains
579  // it.
580  if (ActualName.startswith("::") && !NewName.startswith("::")) {
581  ReplacedName = "::" + NewName.str();
582  }
583  }
584  }
585  // If the NewName contains leading "::", add it back.
586  if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
587  ReplacedName = NewName.str();
588  }
589  Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
590  }
591 
592  // Hanlde using declarations explicitly as "using a::Foo" don't trigger
593  // typeLoc for "a::Foo".
594  for (const auto *Using : Finder.getUsingDecls())
595  Replace(Using->getBeginLoc(), Using->getEndLoc(), "using " + NewName.str());
596 
597  return AtomicChanges;
598 }
599 
600 } // end namespace tooling
601 } // end namespace clang
USRLocFinder.h
clang::Decl::getASTContext
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:414
llvm
Definition: Dominators.h:30
clang::FullSourceLoc
A SourceLocation and its associated SourceManager.
Definition: SourceLocation.h:368
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:210
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
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:185
clang::tooling::getOccurrencesOfUSRs
SymbolOccurrences getOccurrencesOfUSRs(ArrayRef< std::string > USRs, StringRef PrevName, Decl *Decl)
Finds the symbol occurrences for the symbol that's identified by the given USR set.
Definition: USRLocFinder.cpp:520
clang::DynamicInitKind::Initializer
@ Initializer
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:258
clang::tooling::AtomicChange
An atomic change is used to create and group a set of source edits, e.g.
Definition: AtomicChange.h:37
clang::index::SymbolKind::Using
@ Using
SourceManager.h
USRFinder.h
End
SourceLocation End
Definition: USRLocFinder.cpp:167
clang::ASTContext::getSourceManager
SourceManager & getSourceManager()
Definition: ASTContext.h:695
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:626
clang::TypedefType
Definition: Type.h:4371
ParentMapContext.h
Offset
unsigned Offset
Definition: Format.cpp:2381
clang::CodeGen::AlignmentSource::Decl
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
clang::TranslationUnitDecl
The top declaration context.
Definition: Decl.h:82
Lookup.h
Node
DynTypedNode Node
Definition: ASTMatchFinder.cpp:67
clang::tooling::AtomicChanges
std::vector< AtomicChange > AtomicChanges
Definition: AtomicChange.h:152
clang::threadSafety::sx::toString
std::string toString(const til::SExpr *E)
Definition: ThreadSafetyCommon.h:89
ASTContext.h
IgnorePrefixQualifers
bool IgnorePrefixQualifers
Definition: USRLocFinder.cpp:179
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:528
SourceLocation.h
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:302
Specifier
const NestedNameSpecifier * Specifier
Definition: USRLocFinder.cpp:173
Begin
SourceLocation Begin
Definition: USRLocFinder.cpp:165
llvm::ArrayRef
Definition: LLVM.h:34
Lexer.h
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:89
LLVM.h
RecursiveSymbolVisitor.h
FromDecl
const NamedDecl * FromDecl
Definition: USRLocFinder.cpp:169
clang::ElaboratedTypeLoc
Definition: TypeLoc.h:2198
clang::TranslationUnitDecl::getASTContext
ASTContext & getASTContext() const
Definition: Decl.h:120
clang::tooling::getUSRForDecl
std::string getUSRForDecl(const Decl *Decl)
Definition: USRFinder.cpp:135
clang::SourceLocation::isInvalid
bool isInvalid() const
Definition: SourceLocation.h:111
clang
Definition: CalledOnceCheck.h:17
Text
StringRef Text
Definition: Format.cpp:2380
RecursiveASTVisitor.h
clang::tooling::SymbolOccurrences
std::vector< SymbolOccurrence > SymbolOccurrences
Definition: SymbolOccurrences.h:86
SM
#define SM(sm)
Definition: Cuda.cpp:81
SymbolName.h
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:765