clang  3.7.0
ARCMT.cpp
Go to the documentation of this file.
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"
13 #include "clang/Frontend/ASTUnit.h"
17 #include "clang/Frontend/Utils.h"
18 #include "clang/Lex/Preprocessor.h"
22 #include "llvm/ADT/Triple.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 using namespace clang;
25 using namespace arcmt;
26 
28  SourceRange range) {
29  if (range.isInvalid())
30  return false;
31 
32  bool cleared = false;
33  ListTy::iterator I = List.begin();
34  while (I != List.end()) {
35  FullSourceLoc diagLoc = I->getLocation();
36  if ((IDs.empty() || // empty means clear all diagnostics in the range.
37  std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
38  !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
39  (diagLoc == range.getEnd() ||
40  diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
41  cleared = true;
42  ListTy::iterator eraseS = I++;
43  if (eraseS->getLevel() != DiagnosticsEngine::Note)
44  while (I != List.end() && I->getLevel() == DiagnosticsEngine::Note)
45  ++I;
46  // Clear the diagnostic and any notes following it.
47  I = List.erase(eraseS, I);
48  continue;
49  }
50 
51  ++I;
52  }
53 
54  return cleared;
55 }
56 
58  SourceRange range) const {
59  if (range.isInvalid())
60  return false;
61 
62  ListTy::const_iterator I = List.begin();
63  while (I != List.end()) {
64  FullSourceLoc diagLoc = I->getLocation();
65  if ((IDs.empty() || // empty means any diagnostic in the range.
66  std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
67  !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
68  (diagLoc == range.getEnd() ||
69  diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
70  return true;
71  }
72 
73  ++I;
74  }
75 
76  return false;
77 }
78 
80  for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
81  Diags.Report(*I);
82 }
83 
85  for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
86  if (I->getLevel() >= DiagnosticsEngine::Error)
87  return true;
88 
89  return false;
90 }
91 
92 namespace {
93 
94 class CaptureDiagnosticConsumer : public DiagnosticConsumer {
95  DiagnosticsEngine &Diags;
96  DiagnosticConsumer &DiagClient;
97  CapturedDiagList &CapturedDiags;
98  bool HasBegunSourceFile;
99 public:
100  CaptureDiagnosticConsumer(DiagnosticsEngine &diags,
101  DiagnosticConsumer &client,
102  CapturedDiagList &capturedDiags)
103  : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags),
104  HasBegunSourceFile(false) { }
105 
106  void BeginSourceFile(const LangOptions &Opts,
107  const Preprocessor *PP) override {
108  // Pass BeginSourceFile message onto DiagClient on first call.
109  // The corresponding EndSourceFile call will be made from an
110  // explicit call to FinishCapture.
111  if (!HasBegunSourceFile) {
112  DiagClient.BeginSourceFile(Opts, PP);
113  HasBegunSourceFile = true;
114  }
115  }
116 
117  void FinishCapture() {
118  // Call EndSourceFile on DiagClient on completion of capture to
119  // enable VerifyDiagnosticConsumer to check diagnostics *after*
120  // it has received the diagnostic list.
121  if (HasBegunSourceFile) {
122  DiagClient.EndSourceFile();
123  HasBegunSourceFile = false;
124  }
125  }
126 
127  ~CaptureDiagnosticConsumer() override {
128  assert(!HasBegunSourceFile && "FinishCapture not called!");
129  }
130 
131  void HandleDiagnostic(DiagnosticsEngine::Level level,
132  const Diagnostic &Info) override {
134  level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) {
135  if (Info.getLocation().isValid())
136  CapturedDiags.push_back(StoredDiagnostic(level, Info));
137  return;
138  }
139 
140  // Non-ARC warnings are ignored.
141  Diags.setLastDiagnosticIgnored();
142  }
143 };
144 
145 } // end anonymous namespace
146 
147 static bool HasARCRuntime(CompilerInvocation &origCI) {
148  // This duplicates some functionality from Darwin::AddDeploymentTarget
149  // but this function is well defined, so keep it decoupled from the driver
150  // and avoid unrelated complications.
151  llvm::Triple triple(origCI.getTargetOpts().Triple);
152 
153  if (triple.isiOS())
154  return triple.getOSMajorVersion() >= 5;
155 
156  if (triple.getOS() == llvm::Triple::Darwin)
157  return triple.getOSMajorVersion() >= 11;
158 
159  if (triple.getOS() == llvm::Triple::MacOSX) {
160  unsigned Major, Minor, Micro;
161  triple.getOSVersion(Major, Minor, Micro);
162  return Major > 10 || (Major == 10 && Minor >= 7);
163  }
164 
165  return false;
166 }
167 
168 static CompilerInvocation *
170  const PCHContainerReader &PCHContainerRdr) {
171  std::unique_ptr<CompilerInvocation> CInvok;
172  CInvok.reset(new CompilerInvocation(origCI));
173  PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
174  if (!PPOpts.ImplicitPCHInclude.empty()) {
175  // We can't use a PCH because it was likely built in non-ARC mode and we
176  // want to parse in ARC. Include the original header.
177  FileManager FileMgr(origCI.getFileSystemOpts());
180  new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
181  new IgnoringDiagConsumer()));
182  std::string OriginalFile = ASTReader::getOriginalSourceFile(
183  PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerRdr, *Diags);
184  if (!OriginalFile.empty())
185  PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile);
186  PPOpts.ImplicitPCHInclude.clear();
187  }
188  // FIXME: Get the original header of a PTH as well.
189  CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
190  std::string define = getARCMTMacroName();
191  define += '=';
192  CInvok->getPreprocessorOpts().addMacroDef(define);
193  CInvok->getLangOpts()->ObjCAutoRefCount = true;
194  CInvok->getLangOpts()->setGC(LangOptions::NonGC);
195  CInvok->getDiagnosticOpts().ErrorLimit = 0;
196  CInvok->getDiagnosticOpts().PedanticErrors = 0;
197 
198  // Ignore -Werror flags when migrating.
199  std::vector<std::string> WarnOpts;
200  for (std::vector<std::string>::iterator
201  I = CInvok->getDiagnosticOpts().Warnings.begin(),
202  E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
203  if (!StringRef(*I).startswith("error"))
204  WarnOpts.push_back(*I);
205  }
206  WarnOpts.push_back("error=arc-unsafe-retained-assign");
207  CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
208 
209  CInvok->getLangOpts()->ObjCARCWeak = HasARCRuntime(origCI);
210 
211  return CInvok.release();
212 }
213 
214 static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
215  DiagnosticOptions *diagOpts,
216  Preprocessor &PP) {
217  TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
220  new DiagnosticsEngine(DiagID, diagOpts, &printer,
221  /*ShouldOwnClient=*/false));
222  Diags->setSourceManager(&PP.getSourceManager());
223 
224  printer.BeginSourceFile(PP.getLangOpts(), &PP);
225  arcDiags.reportDiagnostics(*Diags);
226  printer.EndSourceFile();
227 }
228 
229 //===----------------------------------------------------------------------===//
230 // checkForManualIssues.
231 //===----------------------------------------------------------------------===//
232 
235  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
236  DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors,
237  StringRef plistOut) {
238  if (!origCI.getLangOpts()->ObjC1)
239  return false;
240 
241  LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
242  bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError;
243  bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
244 
245  std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
246  NoFinalizeRemoval);
247  assert(!transforms.empty());
248 
249  std::unique_ptr<CompilerInvocation> CInvok;
250  CInvok.reset(
251  createInvocationForMigration(origCI, PCHContainerOps->getRawReader()));
252  CInvok->getFrontendOpts().Inputs.clear();
253  CInvok->getFrontendOpts().Inputs.push_back(Input);
254 
255  CapturedDiagList capturedDiags;
256 
257  assert(DiagClient);
260  new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
261  DiagClient, /*ShouldOwnClient=*/false));
262 
263  // Filter of all diagnostics.
264  CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
265  Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
266 
267  std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
268  CInvok.release(), PCHContainerOps, Diags));
269  if (!Unit) {
270  errRec.FinishCapture();
271  return true;
272  }
273 
274  // Don't filter diagnostics anymore.
275  Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
276 
277  ASTContext &Ctx = Unit->getASTContext();
278 
279  if (Diags->hasFatalErrorOccurred()) {
280  Diags->Reset();
281  DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
282  capturedDiags.reportDiagnostics(*Diags);
283  DiagClient->EndSourceFile();
284  errRec.FinishCapture();
285  return true;
286  }
287 
288  if (emitPremigrationARCErrors)
289  emitPremigrationErrors(capturedDiags, &origCI.getDiagnosticOpts(),
290  Unit->getPreprocessor());
291  if (!plistOut.empty()) {
294  I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
295  arcDiags.push_back(*I);
296  writeARCDiagsToPlist(plistOut, arcDiags,
297  Ctx.getSourceManager(), Ctx.getLangOpts());
298  }
299 
300  // After parsing of source files ended, we want to reuse the
301  // diagnostics objects to emit further diagnostics.
302  // We call BeginSourceFile because DiagnosticConsumer requires that
303  // diagnostics with source range information are emitted only in between
304  // BeginSourceFile() and EndSourceFile().
305  DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
306 
307  // No macros will be added since we are just checking and we won't modify
308  // source code.
309  std::vector<SourceLocation> ARCMTMacroLocs;
310 
311  TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
312  MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
313  ARCMTMacroLocs);
314  pass.setNoFinalizeRemoval(NoFinalizeRemoval);
315  if (!NoNSAllocReallocError)
316  Diags->setSeverity(diag::warn_arcmt_nsalloc_realloc, diag::Severity::Error,
317  SourceLocation());
318 
319  for (unsigned i=0, e = transforms.size(); i != e; ++i)
320  transforms[i](pass);
321 
322  capturedDiags.reportDiagnostics(*Diags);
323 
324  DiagClient->EndSourceFile();
325  errRec.FinishCapture();
326 
327  return capturedDiags.hasErrors() || testAct.hasReportedErrors();
328 }
329 
330 //===----------------------------------------------------------------------===//
331 // applyTransformations.
332 //===----------------------------------------------------------------------===//
333 
334 static bool
336  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
337  DiagnosticConsumer *DiagClient, StringRef outputDir,
338  bool emitPremigrationARCErrors, StringRef plistOut) {
339  if (!origCI.getLangOpts()->ObjC1)
340  return false;
341 
342  LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
343 
344  // Make sure checking is successful first.
345  CompilerInvocation CInvokForCheck(origCI);
346  if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps,
347  DiagClient, emitPremigrationARCErrors,
348  plistOut))
349  return true;
350 
351  CompilerInvocation CInvok(origCI);
352  CInvok.getFrontendOpts().Inputs.clear();
353  CInvok.getFrontendOpts().Inputs.push_back(Input);
354 
355  MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir);
356  bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
357 
358  std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
359  NoFinalizeRemoval);
360  assert(!transforms.empty());
361 
362  for (unsigned i=0, e = transforms.size(); i != e; ++i) {
363  bool err = migration.applyTransform(transforms[i]);
364  if (err) return true;
365  }
366 
369  new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
370  DiagClient, /*ShouldOwnClient=*/false));
371 
372  if (outputDir.empty()) {
373  origCI.getLangOpts()->ObjCAutoRefCount = true;
374  return migration.getRemapper().overwriteOriginal(*Diags);
375  } else {
376  return migration.getRemapper().flushToDisk(outputDir, *Diags);
377  }
378 }
379 
382  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
383  DiagnosticConsumer *DiagClient) {
384  return applyTransforms(origCI, Input, PCHContainerOps, DiagClient,
385  StringRef(), false, StringRef());
386 }
387 
390  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
391  DiagnosticConsumer *DiagClient, StringRef outputDir,
392  bool emitPremigrationARCErrors, StringRef plistOut) {
393  assert(!outputDir.empty() && "Expected output directory path");
394  return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
395  emitPremigrationARCErrors, plistOut);
396 }
397 
398 bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
399  remap,
400  StringRef outputDir,
401  DiagnosticConsumer *DiagClient) {
402  assert(!outputDir.empty());
403 
406  new DiagnosticsEngine(DiagID, new DiagnosticOptions,
407  DiagClient, /*ShouldOwnClient=*/false));
408 
409  FileRemapper remapper;
410  bool err = remapper.initFromDisk(outputDir, *Diags,
411  /*ignoreIfFilesChanged=*/true);
412  if (err)
413  return true;
414 
415  PreprocessorOptions PPOpts;
416  remapper.applyMappings(PPOpts);
417  remap = PPOpts.RemappedFiles;
418 
419  return false;
420 }
421 
422 
423 //===----------------------------------------------------------------------===//
424 // CollectTransformActions.
425 //===----------------------------------------------------------------------===//
426 
427 namespace {
428 
429 class ARCMTMacroTrackerPPCallbacks : public PPCallbacks {
430  std::vector<SourceLocation> &ARCMTMacroLocs;
431 
432 public:
433  ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
434  : ARCMTMacroLocs(ARCMTMacroLocs) { }
435 
436  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
437  SourceRange Range, const MacroArgs *Args) override {
438  if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
439  ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
440  }
441 };
442 
443 class ARCMTMacroTrackerAction : public ASTFrontendAction {
444  std::vector<SourceLocation> &ARCMTMacroLocs;
445 
446 public:
447  ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
448  : ARCMTMacroLocs(ARCMTMacroLocs) { }
449 
450  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
451  StringRef InFile) override {
453  llvm::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
454  return llvm::make_unique<ASTConsumer>();
455  }
456 };
457 
458 class RewritesApplicator : public TransformActions::RewriteReceiver {
459  Rewriter &rewriter;
461 
462 public:
463  RewritesApplicator(Rewriter &rewriter, ASTContext &ctx,
465  : rewriter(rewriter), Listener(listener) {
466  if (Listener)
467  Listener->start(ctx);
468  }
469  ~RewritesApplicator() override {
470  if (Listener)
471  Listener->finish();
472  }
473 
474  void insert(SourceLocation loc, StringRef text) override {
475  bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true,
476  /*indentNewLines=*/true);
477  if (!err && Listener)
478  Listener->insert(loc, text);
479  }
480 
481  void remove(CharSourceRange range) override {
482  Rewriter::RewriteOptions removeOpts;
483  removeOpts.IncludeInsertsAtBeginOfRange = false;
484  removeOpts.IncludeInsertsAtEndOfRange = false;
485  removeOpts.RemoveLineIfEmpty = true;
486 
487  bool err = rewriter.RemoveText(range, removeOpts);
488  if (!err && Listener)
489  Listener->remove(range);
490  }
491 
492  void increaseIndentation(CharSourceRange range,
493  SourceLocation parentIndent) override {
494  rewriter.IncreaseIndentation(range, parentIndent);
495  }
496 };
497 
498 } // end anonymous namespace.
499 
500 /// \brief Anchor for VTable.
502 
504  const CompilerInvocation &CI,
505  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
506  DiagnosticConsumer *diagClient, StringRef outputDir)
507  : OrigCI(CI), PCHContainerOps(PCHContainerOps), DiagClient(diagClient),
509  if (!outputDir.empty()) {
512  new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(),
513  DiagClient, /*ShouldOwnClient=*/false));
514  Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true);
515  }
516 }
517 
519  RewriteListener *listener) {
520  std::unique_ptr<CompilerInvocation> CInvok;
521  CInvok.reset(
522  createInvocationForMigration(OrigCI, PCHContainerOps->getRawReader()));
523  CInvok->getDiagnosticOpts().IgnoreWarnings = true;
524 
525  Remapper.applyMappings(CInvok->getPreprocessorOpts());
526 
527  CapturedDiagList capturedDiags;
528  std::vector<SourceLocation> ARCMTMacroLocs;
529 
530  assert(DiagClient);
533  new DiagnosticsEngine(DiagID, new DiagnosticOptions,
534  DiagClient, /*ShouldOwnClient=*/false));
535 
536  // Filter of all diagnostics.
537  CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
538  Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
539 
540  std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
541  ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
542 
543  std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
544  CInvok.release(), PCHContainerOps, Diags, ASTAction.get()));
545  if (!Unit) {
546  errRec.FinishCapture();
547  return true;
548  }
549  Unit->setOwnsRemappedFileBuffers(false); // FileRemapper manages that.
550 
551  HadARCErrors = HadARCErrors || capturedDiags.hasErrors();
552 
553  // Don't filter diagnostics anymore.
554  Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
555 
556  ASTContext &Ctx = Unit->getASTContext();
557 
558  if (Diags->hasFatalErrorOccurred()) {
559  Diags->Reset();
560  DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
561  capturedDiags.reportDiagnostics(*Diags);
562  DiagClient->EndSourceFile();
563  errRec.FinishCapture();
564  return true;
565  }
566 
567  // After parsing of source files ended, we want to reuse the
568  // diagnostics objects to emit further diagnostics.
569  // We call BeginSourceFile because DiagnosticConsumer requires that
570  // diagnostics with source range information are emitted only in between
571  // BeginSourceFile() and EndSourceFile().
572  DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
573 
574  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
575  TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
576  MigrationPass pass(Ctx, OrigCI.getLangOpts()->getGC(),
577  Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
578 
579  trans(pass);
580 
581  {
582  RewritesApplicator applicator(rewriter, Ctx, listener);
583  TA.applyRewrites(applicator);
584  }
585 
586  DiagClient->EndSourceFile();
587  errRec.FinishCapture();
588 
589  if (DiagClient->getNumErrors())
590  return true;
591 
593  I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
594  FileID FID = I->first;
595  RewriteBuffer &buf = I->second;
596  const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
597  assert(file);
598  std::string newFname = file->getName();
599  newFname += "-trans";
600  SmallString<512> newText;
601  llvm::raw_svector_ostream vecOS(newText);
602  buf.write(vecOS);
603  vecOS.flush();
604  std::unique_ptr<llvm::MemoryBuffer> memBuf(
605  llvm::MemoryBuffer::getMemBufferCopy(
606  StringRef(newText.data(), newText.size()), newFname));
607  SmallString<64> filePath(file->getName());
608  Unit->getFileManager().FixupRelativePath(filePath);
609  Remapper.remap(filePath.str(), std::move(memBuf));
610  }
611 
612  return false;
613 }
SourceManager & getSourceManager() const
Definition: Preprocessor.h:682
SourceLocation getEnd() const
void(* TransformFn)(MigrationPass &pass)
Definition: ARCMT.h:92
void reportDiagnostics(DiagnosticsEngine &diags) const
Definition: ARCMT.cpp:79
bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent)
Increase indentation for the lines between the given source range. To determine what the indentation ...
Definition: Rewriter.cpp:329
Implements support for file system lookup, file system caching, and directory search management...
Definition: FileManager.h:115
ListTy::const_iterator iterator
Definition: Internals.h:39
static StringRef getARCMTMacroName()
Definition: Internals.h:173
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Definition: Diagnostic.h:1258
bool applyTransformations(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient)
Works similar to checkForManualIssues but instead of checking, it applies automatic modifications to ...
Definition: ARCMT.cpp:380
std::vector< std::string > Includes
A description of the current definition of a macro.
Definition: MacroInfo.h:564
StringRef getOriginalSourceFile()
Retrieve the name of the original source file name for the primary module file.
Definition: ASTReader.h:1453
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1118
unsigned getID() const
Definition: Diagnostic.h:1147
bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts=RewriteOptions())
RemoveText - Remove the specified text region.
Definition: Rewriter.cpp:293
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
Definition: Diagnostic.h:1342
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1309
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:38
void setNoFinalizeRemoval(bool val)
Definition: Internals.h:168
virtual ~RewriteListener()
Anchor for VTable.
Definition: ARCMT.cpp:501
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:89
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:679
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
Definition: ARCMT.cpp:27
const LangOptions & getLangOpts() const
Definition: ASTContext.h:533
const SourceLocation & getLocation() const
Definition: Diagnostic.h:1148
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override
Callback to inform the diagnostic client that processing of a source file is beginning.
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:135
static void emitPremigrationErrors(const CapturedDiagList &arcDiags, DiagnosticOptions *diagOpts, Preprocessor &PP)
Definition: ARCMT.cpp:214
Present this diagnostic as an error.
bool hasDiagnostic(ArrayRef< unsigned > IDs, SourceRange range) const
Definition: ARCMT.cpp:57
iterator begin() const
Definition: Internals.h:40
Preprocessor & getPreprocessor() const
Return the current preprocessor.
buffer_iterator buffer_end()
Definition: Rewriter.h:178
FrontendOptions & getFrontendOpts()
MigratorOptions & getMigratorOpts()
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
StringRef getName() const
Return the actual identifier string.
Represents a character-granular source range.
Defines the clang::Preprocessor interface.
void writeARCDiagsToPlist(const std::string &outPath, ArrayRef< StoredDiagnostic > diags, SourceManager &SM, const LangOptions &LangOpts)
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:124
static bool applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut)
Definition: ARCMT.cpp:335
bool checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors=false, StringRef plistOut=StringRef())
Creates an AST with the provided CompilerInvocation but with these changes: -if a PCH/PTH is set...
Definition: ARCMT.cpp:233
static bool HasARCRuntime(CompilerInvocation &origCI)
Definition: ARCMT.cpp:147
void EndSourceFile() override
Callback to inform the diagnostic client that processing of a source file has ended.
void applyMappings(PreprocessorOptions &PPOpts) const
MigrationProcess(const CompilerInvocation &CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *diagClient, StringRef outputDir=StringRef())
Definition: ARCMT.cpp:503
An input file for the front end.
static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI, const PCHContainerReader &PCHContainerRdr)
Definition: ARCMT.cpp:169
#define false
Definition: stdbool.h:33
bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())
const char * getName() const
Definition: FileManager.h:84
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
bool isValid() const
Return true if this is a valid SourceLocation object.
Options for controlling the compiler diagnostics engine.
std::vector< FrontendInputFile > Inputs
The input files and their types.
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:53
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
Definition: Rewriter.cpp:240
Abstract base class to use for AST consumer-based frontend actions.
bool RemoveLineIfEmpty
If true and removing some text leaves a blank line also remove the empty line (false by default)...
Definition: Rewriter.h:45
SourceLocation getBegin() const
static ASTUnit * LoadFromCompilerInvocationAction(CompilerInvocation *CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, ASTFrontendAction *Action=nullptr, ASTUnit *Unit=nullptr, bool Persistent=true, StringRef ResourceFilesPath=StringRef(), bool OnlyLocalDecls=false, bool CaptureDiagnostics=false, bool PrecompilePreamble=false, bool CacheCodeCompletionResults=false, bool IncludeBriefCommentsInCodeCompletion=false, bool UserFilesAreVolatile=false, std::unique_ptr< ASTUnit > *ErrAST=nullptr)
Create an ASTUnit from a source file, via a CompilerInvocation object, by invoking the optionally pro...
Definition: ASTUnit.cpp:1722
bool migrateWithTemporaryFiles(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut)
Applies automatic modifications and produces temporary files and metadata into the outputDir path...
Definition: ARCMT.cpp:388
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
A diagnostic client that ignores all diagnostics.
Definition: Diagnostic.h:1365
std::vector< TransformFn > getAllTransformations(LangOptions::GCMode OrigGCMode, bool NoFinalizeRemoval)
Definition: Transforms.cpp:589
Used for handling and querying diagnostic IDs.
Helper class for holding the data necessary to invoke the compiler.
DiagnosticOptions & getDiagnosticOpts() const
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer. Note that it isn't safe to...
Definition: Rewriter.cpp:27
bool IncludeInsertsAtBeginOfRange
Given a source range, true to include previous inserts at the beginning of the range as part of the r...
Definition: Rewriter.h:39
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
Definition: Rewriter.h:53
iterator end() const
Definition: Internals.h:41
bool isInvalid() const
buffer_iterator buffer_begin()
Definition: Rewriter.h:177
SourceManager & getSourceManager()
Definition: ASTContext.h:494
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:141
FileSystemOptions & getFileSystemOpts()
std::vector< std::pair< std::string, std::string > > RemappedFiles
The set of file remappings, which take existing files on the system (the first part of each pair) and...
const StringRef Input
FileRemapper & getRemapper()
Definition: ARCMT.h:124
A SourceLocation and its associated SourceManager.
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
unsigned getNumErrors() const
Definition: Diagnostic.h:1317
bool applyTransform(TransformFn trans, RewriteListener *listener=nullptr)
Definition: ARCMT.cpp:518
A trivial tuple used to represent a source range.
virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP=nullptr)
Callback to inform the diagnostic client that processing of a source file is beginning.
Definition: Diagnostic.h:1334
bool getFileRemappings(std::vector< std::pair< std::string, std::string > > &remap, StringRef outputDir, DiagnosticConsumer *DiagClient)
Get the set of file remappings from the outputDir path that migrateWithTemporaryFiles produced...
Definition: ARCMT.cpp:398
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:773
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:96
bool IncludeInsertsAtEndOfRange
Given a source range, true to include previous inserts at the end of the range as part of the range i...
Definition: Rewriter.h:42
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177