clang  10.0.0svn
ARCMT.cpp
Go to the documentation of this file.
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"
12 #include "clang/Frontend/ASTUnit.h"
16 #include "clang/Frontend/Utils.h"
17 #include "clang/Lex/Preprocessor.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 
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 
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 
81  for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
82  Diags.Report(*I);
83 }
84 
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 {
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(true);
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 *
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());
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);
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 
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);
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()) {
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
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 
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 
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 
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 
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 {
456  std::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
457  return std::make_unique<ASTConsumer>();
458  }
459 };
460 
461 class RewritesApplicator : public TransformActions::RewriteReceiver {
462  Rewriter &rewriter;
464 
465 public:
466  RewritesApplicator(Rewriter &rewriter, ASTContext &ctx,
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.
505 
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()) {
515  new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(),
516  DiagClient, /*ShouldOwnClient=*/false));
517  Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanged=*/true);
518  }
519 }
520 
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);
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 
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 }
bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent)
Increase indentation for the lines between the given source range.
Definition: Rewriter.cpp:344
Implements support for file system lookup, file system caching, and directory search management...
Definition: FileManager.h:171
ListTy::const_iterator iterator
Definition: Internals.h:38
static StringRef getARCMTMacroName()
Definition: Internals.h:172
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Definition: Diagnostic.h:1438
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:383
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:1673
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1290
void push_back(const StoredDiagnostic &diag)
Definition: Internals.h:29
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts=RewriteOptions())
RemoveText - Remove the specified text region.
Definition: Rewriter.cpp:308
bool hasDiagnostic(ArrayRef< unsigned > IDs, SourceRange range) const
Definition: ARCMT.cpp:58
RangeSelector range(RangeSelector Begin, RangeSelector End)
Selects from the start of Begin and to the end of End.
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
Definition: Diagnostic.h:1521
void applyMappings(PreprocessorOptions &PPOpts) const
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1489
RewriteBuffer - As code is rewritten, SourceBuffer&#39;s from the original input with modifications get a...
Definition: RewriteBuffer.h:25
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:35
void setNoFinalizeRemoval(bool val)
Definition: Internals.h:167
unsigned getID() const
Definition: Diagnostic.h:1327
virtual ~RewriteListener()
Anchor for VTable.
Definition: ARCMT.cpp:504
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:160
unsigned getNumErrors() const
Definition: Diagnostic.h:1498
Definition: Format.h:2392
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
iterator begin() const
Definition: Internals.h:39
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:904
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
Definition: ARCMT.cpp:28
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
const SourceLocation & getLocation() const
Definition: Diagnostic.h:1328
void reportDiagnostics(DiagnosticsEngine &diags) const
Definition: ARCMT.cpp:80
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:149
static void emitPremigrationErrors(const CapturedDiagList &arcDiags, DiagnosticOptions *diagOpts, Preprocessor &PP)
Definition: ARCMT.cpp:217
virtual void remove(CharSourceRange range)
Definition: ARCMT.h:118
Present this diagnostic as an error.
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
FrontendOptions & getFrontendOpts()
MigratorOptions & getMigratorOpts()
Represents a character-granular source range.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
Definition: MacroArgs.h:29
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:126
Defines the clang::Preprocessor interface.
void writeARCDiagsToPlist(const std::string &outPath, ArrayRef< StoredDiagnostic > diags, SourceManager &SM, const LangOptions &LangOpts)
static bool applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut)
Definition: ARCMT.cpp:338
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:236
bool isInvalid() const
static bool HasARCRuntime(CompilerInvocation &origCI)
Definition: ARCMT.cpp:148
void EndSourceFile() override
Callback to inform the diagnostic client that processing of a source file has ended.
MigrationProcess(const CompilerInvocation &CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *diagClient, StringRef outputDir=StringRef())
Definition: ARCMT.cpp:506
SourceLocation getEnd() const
An input file for the front end.
virtual void insert(SourceLocation loc, StringRef text)
Definition: ARCMT.h:117
SourceManager & getSourceManager() const
Definition: Preprocessor.h:908
static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI, const PCHContainerReader &PCHContainerRdr)
Definition: ARCMT.cpp:173
#define false
Definition: stdbool.h:17
bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
Definition: Rewriter.cpp:37
StringRef getName() const
Definition: FileManager.h:102
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
Options for controlling the compiler diagnostics engine.
std::vector< FrontendInputFile > Inputs
The input files and their types.
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:179
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:78
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer...
Definition: Rewriter.cpp:255
Abstract base class to use for AST consumer-based frontend actions.
DiagnosticOptions & getDiagnosticOpts() const
bool RemoveLineIfEmpty
If true and removing some text leaves a blank line also remove the empty line (false by default)...
Definition: Rewriter.h:60
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:391
void setLastDiagnosticIgnored(bool Ignored)
Pretend that the last diagnostic issued was ignored, so any subsequent notes will be suppressed...
Definition: Diagnostic.h:668
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
Definition: Rewriter.h:65
void(* TransformFn)(MigrationPass &pass)
Definition: ARCMT.h:91
StringRef getName() const
Return the actual identifier string.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Dataflow Directional Tag Classes.
A diagnostic client that ignores all diagnostics.
Definition: Diagnostic.h:1544
bool isValid() const
Return true if this is a valid SourceLocation object.
std::vector< TransformFn > getAllTransformations(LangOptions::GCMode OrigGCMode, bool NoFinalizeRemoval)
Definition: Transforms.cpp:582
Used for handling and querying diagnostic IDs.
Helper class for holding the data necessary to invoke the compiler.
static ASTUnit * LoadFromCompilerInvocationAction(std::shared_ptr< CompilerInvocation > CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, FrontendAction *Action=nullptr, ASTUnit *Unit=nullptr, bool Persistent=true, StringRef ResourceFilesPath=StringRef(), bool OnlyLocalDecls=false, CaptureDiagsKind CaptureDiagnostics=CaptureDiagsKind::None, unsigned PrecompilePreambleAfterNParses=0, 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:1512
virtual void start(ASTContext &Ctx)
Definition: ARCMT.h:114
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:41
SourceManager & getSourceManager()
Definition: ASTContext.h:678
Preprocessor & getPreprocessor() const
Return the current preprocessor.
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
Rewriter - This is the main interface to the rewrite buffers.
Definition: Rewriter.h:32
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:152
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...
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1317
FileRemapper & getRemapper()
Definition: ARCMT.h:123
A SourceLocation and its associated SourceManager.
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
bool applyTransform(TransformFn trans, RewriteListener *listener=nullptr)
Definition: ARCMT.cpp:521
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:1513
SourceLocation getBegin() const
std::string Triple
The name of the target triple to compile for.
Definition: TargetOptions.h:29
const LangOptions & getLangOpts() const
Definition: ASTContext.h:723
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:401
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:996
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:125
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:45