]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/lib/ARCMigrate/ARCMT.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / lib / ARCMigrate / ARCMT.cpp
1 //===--- ARCMT.cpp - Migration to ARC mode --------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Internals.h"
10 #include "clang/AST/ASTConsumer.h"
11 #include "clang/Basic/DiagnosticCategories.h"
12 #include "clang/Frontend/ASTUnit.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Frontend/FrontendAction.h"
15 #include "clang/Frontend/TextDiagnosticPrinter.h"
16 #include "clang/Frontend/Utils.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Lex/PreprocessorOptions.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          llvm::is_contained(IDs, I->getID())) &&
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          llvm::find(IDs, 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   std::string define = getARCMTMacroName();
193   define += '=';
194   CInvok->getPreprocessorOpts().addMacroDef(define);
195   CInvok->getLangOpts()->ObjCAutoRefCount = true;
196   CInvok->getLangOpts()->setGC(LangOptions::NonGC);
197   CInvok->getDiagnosticOpts().ErrorLimit = 0;
198   CInvok->getDiagnosticOpts().PedanticErrors = 0;
199
200   // Ignore -Werror flags when migrating.
201   std::vector<std::string> WarnOpts;
202   for (std::vector<std::string>::iterator
203          I = CInvok->getDiagnosticOpts().Warnings.begin(),
204          E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
205     if (!StringRef(*I).startswith("error"))
206       WarnOpts.push_back(*I);
207   }
208   WarnOpts.push_back("error=arc-unsafe-retained-assign");
209   CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
210
211   CInvok->getLangOpts()->ObjCWeakRuntime = HasARCRuntime(origCI);
212   CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
213
214   return CInvok.release();
215 }
216
217 static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
218                                    DiagnosticOptions *diagOpts,
219                                    Preprocessor &PP) {
220   TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
221   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
222   IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
223       new DiagnosticsEngine(DiagID, diagOpts, &printer,
224                             /*ShouldOwnClient=*/false));
225   Diags->setSourceManager(&PP.getSourceManager());
226
227   printer.BeginSourceFile(PP.getLangOpts(), &PP);
228   arcDiags.reportDiagnostics(*Diags);
229   printer.EndSourceFile();
230 }
231
232 //===----------------------------------------------------------------------===//
233 // checkForManualIssues.
234 //===----------------------------------------------------------------------===//
235
236 bool arcmt::checkForManualIssues(
237     CompilerInvocation &origCI, const FrontendInputFile &Input,
238     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
239     DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors,
240     StringRef plistOut) {
241   if (!origCI.getLangOpts()->ObjC)
242     return false;
243
244   LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
245   bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError;
246   bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
247
248   std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
249                                                                      NoFinalizeRemoval);
250   assert(!transforms.empty());
251
252   std::unique_ptr<CompilerInvocation> CInvok;
253   CInvok.reset(
254       createInvocationForMigration(origCI, PCHContainerOps->getRawReader()));
255   CInvok->getFrontendOpts().Inputs.clear();
256   CInvok->getFrontendOpts().Inputs.push_back(Input);
257
258   CapturedDiagList capturedDiags;
259
260   assert(DiagClient);
261   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
262   IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
263       new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
264                             DiagClient, /*ShouldOwnClient=*/false));
265
266   // Filter of all diagnostics.
267   CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
268   Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
269
270   std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
271       std::move(CInvok), PCHContainerOps, Diags));
272   if (!Unit) {
273     errRec.FinishCapture();
274     return true;
275   }
276
277   // Don't filter diagnostics anymore.
278   Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
279
280   ASTContext &Ctx = Unit->getASTContext();
281
282   if (Diags->hasFatalErrorOccurred()) {
283     Diags->Reset();
284     DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
285     capturedDiags.reportDiagnostics(*Diags);
286     DiagClient->EndSourceFile();
287     errRec.FinishCapture();
288     return true;
289   }
290
291   if (emitPremigrationARCErrors)
292     emitPremigrationErrors(capturedDiags, &origCI.getDiagnosticOpts(),
293                            Unit->getPreprocessor());
294   if (!plistOut.empty()) {
295     SmallVector<StoredDiagnostic, 8> arcDiags;
296     for (CapturedDiagList::iterator
297            I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
298       arcDiags.push_back(*I);
299     writeARCDiagsToPlist(plistOut, arcDiags,
300                          Ctx.getSourceManager(), Ctx.getLangOpts());
301   }
302
303   // After parsing of source files ended, we want to reuse the
304   // diagnostics objects to emit further diagnostics.
305   // We call BeginSourceFile because DiagnosticConsumer requires that
306   // diagnostics with source range information are emitted only in between
307   // BeginSourceFile() and EndSourceFile().
308   DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
309
310   // No macros will be added since we are just checking and we won't modify
311   // source code.
312   std::vector<SourceLocation> ARCMTMacroLocs;
313
314   TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
315   MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
316                      ARCMTMacroLocs);
317   pass.setNoFinalizeRemoval(NoFinalizeRemoval);
318   if (!NoNSAllocReallocError)
319     Diags->setSeverity(diag::warn_arcmt_nsalloc_realloc, diag::Severity::Error,
320                        SourceLocation());
321
322   for (unsigned i=0, e = transforms.size(); i != e; ++i)
323     transforms[i](pass);
324
325   capturedDiags.reportDiagnostics(*Diags);
326
327   DiagClient->EndSourceFile();
328   errRec.FinishCapture();
329
330   return capturedDiags.hasErrors() || testAct.hasReportedErrors();
331 }
332
333 //===----------------------------------------------------------------------===//
334 // applyTransformations.
335 //===----------------------------------------------------------------------===//
336
337 static bool
338 applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input,
339                 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
340                 DiagnosticConsumer *DiagClient, StringRef outputDir,
341                 bool emitPremigrationARCErrors, StringRef plistOut) {
342   if (!origCI.getLangOpts()->ObjC)
343     return false;
344
345   LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
346
347   // Make sure checking is successful first.
348   CompilerInvocation CInvokForCheck(origCI);
349   if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps,
350                                   DiagClient, emitPremigrationARCErrors,
351                                   plistOut))
352     return true;
353
354   CompilerInvocation CInvok(origCI);
355   CInvok.getFrontendOpts().Inputs.clear();
356   CInvok.getFrontendOpts().Inputs.push_back(Input);
357
358   MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir);
359   bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
360
361   std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
362                                                                      NoFinalizeRemoval);
363   assert(!transforms.empty());
364
365   for (unsigned i=0, e = transforms.size(); i != e; ++i) {
366     bool err = migration.applyTransform(transforms[i]);
367     if (err) return true;
368   }
369
370   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
371   IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
372       new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
373                             DiagClient, /*ShouldOwnClient=*/false));
374
375   if (outputDir.empty()) {
376     origCI.getLangOpts()->ObjCAutoRefCount = true;
377     return migration.getRemapper().overwriteOriginal(*Diags);
378   } else {
379     return migration.getRemapper().flushToDisk(outputDir, *Diags);
380   }
381 }
382
383 bool arcmt::applyTransformations(
384     CompilerInvocation &origCI, const FrontendInputFile &Input,
385     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
386     DiagnosticConsumer *DiagClient) {
387   return applyTransforms(origCI, Input, PCHContainerOps, DiagClient,
388                          StringRef(), false, StringRef());
389 }
390
391 bool arcmt::migrateWithTemporaryFiles(
392     CompilerInvocation &origCI, const FrontendInputFile &Input,
393     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
394     DiagnosticConsumer *DiagClient, StringRef outputDir,
395     bool emitPremigrationARCErrors, StringRef plistOut) {
396   assert(!outputDir.empty() && "Expected output directory path");
397   return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
398                          emitPremigrationARCErrors, plistOut);
399 }
400
401 bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
402                                   remap,
403                               StringRef outputDir,
404                               DiagnosticConsumer *DiagClient) {
405   assert(!outputDir.empty());
406
407   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
408   IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
409       new DiagnosticsEngine(DiagID, new DiagnosticOptions,
410                             DiagClient, /*ShouldOwnClient=*/false));
411
412   FileRemapper remapper;
413   bool err = remapper.initFromDisk(outputDir, *Diags,
414                                    /*ignoreIfFilesChanged=*/true);
415   if (err)
416     return true;
417
418   PreprocessorOptions PPOpts;
419   remapper.applyMappings(PPOpts);
420   remap = PPOpts.RemappedFiles;
421
422   return false;
423 }
424
425
426 //===----------------------------------------------------------------------===//
427 // CollectTransformActions.
428 //===----------------------------------------------------------------------===//
429
430 namespace {
431
432 class ARCMTMacroTrackerPPCallbacks : public PPCallbacks {
433   std::vector<SourceLocation> &ARCMTMacroLocs;
434
435 public:
436   ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
437     : ARCMTMacroLocs(ARCMTMacroLocs) { }
438
439   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
440                     SourceRange Range, const MacroArgs *Args) override {
441     if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
442       ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
443   }
444 };
445
446 class ARCMTMacroTrackerAction : public ASTFrontendAction {
447   std::vector<SourceLocation> &ARCMTMacroLocs;
448
449 public:
450   ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
451     : ARCMTMacroLocs(ARCMTMacroLocs) { }
452
453   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
454                                                  StringRef InFile) override {
455     CI.getPreprocessor().addPPCallbacks(
456                llvm::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
457     return llvm::make_unique<ASTConsumer>();
458   }
459 };
460
461 class RewritesApplicator : public TransformActions::RewriteReceiver {
462   Rewriter &rewriter;
463   MigrationProcess::RewriteListener *Listener;
464
465 public:
466   RewritesApplicator(Rewriter &rewriter, ASTContext &ctx,
467                      MigrationProcess::RewriteListener *listener)
468     : rewriter(rewriter), Listener(listener) {
469     if (Listener)
470       Listener->start(ctx);
471   }
472   ~RewritesApplicator() override {
473     if (Listener)
474       Listener->finish();
475   }
476
477   void insert(SourceLocation loc, StringRef text) override {
478     bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true,
479                                    /*indentNewLines=*/true);
480     if (!err && Listener)
481       Listener->insert(loc, text);
482   }
483
484   void remove(CharSourceRange range) override {
485     Rewriter::RewriteOptions removeOpts;
486     removeOpts.IncludeInsertsAtBeginOfRange = false;
487     removeOpts.IncludeInsertsAtEndOfRange = false;
488     removeOpts.RemoveLineIfEmpty = true;
489
490     bool err = rewriter.RemoveText(range, removeOpts);
491     if (!err && Listener)
492       Listener->remove(range);
493   }
494
495   void increaseIndentation(CharSourceRange range,
496                             SourceLocation parentIndent) override {
497     rewriter.IncreaseIndentation(range, parentIndent);
498   }
499 };
500
501 } // end anonymous namespace.
502
503 /// Anchor for VTable.
504 MigrationProcess::RewriteListener::~RewriteListener() { }
505
506 MigrationProcess::MigrationProcess(
507     const CompilerInvocation &CI,
508     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
509     DiagnosticConsumer *diagClient, StringRef outputDir)
510     : OrigCI(CI), PCHContainerOps(std::move(PCHContainerOps)),
511       DiagClient(diagClient), HadARCErrors(false) {
512   if (!outputDir.empty()) {
513     IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
514     IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
515       new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(),
516                             DiagClient, /*ShouldOwnClient=*/false));
517     Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanged=*/true);
518   }
519 }
520
521 bool MigrationProcess::applyTransform(TransformFn trans,
522                                       RewriteListener *listener) {
523   std::unique_ptr<CompilerInvocation> CInvok;
524   CInvok.reset(
525       createInvocationForMigration(OrigCI, PCHContainerOps->getRawReader()));
526   CInvok->getDiagnosticOpts().IgnoreWarnings = true;
527
528   Remapper.applyMappings(CInvok->getPreprocessorOpts());
529
530   CapturedDiagList capturedDiags;
531   std::vector<SourceLocation> ARCMTMacroLocs;
532
533   assert(DiagClient);
534   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
535   IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
536       new DiagnosticsEngine(DiagID, new DiagnosticOptions,
537                             DiagClient, /*ShouldOwnClient=*/false));
538
539   // Filter of all diagnostics.
540   CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
541   Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
542
543   std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
544   ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
545
546   std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
547       std::move(CInvok), PCHContainerOps, Diags, ASTAction.get()));
548   if (!Unit) {
549     errRec.FinishCapture();
550     return true;
551   }
552   Unit->setOwnsRemappedFileBuffers(false); // FileRemapper manages that.
553
554   HadARCErrors = HadARCErrors || capturedDiags.hasErrors();
555
556   // Don't filter diagnostics anymore.
557   Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
558
559   ASTContext &Ctx = Unit->getASTContext();
560
561   if (Diags->hasFatalErrorOccurred()) {
562     Diags->Reset();
563     DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
564     capturedDiags.reportDiagnostics(*Diags);
565     DiagClient->EndSourceFile();
566     errRec.FinishCapture();
567     return true;
568   }
569
570   // After parsing of source files ended, we want to reuse the
571   // diagnostics objects to emit further diagnostics.
572   // We call BeginSourceFile because DiagnosticConsumer requires that
573   // diagnostics with source range information are emitted only in between
574   // BeginSourceFile() and EndSourceFile().
575   DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
576
577   Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
578   TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
579   MigrationPass pass(Ctx, OrigCI.getLangOpts()->getGC(),
580                      Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
581
582   trans(pass);
583
584   {
585     RewritesApplicator applicator(rewriter, Ctx, listener);
586     TA.applyRewrites(applicator);
587   }
588
589   DiagClient->EndSourceFile();
590   errRec.FinishCapture();
591
592   if (DiagClient->getNumErrors())
593     return true;
594
595   for (Rewriter::buffer_iterator
596         I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
597     FileID FID = I->first;
598     RewriteBuffer &buf = I->second;
599     const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
600     assert(file);
601     std::string newFname = file->getName();
602     newFname += "-trans";
603     SmallString<512> newText;
604     llvm::raw_svector_ostream vecOS(newText);
605     buf.write(vecOS);
606     std::unique_ptr<llvm::MemoryBuffer> memBuf(
607         llvm::MemoryBuffer::getMemBufferCopy(
608             StringRef(newText.data(), newText.size()), newFname));
609     SmallString<64> filePath(file->getName());
610     Unit->getFileManager().FixupRelativePath(filePath);
611     Remapper.remap(filePath.str(), std::move(memBuf));
612   }
613
614   return false;
615 }