static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI) { OwningPtr<CompilerInvocation> CInvok; CInvok.reset(new CompilerInvocation(origCI)); CInvok->getPreprocessorOpts().ImplicitPCHInclude = std::string(); CInvok->getPreprocessorOpts().ImplicitPTHInclude = std::string(); std::string define = getARCMTMacroName(); define += '='; CInvok->getPreprocessorOpts().addMacroDef(define); CInvok->getLangOpts()->ObjCAutoRefCount = true; CInvok->getLangOpts()->setGC(LangOptions::NonGC); CInvok->getDiagnosticOpts().ErrorLimit = 0; CInvok->getDiagnosticOpts().PedanticErrors = 0; // Ignore -Werror flags when migrating. std::vector<std::string> WarnOpts; for (std::vector<std::string>::iterator I = CInvok->getDiagnosticOpts().Warnings.begin(), E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) { if (!StringRef(*I).startswith("error")) WarnOpts.push_back(*I); } WarnOpts.push_back("error=arc-unsafe-retained-assign"); CInvok->getDiagnosticOpts().Warnings = llvm_move(WarnOpts); CInvok->getLangOpts()->ObjCRuntimeHasWeak = HasARCRuntime(origCI); return CInvok.take(); }
static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI) { OwningPtr<CompilerInvocation> CInvok; CInvok.reset(new CompilerInvocation(origCI)); PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); if (!PPOpts.ImplicitPCHInclude.empty()) { // We can't use a PCH because it was likely built in non-ARC mode and we // want to parse in ARC. Include the original header. FileManager FileMgr(origCI.getFileSystemOpts()); IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), new IgnoringDiagConsumer())); std::string OriginalFile = ASTReader::getOriginalSourceFile(PPOpts.ImplicitPCHInclude, FileMgr, *Diags); if (!OriginalFile.empty()) PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile); PPOpts.ImplicitPCHInclude.clear(); } // FIXME: Get the original header of a PTH as well. CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear(); std::string define = getARCMTMacroName(); define += '='; CInvok->getPreprocessorOpts().addMacroDef(define); CInvok->getLangOpts()->ObjCAutoRefCount = true; CInvok->getLangOpts()->setGC(LangOptions::NonGC); CInvok->getDiagnosticOpts().ErrorLimit = 0; CInvok->getDiagnosticOpts().PedanticErrors = 0; // Ignore -Werror flags when migrating. std::vector<std::string> WarnOpts; for (std::vector<std::string>::iterator I = CInvok->getDiagnosticOpts().Warnings.begin(), E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) { if (!StringRef(*I).startswith("error")) WarnOpts.push_back(*I); } WarnOpts.push_back("error=arc-unsafe-retained-assign"); CInvok->getDiagnosticOpts().Warnings = llvm_move(WarnOpts); CInvok->getLangOpts()->ObjCARCWeak = HasARCRuntime(origCI); return CInvok.take(); }
bool MigrationProcess::applyTransform(TransformFn trans, RewriteListener *listener) { OwningPtr<CompilerInvocation> CInvok; CInvok.reset(createInvocationForMigration(OrigCI)); CInvok->getDiagnosticOpts().IgnoreWarnings = true; Remapper.applyMappings(CInvok->getPreprocessorOpts()); CapturedDiagList capturedDiags; std::vector<SourceLocation> ARCMTMacroLocs; assert(DiagClient); IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); // Filter of all diagnostics. CaptureDiagnosticConsumer errRec(*Diags, capturedDiags); Diags->setClient(&errRec, /*ShouldOwnClient=*/false); OwningPtr<ARCMTMacroTrackerAction> ASTAction; ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs)); OwningPtr<ASTUnit> Unit( ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags, ASTAction.get())); if (!Unit) return true; Unit->setOwnsRemappedFileBuffers(false); // FileRemapper manages that. // Don't filter diagnostics anymore. Diags->setClient(DiagClient, /*ShouldOwnClient=*/false); ASTContext &Ctx = Unit->getASTContext(); if (Diags->hasFatalErrorOccurred()) { Diags->Reset(); DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor()); capturedDiags.reportDiagnostics(*Diags); DiagClient->EndSourceFile(); return true; } // After parsing of source files ended, we want to reuse the // diagnostics objects to emit further diagnostics. // We call BeginSourceFile because DiagnosticConsumer requires that // diagnostics with source range information are emitted only in between // BeginSourceFile() and EndSourceFile(). DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor()); Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); MigrationPass pass(Ctx, OrigCI.getLangOpts()->getGC(), Unit->getSema(), TA, ARCMTMacroLocs); trans(pass); { RewritesApplicator applicator(rewriter, Ctx, listener); TA.applyRewrites(applicator); } DiagClient->EndSourceFile(); if (DiagClient->getNumErrors()) return true; for (Rewriter::buffer_iterator I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { FileID FID = I->first; RewriteBuffer &buf = I->second; const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); assert(file); std::string newFname = file->getName(); newFname += "-trans"; SmallString<512> newText; llvm::raw_svector_ostream vecOS(newText); buf.write(vecOS); vecOS.flush(); llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy( StringRef(newText.data(), newText.size()), newFname); SmallString<64> filePath(file->getName()); Unit->getFileManager().FixupRelativePath(filePath); Remapper.remap(filePath.str(), memBuf); } return false; }