xref: /freebsd-src/contrib/llvm-project/clang/lib/ARCMigrate/TransformActions.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- TransformActions.cpp - Migration to ARC mode ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "Internals.h"
100b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
110b57cec5SDimitry Andric #include "clang/AST/Expr.h"
120b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
130b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
140b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
150b57cec5SDimitry Andric #include <map>
160b57cec5SDimitry Andric using namespace clang;
170b57cec5SDimitry Andric using namespace arcmt;
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace {
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric /// Collects transformations and merges them before applying them with
220b57cec5SDimitry Andric /// with applyRewrites(). E.g. if the same source range
230b57cec5SDimitry Andric /// is requested to be removed twice, only one rewriter remove will be invoked.
240b57cec5SDimitry Andric /// Rewrites happen in "transactions"; if one rewrite in the transaction cannot
250b57cec5SDimitry Andric /// be done (e.g. it resides in a macro) all rewrites in the transaction are
260b57cec5SDimitry Andric /// aborted.
270b57cec5SDimitry Andric /// FIXME: "Transactional" rewrites support should be baked in the Rewriter.
280b57cec5SDimitry Andric class TransformActionsImpl {
290b57cec5SDimitry Andric   CapturedDiagList &CapturedDiags;
300b57cec5SDimitry Andric   ASTContext &Ctx;
310b57cec5SDimitry Andric   Preprocessor &PP;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   bool IsInTransaction;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   enum ActionKind {
360b57cec5SDimitry Andric     Act_Insert, Act_InsertAfterToken,
370b57cec5SDimitry Andric     Act_Remove, Act_RemoveStmt,
380b57cec5SDimitry Andric     Act_Replace, Act_ReplaceText,
390b57cec5SDimitry Andric     Act_IncreaseIndentation,
400b57cec5SDimitry Andric     Act_ClearDiagnostic
410b57cec5SDimitry Andric   };
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   struct ActionData {
440b57cec5SDimitry Andric     ActionKind Kind;
450b57cec5SDimitry Andric     SourceLocation Loc;
460b57cec5SDimitry Andric     SourceRange R1, R2;
470b57cec5SDimitry Andric     StringRef Text1, Text2;
480b57cec5SDimitry Andric     Stmt *S;
490b57cec5SDimitry Andric     SmallVector<unsigned, 2> DiagIDs;
500b57cec5SDimitry Andric   };
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   std::vector<ActionData> CachedActions;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   enum RangeComparison {
550b57cec5SDimitry Andric     Range_Before,
560b57cec5SDimitry Andric     Range_After,
570b57cec5SDimitry Andric     Range_Contains,
580b57cec5SDimitry Andric     Range_Contained,
590b57cec5SDimitry Andric     Range_ExtendsBegin,
600b57cec5SDimitry Andric     Range_ExtendsEnd
610b57cec5SDimitry Andric   };
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   /// A range to remove. It is a character range.
640b57cec5SDimitry Andric   struct CharRange {
650b57cec5SDimitry Andric     FullSourceLoc Begin, End;
660b57cec5SDimitry Andric 
CharRange__anon17e9ad270111::TransformActionsImpl::CharRange670b57cec5SDimitry Andric     CharRange(CharSourceRange range, SourceManager &srcMgr, Preprocessor &PP) {
680b57cec5SDimitry Andric       SourceLocation beginLoc = range.getBegin(), endLoc = range.getEnd();
690b57cec5SDimitry Andric       assert(beginLoc.isValid() && endLoc.isValid());
700b57cec5SDimitry Andric       if (range.isTokenRange()) {
710b57cec5SDimitry Andric         Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
720b57cec5SDimitry Andric         End = FullSourceLoc(getLocForEndOfToken(endLoc, srcMgr, PP), srcMgr);
730b57cec5SDimitry Andric       } else {
740b57cec5SDimitry Andric         Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
750b57cec5SDimitry Andric         End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr);
760b57cec5SDimitry Andric       }
770b57cec5SDimitry Andric       assert(Begin.isValid() && End.isValid());
780b57cec5SDimitry Andric     }
790b57cec5SDimitry Andric 
compareWith__anon17e9ad270111::TransformActionsImpl::CharRange800b57cec5SDimitry Andric     RangeComparison compareWith(const CharRange &RHS) const {
810b57cec5SDimitry Andric       if (End.isBeforeInTranslationUnitThan(RHS.Begin))
820b57cec5SDimitry Andric         return Range_Before;
830b57cec5SDimitry Andric       if (RHS.End.isBeforeInTranslationUnitThan(Begin))
840b57cec5SDimitry Andric         return Range_After;
850b57cec5SDimitry Andric       if (!Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
860b57cec5SDimitry Andric           !RHS.End.isBeforeInTranslationUnitThan(End))
870b57cec5SDimitry Andric         return Range_Contained;
880b57cec5SDimitry Andric       if (Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
890b57cec5SDimitry Andric           RHS.End.isBeforeInTranslationUnitThan(End))
900b57cec5SDimitry Andric         return Range_Contains;
910b57cec5SDimitry Andric       if (Begin.isBeforeInTranslationUnitThan(RHS.Begin))
920b57cec5SDimitry Andric         return Range_ExtendsBegin;
930b57cec5SDimitry Andric       else
940b57cec5SDimitry Andric         return Range_ExtendsEnd;
950b57cec5SDimitry Andric     }
960b57cec5SDimitry Andric 
compare__anon17e9ad270111::TransformActionsImpl::CharRange970b57cec5SDimitry Andric     static RangeComparison compare(SourceRange LHS, SourceRange RHS,
980b57cec5SDimitry Andric                                    SourceManager &SrcMgr, Preprocessor &PP) {
990b57cec5SDimitry Andric       return CharRange(CharSourceRange::getTokenRange(LHS), SrcMgr, PP)
1000b57cec5SDimitry Andric                   .compareWith(CharRange(CharSourceRange::getTokenRange(RHS),
1010b57cec5SDimitry Andric                                             SrcMgr, PP));
1020b57cec5SDimitry Andric     }
1030b57cec5SDimitry Andric   };
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   typedef SmallVector<StringRef, 2> TextsVec;
1060b57cec5SDimitry Andric   typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare>
1070b57cec5SDimitry Andric       InsertsMap;
1080b57cec5SDimitry Andric   InsertsMap Inserts;
1090b57cec5SDimitry Andric   /// A list of ranges to remove. They are always sorted and they never
1100b57cec5SDimitry Andric   /// intersect with each other.
1110b57cec5SDimitry Andric   std::list<CharRange> Removals;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   llvm::DenseSet<Stmt *> StmtRemovals;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   std::vector<std::pair<CharRange, SourceLocation> > IndentationRanges;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   /// Keeps text passed to transformation methods.
1180b57cec5SDimitry Andric   llvm::StringMap<bool> UniqueText;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric public:
TransformActionsImpl(CapturedDiagList & capturedDiags,ASTContext & ctx,Preprocessor & PP)1210b57cec5SDimitry Andric   TransformActionsImpl(CapturedDiagList &capturedDiags,
1220b57cec5SDimitry Andric                        ASTContext &ctx, Preprocessor &PP)
1230b57cec5SDimitry Andric     : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { }
1240b57cec5SDimitry Andric 
getASTContext()1250b57cec5SDimitry Andric   ASTContext &getASTContext() { return Ctx; }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   void startTransaction();
1280b57cec5SDimitry Andric   bool commitTransaction();
1290b57cec5SDimitry Andric   void abortTransaction();
1300b57cec5SDimitry Andric 
isInTransaction() const1310b57cec5SDimitry Andric   bool isInTransaction() const { return IsInTransaction; }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   void insert(SourceLocation loc, StringRef text);
1340b57cec5SDimitry Andric   void insertAfterToken(SourceLocation loc, StringRef text);
1350b57cec5SDimitry Andric   void remove(SourceRange range);
1360b57cec5SDimitry Andric   void removeStmt(Stmt *S);
1370b57cec5SDimitry Andric   void replace(SourceRange range, StringRef text);
1380b57cec5SDimitry Andric   void replace(SourceRange range, SourceRange replacementRange);
1390b57cec5SDimitry Andric   void replaceStmt(Stmt *S, StringRef text);
1400b57cec5SDimitry Andric   void replaceText(SourceLocation loc, StringRef text,
1410b57cec5SDimitry Andric                    StringRef replacementText);
1420b57cec5SDimitry Andric   void increaseIndentation(SourceRange range,
1430b57cec5SDimitry Andric                            SourceLocation parentIndent);
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   void applyRewrites(TransformActions::RewriteReceiver &receiver);
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric private:
1500b57cec5SDimitry Andric   bool canInsert(SourceLocation loc);
1510b57cec5SDimitry Andric   bool canInsertAfterToken(SourceLocation loc);
1520b57cec5SDimitry Andric   bool canRemoveRange(SourceRange range);
1530b57cec5SDimitry Andric   bool canReplaceRange(SourceRange range, SourceRange replacementRange);
1540b57cec5SDimitry Andric   bool canReplaceText(SourceLocation loc, StringRef text);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   void commitInsert(SourceLocation loc, StringRef text);
1570b57cec5SDimitry Andric   void commitInsertAfterToken(SourceLocation loc, StringRef text);
1580b57cec5SDimitry Andric   void commitRemove(SourceRange range);
1590b57cec5SDimitry Andric   void commitRemoveStmt(Stmt *S);
1600b57cec5SDimitry Andric   void commitReplace(SourceRange range, SourceRange replacementRange);
1610b57cec5SDimitry Andric   void commitReplaceText(SourceLocation loc, StringRef text,
1620b57cec5SDimitry Andric                          StringRef replacementText);
1630b57cec5SDimitry Andric   void commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent);
1640b57cec5SDimitry Andric   void commitClearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   void addRemoval(CharSourceRange range);
1670b57cec5SDimitry Andric   void addInsertion(SourceLocation loc, StringRef text);
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   /// Stores text passed to the transformation methods to keep the string
1700b57cec5SDimitry Andric   /// "alive". Since the vast majority of text will be the same, we also unique
1710b57cec5SDimitry Andric   /// the strings using a StringMap.
1720b57cec5SDimitry Andric   StringRef getUniqueText(StringRef text);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   /// Computes the source location just past the end of the token at
1750b57cec5SDimitry Andric   /// the given source location. If the location points at a macro, the whole
1760b57cec5SDimitry Andric   /// macro expansion is skipped.
1770b57cec5SDimitry Andric   static SourceLocation getLocForEndOfToken(SourceLocation loc,
1780b57cec5SDimitry Andric                                             SourceManager &SM,Preprocessor &PP);
1790b57cec5SDimitry Andric };
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric } // anonymous namespace
1820b57cec5SDimitry Andric 
startTransaction()1830b57cec5SDimitry Andric void TransformActionsImpl::startTransaction() {
1840b57cec5SDimitry Andric   assert(!IsInTransaction &&
1850b57cec5SDimitry Andric          "Cannot start a transaction in the middle of another one");
1860b57cec5SDimitry Andric   IsInTransaction = true;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
commitTransaction()1890b57cec5SDimitry Andric bool TransformActionsImpl::commitTransaction() {
1900b57cec5SDimitry Andric   assert(IsInTransaction && "No transaction started");
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   if (CachedActions.empty()) {
1930b57cec5SDimitry Andric     IsInTransaction = false;
1940b57cec5SDimitry Andric     return false;
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   // Verify that all actions are possible otherwise abort the whole transaction.
1980b57cec5SDimitry Andric   bool AllActionsPossible = true;
1990b57cec5SDimitry Andric   for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
2000b57cec5SDimitry Andric     ActionData &act = CachedActions[i];
2010b57cec5SDimitry Andric     switch (act.Kind) {
2020b57cec5SDimitry Andric     case Act_Insert:
2030b57cec5SDimitry Andric       if (!canInsert(act.Loc))
2040b57cec5SDimitry Andric         AllActionsPossible = false;
2050b57cec5SDimitry Andric       break;
2060b57cec5SDimitry Andric     case Act_InsertAfterToken:
2070b57cec5SDimitry Andric       if (!canInsertAfterToken(act.Loc))
2080b57cec5SDimitry Andric         AllActionsPossible = false;
2090b57cec5SDimitry Andric       break;
2100b57cec5SDimitry Andric     case Act_Remove:
2110b57cec5SDimitry Andric       if (!canRemoveRange(act.R1))
2120b57cec5SDimitry Andric         AllActionsPossible = false;
2130b57cec5SDimitry Andric       break;
2140b57cec5SDimitry Andric     case Act_RemoveStmt:
2150b57cec5SDimitry Andric       assert(act.S);
2160b57cec5SDimitry Andric       if (!canRemoveRange(act.S->getSourceRange()))
2170b57cec5SDimitry Andric         AllActionsPossible = false;
2180b57cec5SDimitry Andric       break;
2190b57cec5SDimitry Andric     case Act_Replace:
2200b57cec5SDimitry Andric       if (!canReplaceRange(act.R1, act.R2))
2210b57cec5SDimitry Andric         AllActionsPossible = false;
2220b57cec5SDimitry Andric       break;
2230b57cec5SDimitry Andric     case Act_ReplaceText:
2240b57cec5SDimitry Andric       if (!canReplaceText(act.Loc, act.Text1))
2250b57cec5SDimitry Andric         AllActionsPossible = false;
2260b57cec5SDimitry Andric       break;
2270b57cec5SDimitry Andric     case Act_IncreaseIndentation:
2280b57cec5SDimitry Andric       // This is not important, we don't care if it will fail.
2290b57cec5SDimitry Andric       break;
2300b57cec5SDimitry Andric     case Act_ClearDiagnostic:
2310b57cec5SDimitry Andric       // We are just checking source rewrites.
2320b57cec5SDimitry Andric       break;
2330b57cec5SDimitry Andric     }
2340b57cec5SDimitry Andric     if (!AllActionsPossible)
2350b57cec5SDimitry Andric       break;
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   if (!AllActionsPossible) {
2390b57cec5SDimitry Andric     abortTransaction();
2400b57cec5SDimitry Andric     return true;
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
2440b57cec5SDimitry Andric     ActionData &act = CachedActions[i];
2450b57cec5SDimitry Andric     switch (act.Kind) {
2460b57cec5SDimitry Andric     case Act_Insert:
2470b57cec5SDimitry Andric       commitInsert(act.Loc, act.Text1);
2480b57cec5SDimitry Andric       break;
2490b57cec5SDimitry Andric     case Act_InsertAfterToken:
2500b57cec5SDimitry Andric       commitInsertAfterToken(act.Loc, act.Text1);
2510b57cec5SDimitry Andric       break;
2520b57cec5SDimitry Andric     case Act_Remove:
2530b57cec5SDimitry Andric       commitRemove(act.R1);
2540b57cec5SDimitry Andric       break;
2550b57cec5SDimitry Andric     case Act_RemoveStmt:
2560b57cec5SDimitry Andric       commitRemoveStmt(act.S);
2570b57cec5SDimitry Andric       break;
2580b57cec5SDimitry Andric     case Act_Replace:
2590b57cec5SDimitry Andric       commitReplace(act.R1, act.R2);
2600b57cec5SDimitry Andric       break;
2610b57cec5SDimitry Andric     case Act_ReplaceText:
2620b57cec5SDimitry Andric       commitReplaceText(act.Loc, act.Text1, act.Text2);
2630b57cec5SDimitry Andric       break;
2640b57cec5SDimitry Andric     case Act_IncreaseIndentation:
2650b57cec5SDimitry Andric       commitIncreaseIndentation(act.R1, act.Loc);
2660b57cec5SDimitry Andric       break;
2670b57cec5SDimitry Andric     case Act_ClearDiagnostic:
2680b57cec5SDimitry Andric       commitClearDiagnostic(act.DiagIDs, act.R1);
2690b57cec5SDimitry Andric       break;
2700b57cec5SDimitry Andric     }
2710b57cec5SDimitry Andric   }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   CachedActions.clear();
2740b57cec5SDimitry Andric   IsInTransaction = false;
2750b57cec5SDimitry Andric   return false;
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric 
abortTransaction()2780b57cec5SDimitry Andric void TransformActionsImpl::abortTransaction() {
2790b57cec5SDimitry Andric   assert(IsInTransaction && "No transaction started");
2800b57cec5SDimitry Andric   CachedActions.clear();
2810b57cec5SDimitry Andric   IsInTransaction = false;
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
insert(SourceLocation loc,StringRef text)2840b57cec5SDimitry Andric void TransformActionsImpl::insert(SourceLocation loc, StringRef text) {
2850b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
2860b57cec5SDimitry Andric   text = getUniqueText(text);
2870b57cec5SDimitry Andric   ActionData data;
2880b57cec5SDimitry Andric   data.Kind = Act_Insert;
2890b57cec5SDimitry Andric   data.Loc = loc;
2900b57cec5SDimitry Andric   data.Text1 = text;
2910b57cec5SDimitry Andric   CachedActions.push_back(data);
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric 
insertAfterToken(SourceLocation loc,StringRef text)2940b57cec5SDimitry Andric void TransformActionsImpl::insertAfterToken(SourceLocation loc, StringRef text) {
2950b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
2960b57cec5SDimitry Andric   text = getUniqueText(text);
2970b57cec5SDimitry Andric   ActionData data;
2980b57cec5SDimitry Andric   data.Kind = Act_InsertAfterToken;
2990b57cec5SDimitry Andric   data.Loc = loc;
3000b57cec5SDimitry Andric   data.Text1 = text;
3010b57cec5SDimitry Andric   CachedActions.push_back(data);
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
remove(SourceRange range)3040b57cec5SDimitry Andric void TransformActionsImpl::remove(SourceRange range) {
3050b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
3060b57cec5SDimitry Andric   ActionData data;
3070b57cec5SDimitry Andric   data.Kind = Act_Remove;
3080b57cec5SDimitry Andric   data.R1 = range;
3090b57cec5SDimitry Andric   CachedActions.push_back(data);
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric 
removeStmt(Stmt * S)3120b57cec5SDimitry Andric void TransformActionsImpl::removeStmt(Stmt *S) {
3130b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
3140b57cec5SDimitry Andric   ActionData data;
3150b57cec5SDimitry Andric   data.Kind = Act_RemoveStmt;
3160b57cec5SDimitry Andric   if (auto *E = dyn_cast<Expr>(S))
3170b57cec5SDimitry Andric     S = E->IgnoreImplicit(); // important for uniquing
3180b57cec5SDimitry Andric   data.S = S;
3190b57cec5SDimitry Andric   CachedActions.push_back(data);
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
replace(SourceRange range,StringRef text)3220b57cec5SDimitry Andric void TransformActionsImpl::replace(SourceRange range, StringRef text) {
3230b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
3240b57cec5SDimitry Andric   text = getUniqueText(text);
3250b57cec5SDimitry Andric   remove(range);
3260b57cec5SDimitry Andric   insert(range.getBegin(), text);
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
replace(SourceRange range,SourceRange replacementRange)3290b57cec5SDimitry Andric void TransformActionsImpl::replace(SourceRange range,
3300b57cec5SDimitry Andric                                    SourceRange replacementRange) {
3310b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
3320b57cec5SDimitry Andric   ActionData data;
3330b57cec5SDimitry Andric   data.Kind = Act_Replace;
3340b57cec5SDimitry Andric   data.R1 = range;
3350b57cec5SDimitry Andric   data.R2 = replacementRange;
3360b57cec5SDimitry Andric   CachedActions.push_back(data);
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
replaceText(SourceLocation loc,StringRef text,StringRef replacementText)3390b57cec5SDimitry Andric void TransformActionsImpl::replaceText(SourceLocation loc, StringRef text,
3400b57cec5SDimitry Andric                                        StringRef replacementText) {
3410b57cec5SDimitry Andric   text = getUniqueText(text);
3420b57cec5SDimitry Andric   replacementText = getUniqueText(replacementText);
3430b57cec5SDimitry Andric   ActionData data;
3440b57cec5SDimitry Andric   data.Kind = Act_ReplaceText;
3450b57cec5SDimitry Andric   data.Loc = loc;
3460b57cec5SDimitry Andric   data.Text1 = text;
3470b57cec5SDimitry Andric   data.Text2 = replacementText;
3480b57cec5SDimitry Andric   CachedActions.push_back(data);
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
replaceStmt(Stmt * S,StringRef text)3510b57cec5SDimitry Andric void TransformActionsImpl::replaceStmt(Stmt *S, StringRef text) {
3520b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
3530b57cec5SDimitry Andric   text = getUniqueText(text);
3540b57cec5SDimitry Andric   insert(S->getBeginLoc(), text);
3550b57cec5SDimitry Andric   removeStmt(S);
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
increaseIndentation(SourceRange range,SourceLocation parentIndent)3580b57cec5SDimitry Andric void TransformActionsImpl::increaseIndentation(SourceRange range,
3590b57cec5SDimitry Andric                                                SourceLocation parentIndent) {
3600b57cec5SDimitry Andric   if (range.isInvalid()) return;
3610b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
3620b57cec5SDimitry Andric   ActionData data;
3630b57cec5SDimitry Andric   data.Kind = Act_IncreaseIndentation;
3640b57cec5SDimitry Andric   data.R1 = range;
3650b57cec5SDimitry Andric   data.Loc = parentIndent;
3660b57cec5SDimitry Andric   CachedActions.push_back(data);
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
clearDiagnostic(ArrayRef<unsigned> IDs,SourceRange range)3690b57cec5SDimitry Andric bool TransformActionsImpl::clearDiagnostic(ArrayRef<unsigned> IDs,
3700b57cec5SDimitry Andric                                            SourceRange range) {
3710b57cec5SDimitry Andric   assert(IsInTransaction && "Actions only allowed during a transaction");
3720b57cec5SDimitry Andric   if (!CapturedDiags.hasDiagnostic(IDs, range))
3730b57cec5SDimitry Andric     return false;
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   ActionData data;
3760b57cec5SDimitry Andric   data.Kind = Act_ClearDiagnostic;
3770b57cec5SDimitry Andric   data.R1 = range;
3780b57cec5SDimitry Andric   data.DiagIDs.append(IDs.begin(), IDs.end());
3790b57cec5SDimitry Andric   CachedActions.push_back(data);
3800b57cec5SDimitry Andric   return true;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
canInsert(SourceLocation loc)3830b57cec5SDimitry Andric bool TransformActionsImpl::canInsert(SourceLocation loc) {
3840b57cec5SDimitry Andric   if (loc.isInvalid())
3850b57cec5SDimitry Andric     return false;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   SourceManager &SM = Ctx.getSourceManager();
3880b57cec5SDimitry Andric   if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
3890b57cec5SDimitry Andric     return false;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   if (loc.isFileID())
3920b57cec5SDimitry Andric     return true;
3930b57cec5SDimitry Andric   return PP.isAtStartOfMacroExpansion(loc);
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
canInsertAfterToken(SourceLocation loc)3960b57cec5SDimitry Andric bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) {
3970b57cec5SDimitry Andric   if (loc.isInvalid())
3980b57cec5SDimitry Andric     return false;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   SourceManager &SM = Ctx.getSourceManager();
4010b57cec5SDimitry Andric   if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
4020b57cec5SDimitry Andric     return false;
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   if (loc.isFileID())
4050b57cec5SDimitry Andric     return true;
4060b57cec5SDimitry Andric   return PP.isAtEndOfMacroExpansion(loc);
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
canRemoveRange(SourceRange range)4090b57cec5SDimitry Andric bool TransformActionsImpl::canRemoveRange(SourceRange range) {
4100b57cec5SDimitry Andric   return canInsert(range.getBegin()) && canInsertAfterToken(range.getEnd());
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric 
canReplaceRange(SourceRange range,SourceRange replacementRange)4130b57cec5SDimitry Andric bool TransformActionsImpl::canReplaceRange(SourceRange range,
4140b57cec5SDimitry Andric                                            SourceRange replacementRange) {
4150b57cec5SDimitry Andric   return canRemoveRange(range) && canRemoveRange(replacementRange);
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
canReplaceText(SourceLocation loc,StringRef text)4180b57cec5SDimitry Andric bool TransformActionsImpl::canReplaceText(SourceLocation loc, StringRef text) {
4190b57cec5SDimitry Andric   if (!canInsert(loc))
4200b57cec5SDimitry Andric     return false;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   SourceManager &SM = Ctx.getSourceManager();
4230b57cec5SDimitry Andric   loc = SM.getExpansionLoc(loc);
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   // Break down the source location.
4260b57cec5SDimitry Andric   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   // Try to load the file buffer.
4290b57cec5SDimitry Andric   bool invalidTemp = false;
4300b57cec5SDimitry Andric   StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
4310b57cec5SDimitry Andric   if (invalidTemp)
4320b57cec5SDimitry Andric     return false;
4330b57cec5SDimitry Andric 
434*5f757f3fSDimitry Andric   return file.substr(locInfo.second).starts_with(text);
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric 
commitInsert(SourceLocation loc,StringRef text)4370b57cec5SDimitry Andric void TransformActionsImpl::commitInsert(SourceLocation loc, StringRef text) {
4380b57cec5SDimitry Andric   addInsertion(loc, text);
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric 
commitInsertAfterToken(SourceLocation loc,StringRef text)4410b57cec5SDimitry Andric void TransformActionsImpl::commitInsertAfterToken(SourceLocation loc,
4420b57cec5SDimitry Andric                                                   StringRef text) {
4430b57cec5SDimitry Andric   addInsertion(getLocForEndOfToken(loc, Ctx.getSourceManager(), PP), text);
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
commitRemove(SourceRange range)4460b57cec5SDimitry Andric void TransformActionsImpl::commitRemove(SourceRange range) {
4470b57cec5SDimitry Andric   addRemoval(CharSourceRange::getTokenRange(range));
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
commitRemoveStmt(Stmt * S)4500b57cec5SDimitry Andric void TransformActionsImpl::commitRemoveStmt(Stmt *S) {
4510b57cec5SDimitry Andric   assert(S);
4520b57cec5SDimitry Andric   if (StmtRemovals.count(S))
4530b57cec5SDimitry Andric     return; // already removed.
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric   if (Expr *E = dyn_cast<Expr>(S)) {
4560b57cec5SDimitry Andric     commitRemove(E->getSourceRange());
4570b57cec5SDimitry Andric     commitInsert(E->getSourceRange().getBegin(), getARCMTMacroName());
4580b57cec5SDimitry Andric   } else
4590b57cec5SDimitry Andric     commitRemove(S->getSourceRange());
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   StmtRemovals.insert(S);
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric 
commitReplace(SourceRange range,SourceRange replacementRange)4640b57cec5SDimitry Andric void TransformActionsImpl::commitReplace(SourceRange range,
4650b57cec5SDimitry Andric                                          SourceRange replacementRange) {
4660b57cec5SDimitry Andric   RangeComparison comp = CharRange::compare(replacementRange, range,
4670b57cec5SDimitry Andric                                                Ctx.getSourceManager(), PP);
4680b57cec5SDimitry Andric   assert(comp == Range_Contained);
4690b57cec5SDimitry Andric   if (comp != Range_Contained)
4700b57cec5SDimitry Andric     return; // Although we asserted, be extra safe for release build.
4710b57cec5SDimitry Andric   if (range.getBegin() != replacementRange.getBegin())
4720b57cec5SDimitry Andric     addRemoval(CharSourceRange::getCharRange(range.getBegin(),
4730b57cec5SDimitry Andric                                              replacementRange.getBegin()));
4740b57cec5SDimitry Andric   if (replacementRange.getEnd() != range.getEnd())
4750b57cec5SDimitry Andric     addRemoval(CharSourceRange::getTokenRange(
4760b57cec5SDimitry Andric                                   getLocForEndOfToken(replacementRange.getEnd(),
4770b57cec5SDimitry Andric                                                       Ctx.getSourceManager(), PP),
4780b57cec5SDimitry Andric                                   range.getEnd()));
4790b57cec5SDimitry Andric }
commitReplaceText(SourceLocation loc,StringRef text,StringRef replacementText)4800b57cec5SDimitry Andric void TransformActionsImpl::commitReplaceText(SourceLocation loc,
4810b57cec5SDimitry Andric                                              StringRef text,
4820b57cec5SDimitry Andric                                              StringRef replacementText) {
4830b57cec5SDimitry Andric   SourceManager &SM = Ctx.getSourceManager();
4840b57cec5SDimitry Andric   loc = SM.getExpansionLoc(loc);
4850b57cec5SDimitry Andric   // canReplaceText already checked if loc points at text.
4860b57cec5SDimitry Andric   SourceLocation afterText = loc.getLocWithOffset(text.size());
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   addRemoval(CharSourceRange::getCharRange(loc, afterText));
4890b57cec5SDimitry Andric   commitInsert(loc, replacementText);
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric 
commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent)4920b57cec5SDimitry Andric void TransformActionsImpl::commitIncreaseIndentation(SourceRange range,
4930b57cec5SDimitry Andric                                                   SourceLocation parentIndent) {
4940b57cec5SDimitry Andric   SourceManager &SM = Ctx.getSourceManager();
4950b57cec5SDimitry Andric   IndentationRanges.push_back(
4960b57cec5SDimitry Andric                  std::make_pair(CharRange(CharSourceRange::getTokenRange(range),
4970b57cec5SDimitry Andric                                           SM, PP),
4980b57cec5SDimitry Andric                                 SM.getExpansionLoc(parentIndent)));
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric 
commitClearDiagnostic(ArrayRef<unsigned> IDs,SourceRange range)5010b57cec5SDimitry Andric void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs,
5020b57cec5SDimitry Andric                                                  SourceRange range) {
5030b57cec5SDimitry Andric   CapturedDiags.clearDiagnostic(IDs, range);
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
addInsertion(SourceLocation loc,StringRef text)5060b57cec5SDimitry Andric void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) {
5070b57cec5SDimitry Andric   SourceManager &SM = Ctx.getSourceManager();
5080b57cec5SDimitry Andric   loc = SM.getExpansionLoc(loc);
5090b57cec5SDimitry Andric   for (const CharRange &I : llvm::reverse(Removals)) {
5100b57cec5SDimitry Andric     if (!SM.isBeforeInTranslationUnit(loc, I.End))
5110b57cec5SDimitry Andric       break;
5120b57cec5SDimitry Andric     if (I.Begin.isBeforeInTranslationUnitThan(loc))
5130b57cec5SDimitry Andric       return;
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   Inserts[FullSourceLoc(loc, SM)].push_back(text);
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
addRemoval(CharSourceRange range)5190b57cec5SDimitry Andric void TransformActionsImpl::addRemoval(CharSourceRange range) {
5200b57cec5SDimitry Andric   CharRange newRange(range, Ctx.getSourceManager(), PP);
5210b57cec5SDimitry Andric   if (newRange.Begin == newRange.End)
5220b57cec5SDimitry Andric     return;
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   Inserts.erase(Inserts.upper_bound(newRange.Begin),
5250b57cec5SDimitry Andric                 Inserts.lower_bound(newRange.End));
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   std::list<CharRange>::iterator I = Removals.end();
5280b57cec5SDimitry Andric   while (I != Removals.begin()) {
5290b57cec5SDimitry Andric     std::list<CharRange>::iterator RI = I;
5300b57cec5SDimitry Andric     --RI;
5310b57cec5SDimitry Andric     RangeComparison comp = newRange.compareWith(*RI);
5320b57cec5SDimitry Andric     switch (comp) {
5330b57cec5SDimitry Andric     case Range_Before:
5340b57cec5SDimitry Andric       --I;
5350b57cec5SDimitry Andric       break;
5360b57cec5SDimitry Andric     case Range_After:
5370b57cec5SDimitry Andric       Removals.insert(I, newRange);
5380b57cec5SDimitry Andric       return;
5390b57cec5SDimitry Andric     case Range_Contained:
5400b57cec5SDimitry Andric       return;
5410b57cec5SDimitry Andric     case Range_Contains:
5420b57cec5SDimitry Andric       RI->End = newRange.End;
543bdd1243dSDimitry Andric       [[fallthrough]];
5440b57cec5SDimitry Andric     case Range_ExtendsBegin:
5450b57cec5SDimitry Andric       newRange.End = RI->End;
5460b57cec5SDimitry Andric       Removals.erase(RI);
5470b57cec5SDimitry Andric       break;
5480b57cec5SDimitry Andric     case Range_ExtendsEnd:
5490b57cec5SDimitry Andric       RI->End = newRange.End;
5500b57cec5SDimitry Andric       return;
5510b57cec5SDimitry Andric     }
5520b57cec5SDimitry Andric   }
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   Removals.insert(Removals.begin(), newRange);
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric 
applyRewrites(TransformActions::RewriteReceiver & receiver)5570b57cec5SDimitry Andric void TransformActionsImpl::applyRewrites(
5580b57cec5SDimitry Andric                                   TransformActions::RewriteReceiver &receiver) {
5590b57cec5SDimitry Andric   for (InsertsMap::iterator I = Inserts.begin(), E = Inserts.end(); I!=E; ++I) {
5600b57cec5SDimitry Andric     SourceLocation loc = I->first;
5610b57cec5SDimitry Andric     for (TextsVec::iterator
5620b57cec5SDimitry Andric            TI = I->second.begin(), TE = I->second.end(); TI != TE; ++TI) {
5630b57cec5SDimitry Andric       receiver.insert(loc, *TI);
5640b57cec5SDimitry Andric     }
5650b57cec5SDimitry Andric   }
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   for (std::vector<std::pair<CharRange, SourceLocation> >::iterator
5680b57cec5SDimitry Andric        I = IndentationRanges.begin(), E = IndentationRanges.end(); I!=E; ++I) {
5690b57cec5SDimitry Andric     CharSourceRange range = CharSourceRange::getCharRange(I->first.Begin,
5700b57cec5SDimitry Andric                                                           I->first.End);
5710b57cec5SDimitry Andric     receiver.increaseIndentation(range, I->second);
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   for (std::list<CharRange>::iterator
5750b57cec5SDimitry Andric          I = Removals.begin(), E = Removals.end(); I != E; ++I) {
5760b57cec5SDimitry Andric     CharSourceRange range = CharSourceRange::getCharRange(I->Begin, I->End);
5770b57cec5SDimitry Andric     receiver.remove(range);
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric /// Stores text passed to the transformation methods to keep the string
5820b57cec5SDimitry Andric /// "alive". Since the vast majority of text will be the same, we also unique
5830b57cec5SDimitry Andric /// the strings using a StringMap.
getUniqueText(StringRef text)5840b57cec5SDimitry Andric StringRef TransformActionsImpl::getUniqueText(StringRef text) {
5850b57cec5SDimitry Andric   return UniqueText.insert(std::make_pair(text, false)).first->first();
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric /// Computes the source location just past the end of the token at
5890b57cec5SDimitry Andric /// the given source location. If the location points at a macro, the whole
5900b57cec5SDimitry Andric /// macro expansion is skipped.
getLocForEndOfToken(SourceLocation loc,SourceManager & SM,Preprocessor & PP)5910b57cec5SDimitry Andric SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
5920b57cec5SDimitry Andric                                                          SourceManager &SM,
5930b57cec5SDimitry Andric                                                          Preprocessor &PP) {
5940b57cec5SDimitry Andric   if (loc.isMacroID()) {
5950b57cec5SDimitry Andric     CharSourceRange Exp = SM.getExpansionRange(loc);
5960b57cec5SDimitry Andric     if (Exp.isCharRange())
5970b57cec5SDimitry Andric       return Exp.getEnd();
5980b57cec5SDimitry Andric     loc = Exp.getEnd();
5990b57cec5SDimitry Andric   }
6000b57cec5SDimitry Andric   return PP.getLocForEndOfToken(loc);
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
~RewriteReceiver()6030b57cec5SDimitry Andric TransformActions::RewriteReceiver::~RewriteReceiver() { }
6040b57cec5SDimitry Andric 
TransformActions(DiagnosticsEngine & diag,CapturedDiagList & capturedDiags,ASTContext & ctx,Preprocessor & PP)6050b57cec5SDimitry Andric TransformActions::TransformActions(DiagnosticsEngine &diag,
6060b57cec5SDimitry Andric                                    CapturedDiagList &capturedDiags,
6070b57cec5SDimitry Andric                                    ASTContext &ctx, Preprocessor &PP)
6080b57cec5SDimitry Andric     : Diags(diag), CapturedDiags(capturedDiags) {
6090b57cec5SDimitry Andric   Impl = new TransformActionsImpl(capturedDiags, ctx, PP);
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
~TransformActions()6120b57cec5SDimitry Andric TransformActions::~TransformActions() {
6130b57cec5SDimitry Andric   delete static_cast<TransformActionsImpl*>(Impl);
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric 
startTransaction()6160b57cec5SDimitry Andric void TransformActions::startTransaction() {
6170b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->startTransaction();
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
commitTransaction()6200b57cec5SDimitry Andric bool TransformActions::commitTransaction() {
6210b57cec5SDimitry Andric   return static_cast<TransformActionsImpl*>(Impl)->commitTransaction();
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
abortTransaction()6240b57cec5SDimitry Andric void TransformActions::abortTransaction() {
6250b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->abortTransaction();
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric 
insert(SourceLocation loc,StringRef text)6290b57cec5SDimitry Andric void TransformActions::insert(SourceLocation loc, StringRef text) {
6300b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->insert(loc, text);
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric 
insertAfterToken(SourceLocation loc,StringRef text)6330b57cec5SDimitry Andric void TransformActions::insertAfterToken(SourceLocation loc,
6340b57cec5SDimitry Andric                                         StringRef text) {
6350b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->insertAfterToken(loc, text);
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric 
remove(SourceRange range)6380b57cec5SDimitry Andric void TransformActions::remove(SourceRange range) {
6390b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->remove(range);
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
removeStmt(Stmt * S)6420b57cec5SDimitry Andric void TransformActions::removeStmt(Stmt *S) {
6430b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->removeStmt(S);
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric 
replace(SourceRange range,StringRef text)6460b57cec5SDimitry Andric void TransformActions::replace(SourceRange range, StringRef text) {
6470b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->replace(range, text);
6480b57cec5SDimitry Andric }
6490b57cec5SDimitry Andric 
replace(SourceRange range,SourceRange replacementRange)6500b57cec5SDimitry Andric void TransformActions::replace(SourceRange range,
6510b57cec5SDimitry Andric                                SourceRange replacementRange) {
6520b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->replace(range, replacementRange);
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
replaceStmt(Stmt * S,StringRef text)6550b57cec5SDimitry Andric void TransformActions::replaceStmt(Stmt *S, StringRef text) {
6560b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->replaceStmt(S, text);
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric 
replaceText(SourceLocation loc,StringRef text,StringRef replacementText)6590b57cec5SDimitry Andric void TransformActions::replaceText(SourceLocation loc, StringRef text,
6600b57cec5SDimitry Andric                                    StringRef replacementText) {
6610b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->replaceText(loc, text,
6620b57cec5SDimitry Andric                                                         replacementText);
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric 
increaseIndentation(SourceRange range,SourceLocation parentIndent)6650b57cec5SDimitry Andric void TransformActions::increaseIndentation(SourceRange range,
6660b57cec5SDimitry Andric                                            SourceLocation parentIndent) {
6670b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->increaseIndentation(range,
6680b57cec5SDimitry Andric                                                                 parentIndent);
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
clearDiagnostic(ArrayRef<unsigned> IDs,SourceRange range)6710b57cec5SDimitry Andric bool TransformActions::clearDiagnostic(ArrayRef<unsigned> IDs,
6720b57cec5SDimitry Andric                                        SourceRange range) {
6730b57cec5SDimitry Andric   return static_cast<TransformActionsImpl*>(Impl)->clearDiagnostic(IDs, range);
6740b57cec5SDimitry Andric }
6750b57cec5SDimitry Andric 
applyRewrites(RewriteReceiver & receiver)6760b57cec5SDimitry Andric void TransformActions::applyRewrites(RewriteReceiver &receiver) {
6770b57cec5SDimitry Andric   static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver);
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric 
report(SourceLocation loc,unsigned diagId,SourceRange range)6800b57cec5SDimitry Andric DiagnosticBuilder TransformActions::report(SourceLocation loc, unsigned diagId,
6810b57cec5SDimitry Andric                                            SourceRange range) {
6820b57cec5SDimitry Andric   assert(!static_cast<TransformActionsImpl *>(Impl)->isInTransaction() &&
6830b57cec5SDimitry Andric          "Errors should be emitted out of a transaction");
6840b57cec5SDimitry Andric   return Diags.Report(loc, diagId) << range;
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
reportError(StringRef message,SourceLocation loc,SourceRange range)6870b57cec5SDimitry Andric void TransformActions::reportError(StringRef message, SourceLocation loc,
6880b57cec5SDimitry Andric                                    SourceRange range) {
6890b57cec5SDimitry Andric   report(loc, diag::err_mt_message, range) << message;
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric 
reportWarning(StringRef message,SourceLocation loc,SourceRange range)6920b57cec5SDimitry Andric void TransformActions::reportWarning(StringRef message, SourceLocation loc,
6930b57cec5SDimitry Andric                                      SourceRange range) {
6940b57cec5SDimitry Andric   report(loc, diag::warn_mt_message, range) << message;
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
reportNote(StringRef message,SourceLocation loc,SourceRange range)6970b57cec5SDimitry Andric void TransformActions::reportNote(StringRef message, SourceLocation loc,
6980b57cec5SDimitry Andric                                   SourceRange range) {
6990b57cec5SDimitry Andric   report(loc, diag::note_mt_message, range) << message;
7000b57cec5SDimitry Andric }
701