123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- //===--- ARCMT.cpp - Migration to ARC mode --------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "Internals.h"
- #include "clang/ARCMigrate/ARCMT.h"
- #include "clang/AST/ASTConsumer.h"
- #include "clang/Basic/DiagnosticCategories.h"
- #include "clang/Frontend/ASTUnit.h"
- #include "clang/Frontend/CompilerInstance.h"
- #include "clang/Frontend/FrontendAction.h"
- #include "clang/Frontend/TextDiagnosticPrinter.h"
- #include "clang/Frontend/Utils.h"
- #include "clang/Lex/Preprocessor.h"
- #include "clang/Lex/PreprocessorOptions.h"
- #include "clang/Rewrite/Core/Rewriter.h"
- #include "clang/Sema/SemaDiagnostic.h"
- #include "clang/Serialization/ASTReader.h"
- #include "llvm/ADT/Triple.h"
- #include "llvm/Support/MemoryBuffer.h"
- #include <utility>
- using namespace clang;
- using namespace arcmt;
- bool CapturedDiagList::clearDiagnostic(ArrayRef<unsigned> IDs,
- SourceRange range) {
- if (range.isInvalid())
- return false;
- bool cleared = false;
- ListTy::iterator I = List.begin();
- while (I != List.end()) {
- FullSourceLoc diagLoc = I->getLocation();
- if ((IDs.empty() || // empty means clear all diagnostics in the range.
- llvm::is_contained(IDs, I->getID())) &&
- !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
- (diagLoc == range.getEnd() ||
- diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
- cleared = true;
- ListTy::iterator eraseS = I++;
- if (eraseS->getLevel() != DiagnosticsEngine::Note)
- while (I != List.end() && I->getLevel() == DiagnosticsEngine::Note)
- ++I;
- // Clear the diagnostic and any notes following it.
- I = List.erase(eraseS, I);
- continue;
- }
- ++I;
- }
- return cleared;
- }
- bool CapturedDiagList::hasDiagnostic(ArrayRef<unsigned> IDs,
- SourceRange range) const {
- if (range.isInvalid())
- return false;
- ListTy::const_iterator I = List.begin();
- while (I != List.end()) {
- FullSourceLoc diagLoc = I->getLocation();
- if ((IDs.empty() || // empty means any diagnostic in the range.
- llvm::is_contained(IDs, I->getID())) &&
- !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
- (diagLoc == range.getEnd() ||
- diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
- return true;
- }
- ++I;
- }
- return false;
- }
- void CapturedDiagList::reportDiagnostics(DiagnosticsEngine &Diags) const {
- for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
- Diags.Report(*I);
- }
- bool CapturedDiagList::hasErrors() const {
- for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
- if (I->getLevel() >= DiagnosticsEngine::Error)
- return true;
- return false;
- }
- namespace {
- class CaptureDiagnosticConsumer : public DiagnosticConsumer {
- DiagnosticsEngine &Diags;
- DiagnosticConsumer &DiagClient;
- CapturedDiagList &CapturedDiags;
- bool HasBegunSourceFile;
- public:
- CaptureDiagnosticConsumer(DiagnosticsEngine &diags,
- DiagnosticConsumer &client,
- CapturedDiagList &capturedDiags)
- : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags),
- HasBegunSourceFile(false) { }
- void BeginSourceFile(const LangOptions &Opts,
- const Preprocessor *PP) override {
- // Pass BeginSourceFile message onto DiagClient on first call.
- // The corresponding EndSourceFile call will be made from an
- // explicit call to FinishCapture.
- if (!HasBegunSourceFile) {
- DiagClient.BeginSourceFile(Opts, PP);
- HasBegunSourceFile = true;
- }
- }
- void FinishCapture() {
- // Call EndSourceFile on DiagClient on completion of capture to
- // enable VerifyDiagnosticConsumer to check diagnostics *after*
- // it has received the diagnostic list.
- if (HasBegunSourceFile) {
- DiagClient.EndSourceFile();
- HasBegunSourceFile = false;
- }
- }
- ~CaptureDiagnosticConsumer() override {
- assert(!HasBegunSourceFile && "FinishCapture not called!");
- }
- void HandleDiagnostic(DiagnosticsEngine::Level level,
- const Diagnostic &Info) override {
- if (DiagnosticIDs::isARCDiagnostic(Info.getID()) ||
- level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) {
- if (Info.getLocation().isValid())
- CapturedDiags.push_back(StoredDiagnostic(level, Info));
- return;
- }
- // Non-ARC warnings are ignored.
- Diags.setLastDiagnosticIgnored(true);
- }
- };
- } // end anonymous namespace
- static bool HasARCRuntime(CompilerInvocation &origCI) {
- // This duplicates some functionality from Darwin::AddDeploymentTarget
- // but this function is well defined, so keep it decoupled from the driver
- // and avoid unrelated complications.
- llvm::Triple triple(origCI.getTargetOpts().Triple);
- if (triple.isiOS())
- return triple.getOSMajorVersion() >= 5;
- if (triple.isWatchOS())
- return true;
- if (triple.getOS() == llvm::Triple::Darwin)
- return triple.getOSMajorVersion() >= 11;
- if (triple.getOS() == llvm::Triple::MacOSX) {
- return triple.getOSVersion() >= VersionTuple(10, 7);
- }
- return false;
- }
- static CompilerInvocation *
- createInvocationForMigration(CompilerInvocation &origCI,
- const PCHContainerReader &PCHContainerRdr) {
- std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(new CompilerInvocation(origCI));
- PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
- if (!PPOpts.ImplicitPCHInclude.empty()) {
- // We can't use a PCH because it was likely built in non-ARC mode and we
- // want to parse in ARC. Include the original header.
- FileManager FileMgr(origCI.getFileSystemOpts());
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
- new IgnoringDiagConsumer()));
- std::string OriginalFile = ASTReader::getOriginalSourceFile(
- PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerRdr, *Diags);
- if (!OriginalFile.empty())
- PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile);
- PPOpts.ImplicitPCHInclude.clear();
- }
- std::string define = std::string(getARCMTMacroName());
- define += '=';
- CInvok->getPreprocessorOpts().addMacroDef(define);
- CInvok->getLangOpts()->ObjCAutoRefCount = true;
- CInvok->getLangOpts()->setGC(LangOptions::NonGC);
- CInvok->getDiagnosticOpts().ErrorLimit = 0;
- CInvok->getDiagnosticOpts().PedanticErrors = 0;
- // Ignore -Werror flags when migrating.
- std::vector<std::string> WarnOpts;
- for (std::vector<std::string>::iterator
- I = CInvok->getDiagnosticOpts().Warnings.begin(),
- E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
- if (!StringRef(*I).startswith("error"))
- WarnOpts.push_back(*I);
- }
- WarnOpts.push_back("error=arc-unsafe-retained-assign");
- CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
- CInvok->getLangOpts()->ObjCWeakRuntime = HasARCRuntime(origCI);
- CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
- return CInvok.release();
- }
- static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
- DiagnosticOptions *diagOpts,
- Preprocessor &PP) {
- TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, diagOpts, &printer,
- /*ShouldOwnClient=*/false));
- Diags->setSourceManager(&PP.getSourceManager());
- printer.BeginSourceFile(PP.getLangOpts(), &PP);
- arcDiags.reportDiagnostics(*Diags);
- printer.EndSourceFile();
- }
- //===----------------------------------------------------------------------===//
- // checkForManualIssues.
- //===----------------------------------------------------------------------===//
- bool arcmt::checkForManualIssues(
- CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors,
- StringRef plistOut) {
- if (!origCI.getLangOpts()->ObjC)
- return false;
- LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
- bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError;
- bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
- std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
- NoFinalizeRemoval);
- assert(!transforms.empty());
- std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(
- createInvocationForMigration(origCI, PCHContainerOps->getRawReader()));
- CInvok->getFrontendOpts().Inputs.clear();
- CInvok->getFrontendOpts().Inputs.push_back(Input);
- CapturedDiagList capturedDiags;
- assert(DiagClient);
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
- DiagClient, /*ShouldOwnClient=*/false));
- // Filter of all diagnostics.
- CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
- Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
- std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
- std::move(CInvok), PCHContainerOps, Diags));
- if (!Unit) {
- errRec.FinishCapture();
- return true;
- }
- // Don't filter diagnostics anymore.
- Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
- ASTContext &Ctx = Unit->getASTContext();
- if (Diags->hasFatalErrorOccurred()) {
- Diags->Reset();
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
- capturedDiags.reportDiagnostics(*Diags);
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
- return true;
- }
- if (emitPremigrationARCErrors)
- emitPremigrationErrors(capturedDiags, &origCI.getDiagnosticOpts(),
- Unit->getPreprocessor());
- if (!plistOut.empty()) {
- SmallVector<StoredDiagnostic, 8> arcDiags;
- for (CapturedDiagList::iterator
- I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
- arcDiags.push_back(*I);
- writeARCDiagsToPlist(std::string(plistOut), arcDiags,
- Ctx.getSourceManager(), Ctx.getLangOpts());
- }
- // After parsing of source files ended, we want to reuse the
- // diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticConsumer requires that
- // diagnostics with source range information are emitted only in between
- // BeginSourceFile() and EndSourceFile().
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
- // No macros will be added since we are just checking and we won't modify
- // source code.
- std::vector<SourceLocation> ARCMTMacroLocs;
- TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
- MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
- ARCMTMacroLocs);
- pass.setNoFinalizeRemoval(NoFinalizeRemoval);
- if (!NoNSAllocReallocError)
- Diags->setSeverity(diag::warn_arcmt_nsalloc_realloc, diag::Severity::Error,
- SourceLocation());
- for (unsigned i=0, e = transforms.size(); i != e; ++i)
- transforms[i](pass);
- capturedDiags.reportDiagnostics(*Diags);
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
- return capturedDiags.hasErrors() || testAct.hasReportedErrors();
- }
- //===----------------------------------------------------------------------===//
- // applyTransformations.
- //===----------------------------------------------------------------------===//
- static bool
- applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient, StringRef outputDir,
- bool emitPremigrationARCErrors, StringRef plistOut) {
- if (!origCI.getLangOpts()->ObjC)
- return false;
- LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
- // Make sure checking is successful first.
- CompilerInvocation CInvokForCheck(origCI);
- if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps,
- DiagClient, emitPremigrationARCErrors,
- plistOut))
- return true;
- CompilerInvocation CInvok(origCI);
- CInvok.getFrontendOpts().Inputs.clear();
- CInvok.getFrontendOpts().Inputs.push_back(Input);
- MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir);
- bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
- std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
- NoFinalizeRemoval);
- assert(!transforms.empty());
- for (unsigned i=0, e = transforms.size(); i != e; ++i) {
- bool err = migration.applyTransform(transforms[i]);
- if (err) return true;
- }
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
- DiagClient, /*ShouldOwnClient=*/false));
- if (outputDir.empty()) {
- origCI.getLangOpts()->ObjCAutoRefCount = true;
- return migration.getRemapper().overwriteOriginal(*Diags);
- } else {
- return migration.getRemapper().flushToDisk(outputDir, *Diags);
- }
- }
- bool arcmt::applyTransformations(
- CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient) {
- return applyTransforms(origCI, Input, PCHContainerOps, DiagClient,
- StringRef(), false, StringRef());
- }
- bool arcmt::migrateWithTemporaryFiles(
- CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient, StringRef outputDir,
- bool emitPremigrationARCErrors, StringRef plistOut) {
- assert(!outputDir.empty() && "Expected output directory path");
- return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
- emitPremigrationARCErrors, plistOut);
- }
- bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
- remap,
- StringRef outputDir,
- DiagnosticConsumer *DiagClient) {
- assert(!outputDir.empty());
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, new DiagnosticOptions,
- DiagClient, /*ShouldOwnClient=*/false));
- FileRemapper remapper;
- bool err = remapper.initFromDisk(outputDir, *Diags,
- /*ignoreIfFilesChanged=*/true);
- if (err)
- return true;
- remapper.forEachMapping(
- [&](StringRef From, StringRef To) {
- remap.push_back(std::make_pair(From.str(), To.str()));
- },
- [](StringRef, const llvm::MemoryBufferRef &) {});
- return false;
- }
- //===----------------------------------------------------------------------===//
- // CollectTransformActions.
- //===----------------------------------------------------------------------===//
- namespace {
- class ARCMTMacroTrackerPPCallbacks : public PPCallbacks {
- std::vector<SourceLocation> &ARCMTMacroLocs;
- public:
- ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
- : ARCMTMacroLocs(ARCMTMacroLocs) { }
- void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
- SourceRange Range, const MacroArgs *Args) override {
- if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
- ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
- }
- };
- class ARCMTMacroTrackerAction : public ASTFrontendAction {
- std::vector<SourceLocation> &ARCMTMacroLocs;
- public:
- ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
- : ARCMTMacroLocs(ARCMTMacroLocs) { }
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override {
- CI.getPreprocessor().addPPCallbacks(
- std::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
- return std::make_unique<ASTConsumer>();
- }
- };
- class RewritesApplicator : public TransformActions::RewriteReceiver {
- Rewriter &rewriter;
- MigrationProcess::RewriteListener *Listener;
- public:
- RewritesApplicator(Rewriter &rewriter, ASTContext &ctx,
- MigrationProcess::RewriteListener *listener)
- : rewriter(rewriter), Listener(listener) {
- if (Listener)
- Listener->start(ctx);
- }
- ~RewritesApplicator() override {
- if (Listener)
- Listener->finish();
- }
- void insert(SourceLocation loc, StringRef text) override {
- bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true,
- /*indentNewLines=*/true);
- if (!err && Listener)
- Listener->insert(loc, text);
- }
- void remove(CharSourceRange range) override {
- Rewriter::RewriteOptions removeOpts;
- removeOpts.IncludeInsertsAtBeginOfRange = false;
- removeOpts.IncludeInsertsAtEndOfRange = false;
- removeOpts.RemoveLineIfEmpty = true;
- bool err = rewriter.RemoveText(range, removeOpts);
- if (!err && Listener)
- Listener->remove(range);
- }
- void increaseIndentation(CharSourceRange range,
- SourceLocation parentIndent) override {
- rewriter.IncreaseIndentation(range, parentIndent);
- }
- };
- } // end anonymous namespace.
- /// Anchor for VTable.
- MigrationProcess::RewriteListener::~RewriteListener() { }
- MigrationProcess::MigrationProcess(
- const CompilerInvocation &CI,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *diagClient, StringRef outputDir)
- : OrigCI(CI), PCHContainerOps(std::move(PCHContainerOps)),
- DiagClient(diagClient), HadARCErrors(false) {
- if (!outputDir.empty()) {
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(),
- DiagClient, /*ShouldOwnClient=*/false));
- Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanged=*/true);
- }
- }
- bool MigrationProcess::applyTransform(TransformFn trans,
- RewriteListener *listener) {
- std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(
- createInvocationForMigration(OrigCI, PCHContainerOps->getRawReader()));
- CInvok->getDiagnosticOpts().IgnoreWarnings = true;
- Remapper.applyMappings(CInvok->getPreprocessorOpts());
- CapturedDiagList capturedDiags;
- std::vector<SourceLocation> ARCMTMacroLocs;
- assert(DiagClient);
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, new DiagnosticOptions,
- DiagClient, /*ShouldOwnClient=*/false));
- // Filter of all diagnostics.
- CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
- Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
- std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
- ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
- std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
- std::move(CInvok), PCHContainerOps, Diags, ASTAction.get()));
- if (!Unit) {
- errRec.FinishCapture();
- return true;
- }
- Unit->setOwnsRemappedFileBuffers(false); // FileRemapper manages that.
- HadARCErrors = HadARCErrors || capturedDiags.hasErrors();
- // Don't filter diagnostics anymore.
- Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
- ASTContext &Ctx = Unit->getASTContext();
- if (Diags->hasFatalErrorOccurred()) {
- Diags->Reset();
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
- capturedDiags.reportDiagnostics(*Diags);
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
- return true;
- }
- // After parsing of source files ended, we want to reuse the
- // diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticConsumer requires that
- // diagnostics with source range information are emitted only in between
- // BeginSourceFile() and EndSourceFile().
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
- Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
- TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
- MigrationPass pass(Ctx, OrigCI.getLangOpts()->getGC(),
- Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
- trans(pass);
- {
- RewritesApplicator applicator(rewriter, Ctx, listener);
- TA.applyRewrites(applicator);
- }
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
- if (DiagClient->getNumErrors())
- return true;
- for (Rewriter::buffer_iterator
- I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
- FileID FID = I->first;
- RewriteBuffer &buf = I->second;
- const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
- assert(file);
- std::string newFname = std::string(file->getName());
- newFname += "-trans";
- SmallString<512> newText;
- llvm::raw_svector_ostream vecOS(newText);
- buf.write(vecOS);
- std::unique_ptr<llvm::MemoryBuffer> memBuf(
- llvm::MemoryBuffer::getMemBufferCopy(
- StringRef(newText.data(), newText.size()), newFname));
- SmallString<64> filePath(file->getName());
- Unit->getFileManager().FixupRelativePath(filePath);
- Remapper.remap(filePath.str(), std::move(memBuf));
- }
- return false;
- }
|