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