clang API Documentation
00001 //===--- ARCMT.cpp - Migration to ARC mode --------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "Internals.h" 00011 #include "clang/AST/ASTContext.h" 00012 #include "clang/AST/Expr.h" 00013 #include "clang/Basic/SourceManager.h" 00014 #include "clang/Lex/Preprocessor.h" 00015 #include "llvm/ADT/DenseSet.h" 00016 #include <map> 00017 using namespace clang; 00018 using namespace arcmt; 00019 00020 namespace { 00021 00022 /// \brief Collects transformations and merges them before applying them with 00023 /// with applyRewrites(). E.g. if the same source range 00024 /// is requested to be removed twice, only one rewriter remove will be invoked. 00025 /// Rewrites happen in "transactions"; if one rewrite in the transaction cannot 00026 /// be done (e.g. it resides in a macro) all rewrites in the transaction are 00027 /// aborted. 00028 /// FIXME: "Transactional" rewrites support should be baked in the Rewriter. 00029 class TransformActionsImpl { 00030 CapturedDiagList &CapturedDiags; 00031 ASTContext &Ctx; 00032 Preprocessor &PP; 00033 00034 bool IsInTransaction; 00035 00036 enum ActionKind { 00037 Act_Insert, Act_InsertAfterToken, 00038 Act_Remove, Act_RemoveStmt, 00039 Act_Replace, Act_ReplaceText, 00040 Act_IncreaseIndentation, 00041 Act_ClearDiagnostic 00042 }; 00043 00044 struct ActionData { 00045 ActionKind Kind; 00046 SourceLocation Loc; 00047 SourceRange R1, R2; 00048 StringRef Text1, Text2; 00049 Stmt *S; 00050 SmallVector<unsigned, 2> DiagIDs; 00051 }; 00052 00053 std::vector<ActionData> CachedActions; 00054 00055 enum RangeComparison { 00056 Range_Before, 00057 Range_After, 00058 Range_Contains, 00059 Range_Contained, 00060 Range_ExtendsBegin, 00061 Range_ExtendsEnd 00062 }; 00063 00064 /// \brief A range to remove. It is a character range. 00065 struct CharRange { 00066 FullSourceLoc Begin, End; 00067 00068 CharRange(CharSourceRange range, SourceManager &srcMgr, Preprocessor &PP) { 00069 SourceLocation beginLoc = range.getBegin(), endLoc = range.getEnd(); 00070 assert(beginLoc.isValid() && endLoc.isValid()); 00071 if (range.isTokenRange()) { 00072 Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr); 00073 End = FullSourceLoc(getLocForEndOfToken(endLoc, srcMgr, PP), srcMgr); 00074 } else { 00075 Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr); 00076 End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr); 00077 } 00078 assert(Begin.isValid() && End.isValid()); 00079 } 00080 00081 RangeComparison compareWith(const CharRange &RHS) const { 00082 if (End.isBeforeInTranslationUnitThan(RHS.Begin)) 00083 return Range_Before; 00084 if (RHS.End.isBeforeInTranslationUnitThan(Begin)) 00085 return Range_After; 00086 if (!Begin.isBeforeInTranslationUnitThan(RHS.Begin) && 00087 !RHS.End.isBeforeInTranslationUnitThan(End)) 00088 return Range_Contained; 00089 if (Begin.isBeforeInTranslationUnitThan(RHS.Begin) && 00090 RHS.End.isBeforeInTranslationUnitThan(End)) 00091 return Range_Contains; 00092 if (Begin.isBeforeInTranslationUnitThan(RHS.Begin)) 00093 return Range_ExtendsBegin; 00094 else 00095 return Range_ExtendsEnd; 00096 } 00097 00098 static RangeComparison compare(SourceRange LHS, SourceRange RHS, 00099 SourceManager &SrcMgr, Preprocessor &PP) { 00100 return CharRange(CharSourceRange::getTokenRange(LHS), SrcMgr, PP) 00101 .compareWith(CharRange(CharSourceRange::getTokenRange(RHS), 00102 SrcMgr, PP)); 00103 } 00104 }; 00105 00106 typedef SmallVector<StringRef, 2> TextsVec; 00107 typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare> 00108 InsertsMap; 00109 InsertsMap Inserts; 00110 /// \brief A list of ranges to remove. They are always sorted and they never 00111 /// intersect with each other. 00112 std::list<CharRange> Removals; 00113 00114 llvm::DenseSet<Stmt *> StmtRemovals; 00115 00116 std::vector<std::pair<CharRange, SourceLocation> > IndentationRanges; 00117 00118 /// \brief Keeps text passed to transformation methods. 00119 llvm::StringMap<bool> UniqueText; 00120 00121 public: 00122 TransformActionsImpl(CapturedDiagList &capturedDiags, 00123 ASTContext &ctx, Preprocessor &PP) 00124 : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { } 00125 00126 ASTContext &getASTContext() { return Ctx; } 00127 00128 void startTransaction(); 00129 bool commitTransaction(); 00130 void abortTransaction(); 00131 00132 bool isInTransaction() const { return IsInTransaction; } 00133 00134 void insert(SourceLocation loc, StringRef text); 00135 void insertAfterToken(SourceLocation loc, StringRef text); 00136 void remove(SourceRange range); 00137 void removeStmt(Stmt *S); 00138 void replace(SourceRange range, StringRef text); 00139 void replace(SourceRange range, SourceRange replacementRange); 00140 void replaceStmt(Stmt *S, StringRef text); 00141 void replaceText(SourceLocation loc, StringRef text, 00142 StringRef replacementText); 00143 void increaseIndentation(SourceRange range, 00144 SourceLocation parentIndent); 00145 00146 bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range); 00147 00148 void applyRewrites(TransformActions::RewriteReceiver &receiver); 00149 00150 private: 00151 bool canInsert(SourceLocation loc); 00152 bool canInsertAfterToken(SourceLocation loc); 00153 bool canRemoveRange(SourceRange range); 00154 bool canReplaceRange(SourceRange range, SourceRange replacementRange); 00155 bool canReplaceText(SourceLocation loc, StringRef text); 00156 00157 void commitInsert(SourceLocation loc, StringRef text); 00158 void commitInsertAfterToken(SourceLocation loc, StringRef text); 00159 void commitRemove(SourceRange range); 00160 void commitRemoveStmt(Stmt *S); 00161 void commitReplace(SourceRange range, SourceRange replacementRange); 00162 void commitReplaceText(SourceLocation loc, StringRef text, 00163 StringRef replacementText); 00164 void commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent); 00165 void commitClearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range); 00166 00167 void addRemoval(CharSourceRange range); 00168 void addInsertion(SourceLocation loc, StringRef text); 00169 00170 /// \brief Stores text passed to the transformation methods to keep the string 00171 /// "alive". Since the vast majority of text will be the same, we also unique 00172 /// the strings using a StringMap. 00173 StringRef getUniqueText(StringRef text); 00174 00175 /// \brief Computes the source location just past the end of the token at 00176 /// the given source location. If the location points at a macro, the whole 00177 /// macro expansion is skipped. 00178 static SourceLocation getLocForEndOfToken(SourceLocation loc, 00179 SourceManager &SM,Preprocessor &PP); 00180 }; 00181 00182 } // anonymous namespace 00183 00184 void TransformActionsImpl::startTransaction() { 00185 assert(!IsInTransaction && 00186 "Cannot start a transaction in the middle of another one"); 00187 IsInTransaction = true; 00188 } 00189 00190 bool TransformActionsImpl::commitTransaction() { 00191 assert(IsInTransaction && "No transaction started"); 00192 00193 if (CachedActions.empty()) { 00194 IsInTransaction = false; 00195 return false; 00196 } 00197 00198 // Verify that all actions are possible otherwise abort the whole transaction. 00199 bool AllActionsPossible = true; 00200 for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) { 00201 ActionData &act = CachedActions[i]; 00202 switch (act.Kind) { 00203 case Act_Insert: 00204 if (!canInsert(act.Loc)) 00205 AllActionsPossible = false; 00206 break; 00207 case Act_InsertAfterToken: 00208 if (!canInsertAfterToken(act.Loc)) 00209 AllActionsPossible = false; 00210 break; 00211 case Act_Remove: 00212 if (!canRemoveRange(act.R1)) 00213 AllActionsPossible = false; 00214 break; 00215 case Act_RemoveStmt: 00216 assert(act.S); 00217 if (!canRemoveRange(act.S->getSourceRange())) 00218 AllActionsPossible = false; 00219 break; 00220 case Act_Replace: 00221 if (!canReplaceRange(act.R1, act.R2)) 00222 AllActionsPossible = false; 00223 break; 00224 case Act_ReplaceText: 00225 if (!canReplaceText(act.Loc, act.Text1)) 00226 AllActionsPossible = false; 00227 break; 00228 case Act_IncreaseIndentation: 00229 // This is not important, we don't care if it will fail. 00230 break; 00231 case Act_ClearDiagnostic: 00232 // We are just checking source rewrites. 00233 break; 00234 } 00235 if (!AllActionsPossible) 00236 break; 00237 } 00238 00239 if (!AllActionsPossible) { 00240 abortTransaction(); 00241 return true; 00242 } 00243 00244 for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) { 00245 ActionData &act = CachedActions[i]; 00246 switch (act.Kind) { 00247 case Act_Insert: 00248 commitInsert(act.Loc, act.Text1); 00249 break; 00250 case Act_InsertAfterToken: 00251 commitInsertAfterToken(act.Loc, act.Text1); 00252 break; 00253 case Act_Remove: 00254 commitRemove(act.R1); 00255 break; 00256 case Act_RemoveStmt: 00257 commitRemoveStmt(act.S); 00258 break; 00259 case Act_Replace: 00260 commitReplace(act.R1, act.R2); 00261 break; 00262 case Act_ReplaceText: 00263 commitReplaceText(act.Loc, act.Text1, act.Text2); 00264 break; 00265 case Act_IncreaseIndentation: 00266 commitIncreaseIndentation(act.R1, act.Loc); 00267 break; 00268 case Act_ClearDiagnostic: 00269 commitClearDiagnostic(act.DiagIDs, act.R1); 00270 break; 00271 } 00272 } 00273 00274 CachedActions.clear(); 00275 IsInTransaction = false; 00276 return false; 00277 } 00278 00279 void TransformActionsImpl::abortTransaction() { 00280 assert(IsInTransaction && "No transaction started"); 00281 CachedActions.clear(); 00282 IsInTransaction = false; 00283 } 00284 00285 void TransformActionsImpl::insert(SourceLocation loc, StringRef text) { 00286 assert(IsInTransaction && "Actions only allowed during a transaction"); 00287 text = getUniqueText(text); 00288 ActionData data; 00289 data.Kind = Act_Insert; 00290 data.Loc = loc; 00291 data.Text1 = text; 00292 CachedActions.push_back(data); 00293 } 00294 00295 void TransformActionsImpl::insertAfterToken(SourceLocation loc, StringRef text) { 00296 assert(IsInTransaction && "Actions only allowed during a transaction"); 00297 text = getUniqueText(text); 00298 ActionData data; 00299 data.Kind = Act_InsertAfterToken; 00300 data.Loc = loc; 00301 data.Text1 = text; 00302 CachedActions.push_back(data); 00303 } 00304 00305 void TransformActionsImpl::remove(SourceRange range) { 00306 assert(IsInTransaction && "Actions only allowed during a transaction"); 00307 ActionData data; 00308 data.Kind = Act_Remove; 00309 data.R1 = range; 00310 CachedActions.push_back(data); 00311 } 00312 00313 void TransformActionsImpl::removeStmt(Stmt *S) { 00314 assert(IsInTransaction && "Actions only allowed during a transaction"); 00315 ActionData data; 00316 data.Kind = Act_RemoveStmt; 00317 data.S = S->IgnoreImplicit(); // important for uniquing 00318 CachedActions.push_back(data); 00319 } 00320 00321 void TransformActionsImpl::replace(SourceRange range, StringRef text) { 00322 assert(IsInTransaction && "Actions only allowed during a transaction"); 00323 text = getUniqueText(text); 00324 remove(range); 00325 insert(range.getBegin(), text); 00326 } 00327 00328 void TransformActionsImpl::replace(SourceRange range, 00329 SourceRange replacementRange) { 00330 assert(IsInTransaction && "Actions only allowed during a transaction"); 00331 ActionData data; 00332 data.Kind = Act_Replace; 00333 data.R1 = range; 00334 data.R2 = replacementRange; 00335 CachedActions.push_back(data); 00336 } 00337 00338 void TransformActionsImpl::replaceText(SourceLocation loc, StringRef text, 00339 StringRef replacementText) { 00340 text = getUniqueText(text); 00341 replacementText = getUniqueText(replacementText); 00342 ActionData data; 00343 data.Kind = Act_ReplaceText; 00344 data.Loc = loc; 00345 data.Text1 = text; 00346 data.Text2 = replacementText; 00347 CachedActions.push_back(data); 00348 } 00349 00350 void TransformActionsImpl::replaceStmt(Stmt *S, StringRef text) { 00351 assert(IsInTransaction && "Actions only allowed during a transaction"); 00352 text = getUniqueText(text); 00353 insert(S->getLocStart(), text); 00354 removeStmt(S); 00355 } 00356 00357 void TransformActionsImpl::increaseIndentation(SourceRange range, 00358 SourceLocation parentIndent) { 00359 if (range.isInvalid()) return; 00360 assert(IsInTransaction && "Actions only allowed during a transaction"); 00361 ActionData data; 00362 data.Kind = Act_IncreaseIndentation; 00363 data.R1 = range; 00364 data.Loc = parentIndent; 00365 CachedActions.push_back(data); 00366 } 00367 00368 bool TransformActionsImpl::clearDiagnostic(ArrayRef<unsigned> IDs, 00369 SourceRange range) { 00370 assert(IsInTransaction && "Actions only allowed during a transaction"); 00371 if (!CapturedDiags.hasDiagnostic(IDs, range)) 00372 return false; 00373 00374 ActionData data; 00375 data.Kind = Act_ClearDiagnostic; 00376 data.R1 = range; 00377 data.DiagIDs.append(IDs.begin(), IDs.end()); 00378 CachedActions.push_back(data); 00379 return true; 00380 } 00381 00382 bool TransformActionsImpl::canInsert(SourceLocation loc) { 00383 if (loc.isInvalid()) 00384 return false; 00385 00386 SourceManager &SM = Ctx.getSourceManager(); 00387 if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) 00388 return false; 00389 00390 if (loc.isFileID()) 00391 return true; 00392 return PP.isAtStartOfMacroExpansion(loc); 00393 } 00394 00395 bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) { 00396 if (loc.isInvalid()) 00397 return false; 00398 00399 SourceManager &SM = Ctx.getSourceManager(); 00400 if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) 00401 return false; 00402 00403 if (loc.isFileID()) 00404 return true; 00405 return PP.isAtEndOfMacroExpansion(loc); 00406 } 00407 00408 bool TransformActionsImpl::canRemoveRange(SourceRange range) { 00409 return canInsert(range.getBegin()) && canInsertAfterToken(range.getEnd()); 00410 } 00411 00412 bool TransformActionsImpl::canReplaceRange(SourceRange range, 00413 SourceRange replacementRange) { 00414 return canRemoveRange(range) && canRemoveRange(replacementRange); 00415 } 00416 00417 bool TransformActionsImpl::canReplaceText(SourceLocation loc, StringRef text) { 00418 if (!canInsert(loc)) 00419 return false; 00420 00421 SourceManager &SM = Ctx.getSourceManager(); 00422 loc = SM.getExpansionLoc(loc); 00423 00424 // Break down the source location. 00425 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); 00426 00427 // Try to load the file buffer. 00428 bool invalidTemp = false; 00429 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 00430 if (invalidTemp) 00431 return false; 00432 00433 return file.substr(locInfo.second).startswith(text); 00434 } 00435 00436 void TransformActionsImpl::commitInsert(SourceLocation loc, StringRef text) { 00437 addInsertion(loc, text); 00438 } 00439 00440 void TransformActionsImpl::commitInsertAfterToken(SourceLocation loc, 00441 StringRef text) { 00442 addInsertion(getLocForEndOfToken(loc, Ctx.getSourceManager(), PP), text); 00443 } 00444 00445 void TransformActionsImpl::commitRemove(SourceRange range) { 00446 addRemoval(CharSourceRange::getTokenRange(range)); 00447 } 00448 00449 void TransformActionsImpl::commitRemoveStmt(Stmt *S) { 00450 assert(S); 00451 if (StmtRemovals.count(S)) 00452 return; // already removed. 00453 00454 if (Expr *E = dyn_cast<Expr>(S)) { 00455 commitRemove(E->getSourceRange()); 00456 commitInsert(E->getSourceRange().getBegin(), getARCMTMacroName()); 00457 } else 00458 commitRemove(S->getSourceRange()); 00459 00460 StmtRemovals.insert(S); 00461 } 00462 00463 void TransformActionsImpl::commitReplace(SourceRange range, 00464 SourceRange replacementRange) { 00465 RangeComparison comp = CharRange::compare(replacementRange, range, 00466 Ctx.getSourceManager(), PP); 00467 assert(comp == Range_Contained); 00468 if (comp != Range_Contained) 00469 return; // Although we asserted, be extra safe for release build. 00470 if (range.getBegin() != replacementRange.getBegin()) 00471 addRemoval(CharSourceRange::getCharRange(range.getBegin(), 00472 replacementRange.getBegin())); 00473 if (replacementRange.getEnd() != range.getEnd()) 00474 addRemoval(CharSourceRange::getTokenRange( 00475 getLocForEndOfToken(replacementRange.getEnd(), 00476 Ctx.getSourceManager(), PP), 00477 range.getEnd())); 00478 } 00479 void TransformActionsImpl::commitReplaceText(SourceLocation loc, 00480 StringRef text, 00481 StringRef replacementText) { 00482 SourceManager &SM = Ctx.getSourceManager(); 00483 loc = SM.getExpansionLoc(loc); 00484 // canReplaceText already checked if loc points at text. 00485 SourceLocation afterText = loc.getLocWithOffset(text.size()); 00486 00487 addRemoval(CharSourceRange::getCharRange(loc, afterText)); 00488 commitInsert(loc, replacementText); 00489 } 00490 00491 void TransformActionsImpl::commitIncreaseIndentation(SourceRange range, 00492 SourceLocation parentIndent) { 00493 SourceManager &SM = Ctx.getSourceManager(); 00494 IndentationRanges.push_back( 00495 std::make_pair(CharRange(CharSourceRange::getTokenRange(range), 00496 SM, PP), 00497 SM.getExpansionLoc(parentIndent))); 00498 } 00499 00500 void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs, 00501 SourceRange range) { 00502 CapturedDiags.clearDiagnostic(IDs, range); 00503 } 00504 00505 void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) { 00506 SourceManager &SM = Ctx.getSourceManager(); 00507 loc = SM.getExpansionLoc(loc); 00508 for (std::list<CharRange>::reverse_iterator 00509 I = Removals.rbegin(), E = Removals.rend(); I != E; ++I) { 00510 if (!SM.isBeforeInTranslationUnit(loc, I->End)) 00511 break; 00512 if (I->Begin.isBeforeInTranslationUnitThan(loc)) 00513 return; 00514 } 00515 00516 Inserts[FullSourceLoc(loc, SM)].push_back(text); 00517 } 00518 00519 void TransformActionsImpl::addRemoval(CharSourceRange range) { 00520 CharRange newRange(range, Ctx.getSourceManager(), PP); 00521 if (newRange.Begin == newRange.End) 00522 return; 00523 00524 Inserts.erase(Inserts.upper_bound(newRange.Begin), 00525 Inserts.lower_bound(newRange.End)); 00526 00527 std::list<CharRange>::iterator I = Removals.end(); 00528 while (I != Removals.begin()) { 00529 std::list<CharRange>::iterator RI = I; 00530 --RI; 00531 RangeComparison comp = newRange.compareWith(*RI); 00532 switch (comp) { 00533 case Range_Before: 00534 --I; 00535 break; 00536 case Range_After: 00537 Removals.insert(I, newRange); 00538 return; 00539 case Range_Contained: 00540 return; 00541 case Range_Contains: 00542 RI->End = newRange.End; 00543 case Range_ExtendsBegin: 00544 newRange.End = RI->End; 00545 Removals.erase(RI); 00546 break; 00547 case Range_ExtendsEnd: 00548 RI->End = newRange.End; 00549 return; 00550 } 00551 } 00552 00553 Removals.insert(Removals.begin(), newRange); 00554 } 00555 00556 void TransformActionsImpl::applyRewrites( 00557 TransformActions::RewriteReceiver &receiver) { 00558 for (InsertsMap::iterator I = Inserts.begin(), E = Inserts.end(); I!=E; ++I) { 00559 SourceLocation loc = I->first; 00560 for (TextsVec::iterator 00561 TI = I->second.begin(), TE = I->second.end(); TI != TE; ++TI) { 00562 receiver.insert(loc, *TI); 00563 } 00564 } 00565 00566 for (std::vector<std::pair<CharRange, SourceLocation> >::iterator 00567 I = IndentationRanges.begin(), E = IndentationRanges.end(); I!=E; ++I) { 00568 CharSourceRange range = CharSourceRange::getCharRange(I->first.Begin, 00569 I->first.End); 00570 receiver.increaseIndentation(range, I->second); 00571 } 00572 00573 for (std::list<CharRange>::iterator 00574 I = Removals.begin(), E = Removals.end(); I != E; ++I) { 00575 CharSourceRange range = CharSourceRange::getCharRange(I->Begin, I->End); 00576 receiver.remove(range); 00577 } 00578 } 00579 00580 /// \brief Stores text passed to the transformation methods to keep the string 00581 /// "alive". Since the vast majority of text will be the same, we also unique 00582 /// the strings using a StringMap. 00583 StringRef TransformActionsImpl::getUniqueText(StringRef text) { 00584 llvm::StringMapEntry<bool> &entry = UniqueText.GetOrCreateValue(text); 00585 return entry.getKey(); 00586 } 00587 00588 /// \brief Computes the source location just past the end of the token at 00589 /// the given source location. If the location points at a macro, the whole 00590 /// macro expansion is skipped. 00591 SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc, 00592 SourceManager &SM, 00593 Preprocessor &PP) { 00594 if (loc.isMacroID()) 00595 loc = SM.getExpansionRange(loc).second; 00596 return PP.getLocForEndOfToken(loc); 00597 } 00598 00599 TransformActions::RewriteReceiver::~RewriteReceiver() { } 00600 00601 TransformActions::TransformActions(DiagnosticsEngine &diag, 00602 CapturedDiagList &capturedDiags, 00603 ASTContext &ctx, Preprocessor &PP) 00604 : Diags(diag), CapturedDiags(capturedDiags) { 00605 Impl = new TransformActionsImpl(capturedDiags, ctx, PP); 00606 } 00607 00608 TransformActions::~TransformActions() { 00609 delete static_cast<TransformActionsImpl*>(Impl); 00610 } 00611 00612 void TransformActions::startTransaction() { 00613 static_cast<TransformActionsImpl*>(Impl)->startTransaction(); 00614 } 00615 00616 bool TransformActions::commitTransaction() { 00617 return static_cast<TransformActionsImpl*>(Impl)->commitTransaction(); 00618 } 00619 00620 void TransformActions::abortTransaction() { 00621 static_cast<TransformActionsImpl*>(Impl)->abortTransaction(); 00622 } 00623 00624 00625 void TransformActions::insert(SourceLocation loc, StringRef text) { 00626 static_cast<TransformActionsImpl*>(Impl)->insert(loc, text); 00627 } 00628 00629 void TransformActions::insertAfterToken(SourceLocation loc, 00630 StringRef text) { 00631 static_cast<TransformActionsImpl*>(Impl)->insertAfterToken(loc, text); 00632 } 00633 00634 void TransformActions::remove(SourceRange range) { 00635 static_cast<TransformActionsImpl*>(Impl)->remove(range); 00636 } 00637 00638 void TransformActions::removeStmt(Stmt *S) { 00639 static_cast<TransformActionsImpl*>(Impl)->removeStmt(S); 00640 } 00641 00642 void TransformActions::replace(SourceRange range, StringRef text) { 00643 static_cast<TransformActionsImpl*>(Impl)->replace(range, text); 00644 } 00645 00646 void TransformActions::replace(SourceRange range, 00647 SourceRange replacementRange) { 00648 static_cast<TransformActionsImpl*>(Impl)->replace(range, replacementRange); 00649 } 00650 00651 void TransformActions::replaceStmt(Stmt *S, StringRef text) { 00652 static_cast<TransformActionsImpl*>(Impl)->replaceStmt(S, text); 00653 } 00654 00655 void TransformActions::replaceText(SourceLocation loc, StringRef text, 00656 StringRef replacementText) { 00657 static_cast<TransformActionsImpl*>(Impl)->replaceText(loc, text, 00658 replacementText); 00659 } 00660 00661 void TransformActions::increaseIndentation(SourceRange range, 00662 SourceLocation parentIndent) { 00663 static_cast<TransformActionsImpl*>(Impl)->increaseIndentation(range, 00664 parentIndent); 00665 } 00666 00667 bool TransformActions::clearDiagnostic(ArrayRef<unsigned> IDs, 00668 SourceRange range) { 00669 return static_cast<TransformActionsImpl*>(Impl)->clearDiagnostic(IDs, range); 00670 } 00671 00672 void TransformActions::applyRewrites(RewriteReceiver &receiver) { 00673 static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver); 00674 } 00675 00676 DiagnosticBuilder TransformActions::report(SourceLocation loc, unsigned diagId, 00677 SourceRange range) { 00678 assert(!static_cast<TransformActionsImpl *>(Impl)->isInTransaction() && 00679 "Errors should be emitted out of a transaction"); 00680 return Diags.Report(loc, diagId) << range; 00681 } 00682 00683 void TransformActions::reportError(StringRef message, SourceLocation loc, 00684 SourceRange range) { 00685 report(loc, diag::err_mt_message, range) << message; 00686 } 00687 00688 void TransformActions::reportWarning(StringRef message, SourceLocation loc, 00689 SourceRange range) { 00690 report(loc, diag::warn_mt_message, range) << message; 00691 } 00692 00693 void TransformActions::reportNote(StringRef message, SourceLocation loc, 00694 SourceRange range) { 00695 report(loc, diag::note_mt_message, range) << message; 00696 }