TransformActions.cpp 23 KB

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