clang  10.0.0svn
TransformActions.cpp
Go to the documentation of this file.
1 //===-- TransformActions.cpp - Migration to ARC mode ----------------------===//
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 #include "Internals.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Expr.h"
13 #include "clang/Lex/Preprocessor.h"
14 #include "llvm/ADT/DenseSet.h"
15 #include <map>
16 using namespace clang;
17 using namespace arcmt;
18 
19 namespace {
20 
21 /// Collects transformations and merges them before applying them with
22 /// with applyRewrites(). E.g. if the same source range
23 /// is requested to be removed twice, only one rewriter remove will be invoked.
24 /// Rewrites happen in "transactions"; if one rewrite in the transaction cannot
25 /// be done (e.g. it resides in a macro) all rewrites in the transaction are
26 /// aborted.
27 /// FIXME: "Transactional" rewrites support should be baked in the Rewriter.
28 class TransformActionsImpl {
29  CapturedDiagList &CapturedDiags;
30  ASTContext &Ctx;
31  Preprocessor &PP;
32 
33  bool IsInTransaction;
34 
35  enum ActionKind {
36  Act_Insert, Act_InsertAfterToken,
37  Act_Remove, Act_RemoveStmt,
38  Act_Replace, Act_ReplaceText,
39  Act_IncreaseIndentation,
40  Act_ClearDiagnostic
41  };
42 
43  struct ActionData {
45  SourceLocation Loc;
46  SourceRange R1, R2;
47  StringRef Text1, Text2;
48  Stmt *S;
50  };
51 
52  std::vector<ActionData> CachedActions;
53 
54  enum RangeComparison {
55  Range_Before,
56  Range_After,
57  Range_Contains,
58  Range_Contained,
59  Range_ExtendsBegin,
60  Range_ExtendsEnd
61  };
62 
63  /// A range to remove. It is a character range.
64  struct CharRange {
66 
67  CharRange(CharSourceRange range, SourceManager &srcMgr, Preprocessor &PP) {
68  SourceLocation beginLoc = range.getBegin(), endLoc = range.getEnd();
69  assert(beginLoc.isValid() && endLoc.isValid());
70  if (range.isTokenRange()) {
71  Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
72  End = FullSourceLoc(getLocForEndOfToken(endLoc, srcMgr, PP), srcMgr);
73  } else {
74  Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
75  End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr);
76  }
77  assert(Begin.isValid() && End.isValid());
78  }
79 
80  RangeComparison compareWith(const CharRange &RHS) const {
81  if (End.isBeforeInTranslationUnitThan(RHS.Begin))
82  return Range_Before;
83  if (RHS.End.isBeforeInTranslationUnitThan(Begin))
84  return Range_After;
85  if (!Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
86  !RHS.End.isBeforeInTranslationUnitThan(End))
87  return Range_Contained;
88  if (Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
89  RHS.End.isBeforeInTranslationUnitThan(End))
90  return Range_Contains;
91  if (Begin.isBeforeInTranslationUnitThan(RHS.Begin))
92  return Range_ExtendsBegin;
93  else
94  return Range_ExtendsEnd;
95  }
96 
97  static RangeComparison compare(SourceRange LHS, SourceRange RHS,
98  SourceManager &SrcMgr, Preprocessor &PP) {
99  return CharRange(CharSourceRange::getTokenRange(LHS), SrcMgr, PP)
100  .compareWith(CharRange(CharSourceRange::getTokenRange(RHS),
101  SrcMgr, PP));
102  }
103  };
104 
105  typedef SmallVector<StringRef, 2> TextsVec;
106  typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare>
107  InsertsMap;
108  InsertsMap Inserts;
109  /// A list of ranges to remove. They are always sorted and they never
110  /// intersect with each other.
111  std::list<CharRange> Removals;
112 
113  llvm::DenseSet<Stmt *> StmtRemovals;
114 
115  std::vector<std::pair<CharRange, SourceLocation> > IndentationRanges;
116 
117  /// Keeps text passed to transformation methods.
118  llvm::StringMap<bool> UniqueText;
119 
120 public:
121  TransformActionsImpl(CapturedDiagList &capturedDiags,
122  ASTContext &ctx, Preprocessor &PP)
123  : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { }
124 
125  ASTContext &getASTContext() { return Ctx; }
126 
127  void startTransaction();
128  bool commitTransaction();
129  void abortTransaction();
130 
131  bool isInTransaction() const { return IsInTransaction; }
132 
133  void insert(SourceLocation loc, StringRef text);
134  void insertAfterToken(SourceLocation loc, StringRef text);
135  void remove(SourceRange range);
136  void removeStmt(Stmt *S);
137  void replace(SourceRange range, StringRef text);
138  void replace(SourceRange range, SourceRange replacementRange);
139  void replaceStmt(Stmt *S, StringRef text);
140  void replaceText(SourceLocation loc, StringRef text,
141  StringRef replacementText);
142  void increaseIndentation(SourceRange range,
143  SourceLocation parentIndent);
144 
145  bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
146 
147  void applyRewrites(TransformActions::RewriteReceiver &receiver);
148 
149 private:
150  bool canInsert(SourceLocation loc);
151  bool canInsertAfterToken(SourceLocation loc);
152  bool canRemoveRange(SourceRange range);
153  bool canReplaceRange(SourceRange range, SourceRange replacementRange);
154  bool canReplaceText(SourceLocation loc, StringRef text);
155 
156  void commitInsert(SourceLocation loc, StringRef text);
157  void commitInsertAfterToken(SourceLocation loc, StringRef text);
158  void commitRemove(SourceRange range);
159  void commitRemoveStmt(Stmt *S);
160  void commitReplace(SourceRange range, SourceRange replacementRange);
161  void commitReplaceText(SourceLocation loc, StringRef text,
162  StringRef replacementText);
163  void commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent);
164  void commitClearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
165 
166  void addRemoval(CharSourceRange range);
167  void addInsertion(SourceLocation loc, StringRef text);
168 
169  /// Stores text passed to the transformation methods to keep the string
170  /// "alive". Since the vast majority of text will be the same, we also unique
171  /// the strings using a StringMap.
172  StringRef getUniqueText(StringRef text);
173 
174  /// Computes the source location just past the end of the token at
175  /// the given source location. If the location points at a macro, the whole
176  /// macro expansion is skipped.
177  static SourceLocation getLocForEndOfToken(SourceLocation loc,
179 };
180 
181 } // anonymous namespace
182 
183 void TransformActionsImpl::startTransaction() {
184  assert(!IsInTransaction &&
185  "Cannot start a transaction in the middle of another one");
186  IsInTransaction = true;
187 }
188 
189 bool TransformActionsImpl::commitTransaction() {
190  assert(IsInTransaction && "No transaction started");
191 
192  if (CachedActions.empty()) {
193  IsInTransaction = false;
194  return false;
195  }
196 
197  // Verify that all actions are possible otherwise abort the whole transaction.
198  bool AllActionsPossible = true;
199  for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
200  ActionData &act = CachedActions[i];
201  switch (act.Kind) {
202  case Act_Insert:
203  if (!canInsert(act.Loc))
204  AllActionsPossible = false;
205  break;
206  case Act_InsertAfterToken:
207  if (!canInsertAfterToken(act.Loc))
208  AllActionsPossible = false;
209  break;
210  case Act_Remove:
211  if (!canRemoveRange(act.R1))
212  AllActionsPossible = false;
213  break;
214  case Act_RemoveStmt:
215  assert(act.S);
216  if (!canRemoveRange(act.S->getSourceRange()))
217  AllActionsPossible = false;
218  break;
219  case Act_Replace:
220  if (!canReplaceRange(act.R1, act.R2))
221  AllActionsPossible = false;
222  break;
223  case Act_ReplaceText:
224  if (!canReplaceText(act.Loc, act.Text1))
225  AllActionsPossible = false;
226  break;
227  case Act_IncreaseIndentation:
228  // This is not important, we don't care if it will fail.
229  break;
230  case Act_ClearDiagnostic:
231  // We are just checking source rewrites.
232  break;
233  }
234  if (!AllActionsPossible)
235  break;
236  }
237 
238  if (!AllActionsPossible) {
239  abortTransaction();
240  return true;
241  }
242 
243  for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
244  ActionData &act = CachedActions[i];
245  switch (act.Kind) {
246  case Act_Insert:
247  commitInsert(act.Loc, act.Text1);
248  break;
249  case Act_InsertAfterToken:
250  commitInsertAfterToken(act.Loc, act.Text1);
251  break;
252  case Act_Remove:
253  commitRemove(act.R1);
254  break;
255  case Act_RemoveStmt:
256  commitRemoveStmt(act.S);
257  break;
258  case Act_Replace:
259  commitReplace(act.R1, act.R2);
260  break;
261  case Act_ReplaceText:
262  commitReplaceText(act.Loc, act.Text1, act.Text2);
263  break;
264  case Act_IncreaseIndentation:
265  commitIncreaseIndentation(act.R1, act.Loc);
266  break;
267  case Act_ClearDiagnostic:
268  commitClearDiagnostic(act.DiagIDs, act.R1);
269  break;
270  }
271  }
272 
273  CachedActions.clear();
274  IsInTransaction = false;
275  return false;
276 }
277 
278 void TransformActionsImpl::abortTransaction() {
279  assert(IsInTransaction && "No transaction started");
280  CachedActions.clear();
281  IsInTransaction = false;
282 }
283 
284 void TransformActionsImpl::insert(SourceLocation loc, StringRef text) {
285  assert(IsInTransaction && "Actions only allowed during a transaction");
286  text = getUniqueText(text);
287  ActionData data;
288  data.Kind = Act_Insert;
289  data.Loc = loc;
290  data.Text1 = text;
291  CachedActions.push_back(data);
292 }
293 
294 void TransformActionsImpl::insertAfterToken(SourceLocation loc, StringRef text) {
295  assert(IsInTransaction && "Actions only allowed during a transaction");
296  text = getUniqueText(text);
297  ActionData data;
298  data.Kind = Act_InsertAfterToken;
299  data.Loc = loc;
300  data.Text1 = text;
301  CachedActions.push_back(data);
302 }
303 
305  assert(IsInTransaction && "Actions only allowed during a transaction");
306  ActionData data;
307  data.Kind = Act_Remove;
308  data.R1 = range;
309  CachedActions.push_back(data);
310 }
311 
312 void TransformActionsImpl::removeStmt(Stmt *S) {
313  assert(IsInTransaction && "Actions only allowed during a transaction");
314  ActionData data;
315  data.Kind = Act_RemoveStmt;
316  if (auto *E = dyn_cast<Expr>(S))
317  S = E->IgnoreImplicit(); // important for uniquing
318  data.S = S;
319  CachedActions.push_back(data);
320 }
321 
322 void TransformActionsImpl::replace(SourceRange range, StringRef text) {
323  assert(IsInTransaction && "Actions only allowed during a transaction");
324  text = getUniqueText(text);
325  remove(range);
326  insert(range.getBegin(), text);
327 }
328 
329 void TransformActionsImpl::replace(SourceRange range,
330  SourceRange replacementRange) {
331  assert(IsInTransaction && "Actions only allowed during a transaction");
332  ActionData data;
333  data.Kind = Act_Replace;
334  data.R1 = range;
335  data.R2 = replacementRange;
336  CachedActions.push_back(data);
337 }
338 
339 void TransformActionsImpl::replaceText(SourceLocation loc, StringRef text,
340  StringRef replacementText) {
341  text = getUniqueText(text);
342  replacementText = getUniqueText(replacementText);
343  ActionData data;
344  data.Kind = Act_ReplaceText;
345  data.Loc = loc;
346  data.Text1 = text;
347  data.Text2 = replacementText;
348  CachedActions.push_back(data);
349 }
350 
351 void TransformActionsImpl::replaceStmt(Stmt *S, StringRef text) {
352  assert(IsInTransaction && "Actions only allowed during a transaction");
353  text = getUniqueText(text);
354  insert(S->getBeginLoc(), text);
355  removeStmt(S);
356 }
357 
358 void TransformActionsImpl::increaseIndentation(SourceRange range,
359  SourceLocation parentIndent) {
360  if (range.isInvalid()) return;
361  assert(IsInTransaction && "Actions only allowed during a transaction");
362  ActionData data;
363  data.Kind = Act_IncreaseIndentation;
364  data.R1 = range;
365  data.Loc = parentIndent;
366  CachedActions.push_back(data);
367 }
368 
369 bool TransformActionsImpl::clearDiagnostic(ArrayRef<unsigned> IDs,
370  SourceRange range) {
371  assert(IsInTransaction && "Actions only allowed during a transaction");
372  if (!CapturedDiags.hasDiagnostic(IDs, range))
373  return false;
374 
375  ActionData data;
376  data.Kind = Act_ClearDiagnostic;
377  data.R1 = range;
378  data.DiagIDs.append(IDs.begin(), IDs.end());
379  CachedActions.push_back(data);
380  return true;
381 }
382 
383 bool TransformActionsImpl::canInsert(SourceLocation loc) {
384  if (loc.isInvalid())
385  return false;
386 
388  if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
389  return false;
390 
391  if (loc.isFileID())
392  return true;
393  return PP.isAtStartOfMacroExpansion(loc);
394 }
395 
396 bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) {
397  if (loc.isInvalid())
398  return false;
399 
400  SourceManager &SM = Ctx.getSourceManager();
401  if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
402  return false;
403 
404  if (loc.isFileID())
405  return true;
406  return PP.isAtEndOfMacroExpansion(loc);
407 }
408 
409 bool TransformActionsImpl::canRemoveRange(SourceRange range) {
410  return canInsert(range.getBegin()) && canInsertAfterToken(range.getEnd());
411 }
412 
413 bool TransformActionsImpl::canReplaceRange(SourceRange range,
414  SourceRange replacementRange) {
415  return canRemoveRange(range) && canRemoveRange(replacementRange);
416 }
417 
418 bool TransformActionsImpl::canReplaceText(SourceLocation loc, StringRef text) {
419  if (!canInsert(loc))
420  return false;
421 
422  SourceManager &SM = Ctx.getSourceManager();
423  loc = SM.getExpansionLoc(loc);
424 
425  // Break down the source location.
426  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
427 
428  // Try to load the file buffer.
429  bool invalidTemp = false;
430  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
431  if (invalidTemp)
432  return false;
433 
434  return file.substr(locInfo.second).startswith(text);
435 }
436 
437 void TransformActionsImpl::commitInsert(SourceLocation loc, StringRef text) {
438  addInsertion(loc, text);
439 }
440 
441 void TransformActionsImpl::commitInsertAfterToken(SourceLocation loc,
442  StringRef text) {
443  addInsertion(getLocForEndOfToken(loc, Ctx.getSourceManager(), PP), text);
444 }
445 
446 void TransformActionsImpl::commitRemove(SourceRange range) {
447  addRemoval(CharSourceRange::getTokenRange(range));
448 }
449 
450 void TransformActionsImpl::commitRemoveStmt(Stmt *S) {
451  assert(S);
452  if (StmtRemovals.count(S))
453  return; // already removed.
454 
455  if (Expr *E = dyn_cast<Expr>(S)) {
456  commitRemove(E->getSourceRange());
457  commitInsert(E->getSourceRange().getBegin(), getARCMTMacroName());
458  } else
459  commitRemove(S->getSourceRange());
460 
461  StmtRemovals.insert(S);
462 }
463 
464 void TransformActionsImpl::commitReplace(SourceRange range,
465  SourceRange replacementRange) {
466  RangeComparison comp = CharRange::compare(replacementRange, range,
467  Ctx.getSourceManager(), PP);
468  assert(comp == Range_Contained);
469  if (comp != Range_Contained)
470  return; // Although we asserted, be extra safe for release build.
471  if (range.getBegin() != replacementRange.getBegin())
472  addRemoval(CharSourceRange::getCharRange(range.getBegin(),
473  replacementRange.getBegin()));
474  if (replacementRange.getEnd() != range.getEnd())
476  getLocForEndOfToken(replacementRange.getEnd(),
477  Ctx.getSourceManager(), PP),
478  range.getEnd()));
479 }
480 void TransformActionsImpl::commitReplaceText(SourceLocation loc,
481  StringRef text,
482  StringRef replacementText) {
483  SourceManager &SM = Ctx.getSourceManager();
484  loc = SM.getExpansionLoc(loc);
485  // canReplaceText already checked if loc points at text.
486  SourceLocation afterText = loc.getLocWithOffset(text.size());
487 
488  addRemoval(CharSourceRange::getCharRange(loc, afterText));
489  commitInsert(loc, replacementText);
490 }
491 
492 void TransformActionsImpl::commitIncreaseIndentation(SourceRange range,
493  SourceLocation parentIndent) {
494  SourceManager &SM = Ctx.getSourceManager();
495  IndentationRanges.push_back(
496  std::make_pair(CharRange(CharSourceRange::getTokenRange(range),
497  SM, PP),
498  SM.getExpansionLoc(parentIndent)));
499 }
500 
501 void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs,
502  SourceRange range) {
503  CapturedDiags.clearDiagnostic(IDs, range);
504 }
505 
506 void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) {
507  SourceManager &SM = Ctx.getSourceManager();
508  loc = SM.getExpansionLoc(loc);
509  for (const CharRange &I : llvm::reverse(Removals)) {
510  if (!SM.isBeforeInTranslationUnit(loc, I.End))
511  break;
512  if (I.Begin.isBeforeInTranslationUnitThan(loc))
513  return;
514  }
515 
516  Inserts[FullSourceLoc(loc, SM)].push_back(text);
517 }
518 
519 void TransformActionsImpl::addRemoval(CharSourceRange range) {
520  CharRange newRange(range, Ctx.getSourceManager(), PP);
521  if (newRange.Begin == newRange.End)
522  return;
523 
524  Inserts.erase(Inserts.upper_bound(newRange.Begin),
525  Inserts.lower_bound(newRange.End));
526 
527  std::list<CharRange>::iterator I = Removals.end();
528  while (I != Removals.begin()) {
529  std::list<CharRange>::iterator RI = I;
530  --RI;
531  RangeComparison comp = newRange.compareWith(*RI);
532  switch (comp) {
533  case Range_Before:
534  --I;
535  break;
536  case Range_After:
537  Removals.insert(I, newRange);
538  return;
539  case Range_Contained:
540  return;
541  case Range_Contains:
542  RI->End = newRange.End;
543  LLVM_FALLTHROUGH;
544  case Range_ExtendsBegin:
545  newRange.End = RI->End;
546  Removals.erase(RI);
547  break;
548  case Range_ExtendsEnd:
549  RI->End = newRange.End;
550  return;
551  }
552  }
553 
554  Removals.insert(Removals.begin(), newRange);
555 }
556 
557 void TransformActionsImpl::applyRewrites(
559  for (InsertsMap::iterator I = Inserts.begin(), E = Inserts.end(); I!=E; ++I) {
560  SourceLocation loc = I->first;
561  for (TextsVec::iterator
562  TI = I->second.begin(), TE = I->second.end(); TI != TE; ++TI) {
563  receiver.insert(loc, *TI);
564  }
565  }
566 
567  for (std::vector<std::pair<CharRange, SourceLocation> >::iterator
568  I = IndentationRanges.begin(), E = IndentationRanges.end(); I!=E; ++I) {
569  CharSourceRange range = CharSourceRange::getCharRange(I->first.Begin,
570  I->first.End);
571  receiver.increaseIndentation(range, I->second);
572  }
573 
574  for (std::list<CharRange>::iterator
575  I = Removals.begin(), E = Removals.end(); I != E; ++I) {
576  CharSourceRange range = CharSourceRange::getCharRange(I->Begin, I->End);
577  receiver.remove(range);
578  }
579 }
580 
581 /// Stores text passed to the transformation methods to keep the string
582 /// "alive". Since the vast majority of text will be the same, we also unique
583 /// the strings using a StringMap.
584 StringRef TransformActionsImpl::getUniqueText(StringRef text) {
585  return UniqueText.insert(std::make_pair(text, false)).first->first();
586 }
587 
588 /// Computes the source location just past the end of the token at
589 /// the given source location. If the location points at a macro, the whole
590 /// macro expansion is skipped.
591 SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
592  SourceManager &SM,
593  Preprocessor &PP) {
594  if (loc.isMacroID()) {
595  CharSourceRange Exp = SM.getExpansionRange(loc);
596  if (Exp.isCharRange())
597  return Exp.getEnd();
598  loc = Exp.getEnd();
599  }
600  return PP.getLocForEndOfToken(loc);
601 }
602 
604 
606  CapturedDiagList &capturedDiags,
607  ASTContext &ctx, Preprocessor &PP)
608  : Diags(diag), CapturedDiags(capturedDiags) {
609  Impl = new TransformActionsImpl(capturedDiags, ctx, PP);
610 }
611 
613  delete static_cast<TransformActionsImpl*>(Impl);
614 }
615 
617  static_cast<TransformActionsImpl*>(Impl)->startTransaction();
618 }
619 
621  return static_cast<TransformActionsImpl*>(Impl)->commitTransaction();
622 }
623 
625  static_cast<TransformActionsImpl*>(Impl)->abortTransaction();
626 }
627 
628 
629 void TransformActions::insert(SourceLocation loc, StringRef text) {
630  static_cast<TransformActionsImpl*>(Impl)->insert(loc, text);
631 }
632 
634  StringRef text) {
635  static_cast<TransformActionsImpl*>(Impl)->insertAfterToken(loc, text);
636 }
637 
639  static_cast<TransformActionsImpl*>(Impl)->remove(range);
640 }
641 
643  static_cast<TransformActionsImpl*>(Impl)->removeStmt(S);
644 }
645 
646 void TransformActions::replace(SourceRange range, StringRef text) {
647  static_cast<TransformActionsImpl*>(Impl)->replace(range, text);
648 }
649 
651  SourceRange replacementRange) {
652  static_cast<TransformActionsImpl*>(Impl)->replace(range, replacementRange);
653 }
654 
655 void TransformActions::replaceStmt(Stmt *S, StringRef text) {
656  static_cast<TransformActionsImpl*>(Impl)->replaceStmt(S, text);
657 }
658 
660  StringRef replacementText) {
661  static_cast<TransformActionsImpl*>(Impl)->replaceText(loc, text,
662  replacementText);
663 }
664 
666  SourceLocation parentIndent) {
667  static_cast<TransformActionsImpl*>(Impl)->increaseIndentation(range,
668  parentIndent);
669 }
670 
672  SourceRange range) {
673  return static_cast<TransformActionsImpl*>(Impl)->clearDiagnostic(IDs, range);
674 }
675 
677  static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver);
678 }
679 
681  SourceRange range) {
682  assert(!static_cast<TransformActionsImpl *>(Impl)->isInTransaction() &&
683  "Errors should be emitted out of a transaction");
684  return Diags.Report(loc, diagId) << range;
685 }
686 
687 void TransformActions::reportError(StringRef message, SourceLocation loc,
688  SourceRange range) {
689  report(loc, diag::err_mt_message, range) << message;
690 }
691 
693  SourceRange range) {
694  report(loc, diag::warn_mt_message, range) << message;
695 }
696 
697 void TransformActions::reportNote(StringRef message, SourceLocation loc,
698  SourceRange range) {
699  report(loc, diag::note_mt_message, range) << message;
700 }
Defines the clang::ASTContext interface.
void reportNote(StringRef note, SourceLocation loc, SourceRange range=SourceRange())
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
Stmt - This represents one statement.
Definition: Stmt.h:66
Defines the SourceManager interface.
static StringRef getARCMTMacroName()
Definition: Internals.h:172
static CharSourceRange getTokenRange(SourceRange R)
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1290
bool hasDiagnostic(ArrayRef< unsigned > IDs, SourceRange range) const
Definition: ARCMT.cpp:58
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
RangeSelector range(RangeSelector Begin, RangeSelector End)
Selects from the start of Begin and to the end of End.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Computes the source location just past the end of the token at this source location.
SourceLocation getBegin() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:160
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:274
void applyRewrites(RewriteReceiver &receiver)
DiagnosticBuilder report(SourceLocation loc, unsigned diagId, SourceRange range=SourceRange())
void reportError(StringRef error, SourceLocation loc, SourceRange range=SourceRange())
void reportWarning(StringRef warning, SourceLocation loc, SourceRange range=SourceRange())
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
Definition: ARCMT.cpp:28
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:149
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1043
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
This represents one expression.
Definition: Expr.h:108
SourceLocation End
Represents a character-granular source range.
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
void insertAfterToken(SourceLocation loc, StringRef text)
Defines the clang::Preprocessor interface.
SourceLocation Begin
ASTEdit remove(RangeSelector S)
Removes the source selected by S.
Definition: Transformer.h:230
bool isInvalid() const
virtual void insert(SourceLocation loc, StringRef text)=0
SourceLocation getEnd() const
const SourceManager & SM
Definition: Format.cpp:1609
static CharSourceRange getCharRange(SourceRange R)
TransformActions(DiagnosticsEngine &diag, CapturedDiagList &capturedDiags, ASTContext &ctx, Preprocessor &PP)
#define false
Definition: stdbool.h:17
Kind
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
Encodes a location in the source.
void replaceStmt(Stmt *S, StringRef text)
void increaseIndentation(SourceRange range, SourceLocation parentIndent)
bool isAtStartOfMacroExpansion(SourceLocation loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the first token of the macro expansion...
bool isAtEndOfMacroExpansion(SourceLocation loc, SourceLocation *MacroEnd=nullptr) const
Returns true if the given MacroID location points at the last token of the macro expansion.
virtual void remove(CharSourceRange range)=0
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
void replaceText(SourceLocation loc, StringRef text, StringRef replacementText)
bool isMacroID() const
SourceLocation getEnd() const
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
SourceManager & getSourceManager()
Definition: ASTContext.h:675
void replace(SourceRange range, StringRef text)
void remove(SourceRange range)
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:262
void insert(SourceLocation loc, StringRef text)
A SourceLocation and its associated SourceManager.
virtual void increaseIndentation(CharSourceRange range, SourceLocation parentIndent)=0
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:125