diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 13:58:24 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 14:11:53 +0300 |
commit | 11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch) | |
tree | fabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/lib/ARCMigrate/ARCMT.cpp | |
parent | 9685917341315774aad5733b1793b1e533a88bbb (diff) | |
download | ydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz |
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/lib/ARCMigrate/ARCMT.cpp')
-rw-r--r-- | contrib/libs/clang16/lib/ARCMigrate/ARCMT.cpp | 616 |
1 files changed, 616 insertions, 0 deletions
diff --git a/contrib/libs/clang16/lib/ARCMigrate/ARCMT.cpp b/contrib/libs/clang16/lib/ARCMigrate/ARCMT.cpp new file mode 100644 index 0000000000..68ee7c5927 --- /dev/null +++ b/contrib/libs/clang16/lib/ARCMigrate/ARCMT.cpp @@ -0,0 +1,616 @@ +//===--- 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; +} |