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