1//===--- ARCMT.cpp - Migration to ARC mode --------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Internals.h"
11#include "clang/AST/ASTConsumer.h"
12#include "clang/Basic/DiagnosticCategories.h"
13#include "clang/Frontend/ASTUnit.h"
14#include "clang/Frontend/CompilerInstance.h"
15#include "clang/Frontend/FrontendAction.h"
16#include "clang/Frontend/TextDiagnosticPrinter.h"
17#include "clang/Frontend/Utils.h"
18#include "clang/Lex/Preprocessor.h"
19#include "clang/Rewrite/Core/Rewriter.h"
20#include "clang/Sema/SemaDiagnostic.h"
21#include "clang/Serialization/ASTReader.h"
22#include "llvm/ADT/Triple.h"
23#include "llvm/Support/MemoryBuffer.h"
24#include <utility>
25using namespace clang;
26using namespace arcmt;
27
28bool CapturedDiagList::clearDiagnostic(ArrayRef<unsigned> IDs,
29                                       SourceRange range) {
30  if (range.isInvalid())
31    return false;
32
33  bool cleared = false;
34  ListTy::iterator I = List.begin();
35  while (I != List.end()) {
36    FullSourceLoc diagLoc = I->getLocation();
37    if ((IDs.empty() || // empty means clear all diagnostics in the range.
38         std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
39        !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
40        (diagLoc == range.getEnd() ||
41           diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
42      cleared = true;
43      ListTy::iterator eraseS = I++;
44      if (eraseS->getLevel() != DiagnosticsEngine::Note)
45        while (I != List.end() && I->getLevel() == DiagnosticsEngine::Note)
46          ++I;
47      // Clear the diagnostic and any notes following it.
48      I = List.erase(eraseS, I);
49      continue;
50    }
51
52    ++I;
53  }
54
55  return cleared;
56}
57
58bool CapturedDiagList::hasDiagnostic(ArrayRef<unsigned> IDs,
59                                     SourceRange range) const {
60  if (range.isInvalid())
61    return false;
62
63  ListTy::const_iterator I = List.begin();
64  while (I != List.end()) {
65    FullSourceLoc diagLoc = I->getLocation();
66    if ((IDs.empty() || // empty means any diagnostic in the range.
67         std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
68        !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
69        (diagLoc == range.getEnd() ||
70           diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
71      return true;
72    }
73
74    ++I;
75  }
76
77  return false;
78}
79
80void CapturedDiagList::reportDiagnostics(DiagnosticsEngine &Diags) const {
81  for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
82    Diags.Report(*I);
83}
84
85bool CapturedDiagList::hasErrors() const {
86  for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
87    if (I->getLevel() >= DiagnosticsEngine::Error)
88      return true;
89
90  return false;
91}
92
93namespace {
94
95class CaptureDiagnosticConsumer : public DiagnosticConsumer {
96  DiagnosticsEngine &Diags;
97  DiagnosticConsumer &DiagClient;
98  CapturedDiagList &CapturedDiags;
99  bool HasBegunSourceFile;
100public:
101  CaptureDiagnosticConsumer(DiagnosticsEngine &diags,
102                            DiagnosticConsumer &client,
103                            CapturedDiagList &capturedDiags)
104    : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags),
105      HasBegunSourceFile(false) { }
106
107  void BeginSourceFile(const LangOptions &Opts,
108                       const Preprocessor *PP) override {
109    // Pass BeginSourceFile message onto DiagClient on first call.
110    // The corresponding EndSourceFile call will be made from an
111    // explicit call to FinishCapture.
112    if (!HasBegunSourceFile) {
113      DiagClient.BeginSourceFile(Opts, PP);
114      HasBegunSourceFile = true;
115    }
116  }
117
118  void FinishCapture() {
119    // Call EndSourceFile on DiagClient on completion of capture to
120    // enable VerifyDiagnosticConsumer to check diagnostics *after*
121    // it has received the diagnostic list.
122    if (HasBegunSourceFile) {
123      DiagClient.EndSourceFile();
124      HasBegunSourceFile = false;
125    }
126  }
127
128  ~CaptureDiagnosticConsumer() override {
129    assert(!HasBegunSourceFile && "FinishCapture not called!");
130  }
131
132  void HandleDiagnostic(DiagnosticsEngine::Level level,
133                        const Diagnostic &Info) override {
134    if (DiagnosticIDs::isARCDiagnostic(Info.getID()) ||
135        level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) {
136      if (Info.getLocation().isValid())
137        CapturedDiags.push_back(StoredDiagnostic(level, Info));
138      return;
139    }
140
141    // Non-ARC warnings are ignored.
142    Diags.setLastDiagnosticIgnored();
143  }
144};
145
146} // end anonymous namespace
147
148static bool HasARCRuntime(CompilerInvocation &origCI) {
149  // This duplicates some functionality from Darwin::AddDeploymentTarget
150  // but this function is well defined, so keep it decoupled from the driver
151  // and avoid unrelated complications.
152  llvm::Triple triple(origCI.getTargetOpts().Triple);
153
154  if (triple.isiOS())
155    return triple.getOSMajorVersion() >= 5;
156
157  if (triple.isWatchOS())
158    return true;
159
160  if (triple.getOS() == llvm::Triple::Darwin)
161    return triple.getOSMajorVersion() >= 11;
162
163  if (triple.getOS() == llvm::Triple::MacOSX) {
164    unsigned Major, Minor, Micro;
165    triple.getOSVersion(Major, Minor, Micro);
166    return Major > 10 || (Major == 10 && Minor >= 7);
167  }
168
169  return false;
170}
171
172static CompilerInvocation *
173createInvocationForMigration(CompilerInvocation &origCI,
174                             const PCHContainerReader &PCHContainerRdr) {
175  std::unique_ptr<CompilerInvocation> CInvok;
176  CInvok.reset(new CompilerInvocation(origCI));
177  PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
178  if (!PPOpts.ImplicitPCHInclude.empty()) {
179    // We can't use a PCH because it was likely built in non-ARC mode and we
180    // want to parse in ARC. Include the original header.
181    FileManager FileMgr(origCI.getFileSystemOpts());
182    IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
183    IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
184        new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
185                              new IgnoringDiagConsumer()));
186    std::string OriginalFile = ASTReader::getOriginalSourceFile(
187        PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerRdr, *Diags);
188    if (!OriginalFile.empty())
189      PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile);
190    PPOpts.ImplicitPCHInclude.clear();
191  }
192  // FIXME: Get the original header of a PTH as well.
193  CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
194  std::string define = getARCMTMacroName();
195  define += '=';
196  CInvok->getPreprocessorOpts().addMacroDef(define);
197  CInvok->getLangOpts()->ObjCAutoRefCount = true;
198  CInvok->getLangOpts()->setGC(LangOptions::NonGC);
199  CInvok->getDiagnosticOpts().ErrorLimit = 0;
200  CInvok->getDiagnosticOpts().PedanticErrors = 0;
201
202  // Ignore -Werror flags when migrating.
203  std::vector<std::string> WarnOpts;
204  for (std::vector<std::string>::iterator
205         I = CInvok->getDiagnosticOpts().Warnings.begin(),
206         E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
207    if (!StringRef(*I).startswith("error"))
208      WarnOpts.push_back(*I);
209  }
210  WarnOpts.push_back("error=arc-unsafe-retained-assign");
211  CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
212
213  CInvok->getLangOpts()->ObjCWeakRuntime = HasARCRuntime(origCI);
214  CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
215
216  return CInvok.release();
217}
218
219static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
220                                   DiagnosticOptions *diagOpts,
221                                   Preprocessor &PP) {
222  TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
223  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
224  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
225      new DiagnosticsEngine(DiagID, diagOpts, &printer,
226                            /*ShouldOwnClient=*/false));
227  Diags->setSourceManager(&PP.getSourceManager());
228
229  printer.BeginSourceFile(PP.getLangOpts(), &PP);
230  arcDiags.reportDiagnostics(*Diags);
231  printer.EndSourceFile();
232}
233
234//===----------------------------------------------------------------------===//
235// checkForManualIssues.
236//===----------------------------------------------------------------------===//
237
238bool arcmt::checkForManualIssues(
239    CompilerInvocation &origCI, const FrontendInputFile &Input,
240    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
241    DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors,
242    StringRef plistOut) {
243  if (!origCI.getLangOpts()->ObjC1)
244    return false;
245
246  LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
247  bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError;
248  bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
249
250  std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
251                                                                     NoFinalizeRemoval);
252  assert(!transforms.empty());
253
254  std::unique_ptr<CompilerInvocation> CInvok;
255  CInvok.reset(
256      createInvocationForMigration(origCI, PCHContainerOps->getRawReader()));
257  CInvok->getFrontendOpts().Inputs.clear();
258  CInvok->getFrontendOpts().Inputs.push_back(Input);
259
260  CapturedDiagList capturedDiags;
261
262  assert(DiagClient);
263  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
264  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
265      new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
266                            DiagClient, /*ShouldOwnClient=*/false));
267
268  // Filter of all diagnostics.
269  CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
270  Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
271
272  std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
273      CInvok.release(), PCHContainerOps, Diags));
274  if (!Unit) {
275    errRec.FinishCapture();
276    return true;
277  }
278
279  // Don't filter diagnostics anymore.
280  Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
281
282  ASTContext &Ctx = Unit->getASTContext();
283
284  if (Diags->hasFatalErrorOccurred()) {
285    Diags->Reset();
286    DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
287    capturedDiags.reportDiagnostics(*Diags);
288    DiagClient->EndSourceFile();
289    errRec.FinishCapture();
290    return true;
291  }
292
293  if (emitPremigrationARCErrors)
294    emitPremigrationErrors(capturedDiags, &origCI.getDiagnosticOpts(),
295                           Unit->getPreprocessor());
296  if (!plistOut.empty()) {
297    SmallVector<StoredDiagnostic, 8> arcDiags;
298    for (CapturedDiagList::iterator
299           I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
300      arcDiags.push_back(*I);
301    writeARCDiagsToPlist(plistOut, arcDiags,
302                         Ctx.getSourceManager(), Ctx.getLangOpts());
303  }
304
305  // After parsing of source files ended, we want to reuse the
306  // diagnostics objects to emit further diagnostics.
307  // We call BeginSourceFile because DiagnosticConsumer requires that
308  // diagnostics with source range information are emitted only in between
309  // BeginSourceFile() and EndSourceFile().
310  DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
311
312  // No macros will be added since we are just checking and we won't modify
313  // source code.
314  std::vector<SourceLocation> ARCMTMacroLocs;
315
316  TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
317  MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
318                     ARCMTMacroLocs);
319  pass.setNoFinalizeRemoval(NoFinalizeRemoval);
320  if (!NoNSAllocReallocError)
321    Diags->setSeverity(diag::warn_arcmt_nsalloc_realloc, diag::Severity::Error,
322                       SourceLocation());
323
324  for (unsigned i=0, e = transforms.size(); i != e; ++i)
325    transforms[i](pass);
326
327  capturedDiags.reportDiagnostics(*Diags);
328
329  DiagClient->EndSourceFile();
330  errRec.FinishCapture();
331
332  return capturedDiags.hasErrors() || testAct.hasReportedErrors();
333}
334
335//===----------------------------------------------------------------------===//
336// applyTransformations.
337//===----------------------------------------------------------------------===//
338
339static bool
340applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input,
341                std::shared_ptr<PCHContainerOperations> PCHContainerOps,
342                DiagnosticConsumer *DiagClient, StringRef outputDir,
343                bool emitPremigrationARCErrors, StringRef plistOut) {
344  if (!origCI.getLangOpts()->ObjC1)
345    return false;
346
347  LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
348
349  // Make sure checking is successful first.
350  CompilerInvocation CInvokForCheck(origCI);
351  if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps,
352                                  DiagClient, emitPremigrationARCErrors,
353                                  plistOut))
354    return true;
355
356  CompilerInvocation CInvok(origCI);
357  CInvok.getFrontendOpts().Inputs.clear();
358  CInvok.getFrontendOpts().Inputs.push_back(Input);
359
360  MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir);
361  bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
362
363  std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
364                                                                     NoFinalizeRemoval);
365  assert(!transforms.empty());
366
367  for (unsigned i=0, e = transforms.size(); i != e; ++i) {
368    bool err = migration.applyTransform(transforms[i]);
369    if (err) return true;
370  }
371
372  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
373  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
374      new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
375                            DiagClient, /*ShouldOwnClient=*/false));
376
377  if (outputDir.empty()) {
378    origCI.getLangOpts()->ObjCAutoRefCount = true;
379    return migration.getRemapper().overwriteOriginal(*Diags);
380  } else {
381    return migration.getRemapper().flushToDisk(outputDir, *Diags);
382  }
383}
384
385bool arcmt::applyTransformations(
386    CompilerInvocation &origCI, const FrontendInputFile &Input,
387    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
388    DiagnosticConsumer *DiagClient) {
389  return applyTransforms(origCI, Input, PCHContainerOps, DiagClient,
390                         StringRef(), false, StringRef());
391}
392
393bool arcmt::migrateWithTemporaryFiles(
394    CompilerInvocation &origCI, const FrontendInputFile &Input,
395    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
396    DiagnosticConsumer *DiagClient, StringRef outputDir,
397    bool emitPremigrationARCErrors, StringRef plistOut) {
398  assert(!outputDir.empty() && "Expected output directory path");
399  return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
400                         emitPremigrationARCErrors, plistOut);
401}
402
403bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
404                                  remap,
405                              StringRef outputDir,
406                              DiagnosticConsumer *DiagClient) {
407  assert(!outputDir.empty());
408
409  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
410  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
411      new DiagnosticsEngine(DiagID, new DiagnosticOptions,
412                            DiagClient, /*ShouldOwnClient=*/false));
413
414  FileRemapper remapper;
415  bool err = remapper.initFromDisk(outputDir, *Diags,
416                                   /*ignoreIfFilesChanged=*/true);
417  if (err)
418    return true;
419
420  PreprocessorOptions PPOpts;
421  remapper.applyMappings(PPOpts);
422  remap = PPOpts.RemappedFiles;
423
424  return false;
425}
426
427
428//===----------------------------------------------------------------------===//
429// CollectTransformActions.
430//===----------------------------------------------------------------------===//
431
432namespace {
433
434class ARCMTMacroTrackerPPCallbacks : public PPCallbacks {
435  std::vector<SourceLocation> &ARCMTMacroLocs;
436
437public:
438  ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
439    : ARCMTMacroLocs(ARCMTMacroLocs) { }
440
441  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
442                    SourceRange Range, const MacroArgs *Args) override {
443    if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
444      ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
445  }
446};
447
448class ARCMTMacroTrackerAction : public ASTFrontendAction {
449  std::vector<SourceLocation> &ARCMTMacroLocs;
450
451public:
452  ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
453    : ARCMTMacroLocs(ARCMTMacroLocs) { }
454
455  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
456                                                 StringRef InFile) override {
457    CI.getPreprocessor().addPPCallbacks(
458               llvm::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
459    return llvm::make_unique<ASTConsumer>();
460  }
461};
462
463class RewritesApplicator : public TransformActions::RewriteReceiver {
464  Rewriter &rewriter;
465  MigrationProcess::RewriteListener *Listener;
466
467public:
468  RewritesApplicator(Rewriter &rewriter, ASTContext &ctx,
469                     MigrationProcess::RewriteListener *listener)
470    : rewriter(rewriter), Listener(listener) {
471    if (Listener)
472      Listener->start(ctx);
473  }
474  ~RewritesApplicator() override {
475    if (Listener)
476      Listener->finish();
477  }
478
479  void insert(SourceLocation loc, StringRef text) override {
480    bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true,
481                                   /*indentNewLines=*/true);
482    if (!err && Listener)
483      Listener->insert(loc, text);
484  }
485
486  void remove(CharSourceRange range) override {
487    Rewriter::RewriteOptions removeOpts;
488    removeOpts.IncludeInsertsAtBeginOfRange = false;
489    removeOpts.IncludeInsertsAtEndOfRange = false;
490    removeOpts.RemoveLineIfEmpty = true;
491
492    bool err = rewriter.RemoveText(range, removeOpts);
493    if (!err && Listener)
494      Listener->remove(range);
495  }
496
497  void increaseIndentation(CharSourceRange range,
498                            SourceLocation parentIndent) override {
499    rewriter.IncreaseIndentation(range, parentIndent);
500  }
501};
502
503} // end anonymous namespace.
504
505/// \brief Anchor for VTable.
506MigrationProcess::RewriteListener::~RewriteListener() { }
507
508MigrationProcess::MigrationProcess(
509    const CompilerInvocation &CI,
510    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
511    DiagnosticConsumer *diagClient, StringRef outputDir)
512    : OrigCI(CI), PCHContainerOps(std::move(PCHContainerOps)),
513      DiagClient(diagClient), HadARCErrors(false) {
514  if (!outputDir.empty()) {
515    IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
516    IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
517      new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(),
518                            DiagClient, /*ShouldOwnClient=*/false));
519    Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true);
520  }
521}
522
523bool MigrationProcess::applyTransform(TransformFn trans,
524                                      RewriteListener *listener) {
525  std::unique_ptr<CompilerInvocation> CInvok;
526  CInvok.reset(
527      createInvocationForMigration(OrigCI, PCHContainerOps->getRawReader()));
528  CInvok->getDiagnosticOpts().IgnoreWarnings = true;
529
530  Remapper.applyMappings(CInvok->getPreprocessorOpts());
531
532  CapturedDiagList capturedDiags;
533  std::vector<SourceLocation> ARCMTMacroLocs;
534
535  assert(DiagClient);
536  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
537  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
538      new DiagnosticsEngine(DiagID, new DiagnosticOptions,
539                            DiagClient, /*ShouldOwnClient=*/false));
540
541  // Filter of all diagnostics.
542  CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
543  Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
544
545  std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
546  ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
547
548  std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
549      CInvok.release(), PCHContainerOps, Diags, ASTAction.get()));
550  if (!Unit) {
551    errRec.FinishCapture();
552    return true;
553  }
554  Unit->setOwnsRemappedFileBuffers(false); // FileRemapper manages that.
555
556  HadARCErrors = HadARCErrors || capturedDiags.hasErrors();
557
558  // Don't filter diagnostics anymore.
559  Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
560
561  ASTContext &Ctx = Unit->getASTContext();
562
563  if (Diags->hasFatalErrorOccurred()) {
564    Diags->Reset();
565    DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
566    capturedDiags.reportDiagnostics(*Diags);
567    DiagClient->EndSourceFile();
568    errRec.FinishCapture();
569    return true;
570  }
571
572  // After parsing of source files ended, we want to reuse the
573  // diagnostics objects to emit further diagnostics.
574  // We call BeginSourceFile because DiagnosticConsumer requires that
575  // diagnostics with source range information are emitted only in between
576  // BeginSourceFile() and EndSourceFile().
577  DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
578
579  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
580  TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
581  MigrationPass pass(Ctx, OrigCI.getLangOpts()->getGC(),
582                     Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
583
584  trans(pass);
585
586  {
587    RewritesApplicator applicator(rewriter, Ctx, listener);
588    TA.applyRewrites(applicator);
589  }
590
591  DiagClient->EndSourceFile();
592  errRec.FinishCapture();
593
594  if (DiagClient->getNumErrors())
595    return true;
596
597  for (Rewriter::buffer_iterator
598        I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
599    FileID FID = I->first;
600    RewriteBuffer &buf = I->second;
601    const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
602    assert(file);
603    std::string newFname = file->getName();
604    newFname += "-trans";
605    SmallString<512> newText;
606    llvm::raw_svector_ostream vecOS(newText);
607    buf.write(vecOS);
608    std::unique_ptr<llvm::MemoryBuffer> memBuf(
609        llvm::MemoryBuffer::getMemBufferCopy(
610            StringRef(newText.data(), newText.size()), newFname));
611    SmallString<64> filePath(file->getName());
612    Unit->getFileManager().FixupRelativePath(filePath);
613    Remapper.remap(filePath.str(), std::move(memBuf));
614  }
615
616  return false;
617}
618