]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
Merge ^/head r304700 through r304884.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / ARCMigrate / ARCMT.cpp
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>
25 using namespace clang;
26 using namespace arcmt;
27
28 bool 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
58 bool 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
80 void 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
85 bool 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
93 namespace {
94
95 class CaptureDiagnosticConsumer : public DiagnosticConsumer {
96   DiagnosticsEngine &Diags;
97   DiagnosticConsumer &DiagClient;
98   CapturedDiagList &CapturedDiags;
99   bool HasBegunSourceFile;
100 public:
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
148 static 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
172 static CompilerInvocation *
173 createInvocationForMigration(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
219 static 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
238 bool 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
339 static bool
340 applyTransforms(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
385 bool 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
393 bool 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
403 bool 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
432 namespace {
433
434 class ARCMTMacroTrackerPPCallbacks : public PPCallbacks {
435   std::vector<SourceLocation> &ARCMTMacroLocs;
436
437 public:
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
448 class ARCMTMacroTrackerAction : public ASTFrontendAction {
449   std::vector<SourceLocation> &ARCMTMacroLocs;
450
451 public:
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
463 class RewritesApplicator : public TransformActions::RewriteReceiver {
464   Rewriter &rewriter;
465   MigrationProcess::RewriteListener *Listener;
466
467 public:
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.
506 MigrationProcess::RewriteListener::~RewriteListener() { }
507
508 MigrationProcess::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
523 bool 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 }