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; }
ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes; assert(!includes.empty() && "No '-chain-include' in options!"); OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource()); InputKind IK = CI.getFrontendOpts().Inputs[0].getKind(); SmallVector<llvm::MemoryBuffer *, 4> serialBufs; SmallVector<std::string, 4> serialBufNames; for (unsigned i = 0, e = includes.size(); i != e; ++i) { bool firstInclude = (i == 0); OwningPtr<CompilerInvocation> CInvok; CInvok.reset(new CompilerInvocation(CI.getInvocation())); CInvok->getPreprocessorOpts().ChainedIncludes.clear(); CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear(); CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear(); CInvok->getPreprocessorOpts().DisablePCHValidation = true; CInvok->getPreprocessorOpts().Includes.clear(); CInvok->getPreprocessorOpts().MacroIncludes.clear(); CInvok->getPreprocessorOpts().Macros.clear(); CInvok->getFrontendOpts().Inputs.clear(); FrontendInputFile InputFile(includes[i], IK); CInvok->getFrontendOpts().Inputs.push_back(InputFile); TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions()); IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> Diags( new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient)); OwningPtr<CompilerInstance> Clang(new CompilerInstance()); Clang->setInvocation(CInvok.take()); Clang->setDiagnostics(Diags.getPtr()); Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), Clang->getTargetOpts())); Clang->createFileManager(); Clang->createSourceManager(Clang->getFileManager()); Clang->createPreprocessor(); Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), &Clang->getPreprocessor()); Clang->createASTContext(); SmallVector<char, 256> serialAST; llvm::raw_svector_ostream OS(serialAST); OwningPtr<ASTConsumer> consumer; consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0, /*isysroot=*/"", &OS)); Clang->getPreprocessor().setPPMutationListener( consumer->GetPPMutationListener()); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(consumer.take()); Clang->createSema(TU_Prefix, 0); if (firstInclude) { Preprocessor &PP = Clang->getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); } else { assert(!serialBufs.empty()); SmallVector<llvm::MemoryBuffer *, 4> bufs; for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) { bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy( StringRef(serialBufs[si]->getBufferStart(), serialBufs[si]->getBufferSize()))); } std::string pchName = includes[i-1]; llvm::raw_string_ostream os(pchName); os << ".pch" << i-1; os.flush(); serialBufNames.push_back(pchName); OwningPtr<ExternalASTSource> Reader; Reader.reset(createASTReader(*Clang, pchName, bufs, serialBufNames, Clang->getASTConsumer().GetASTDeserializationListener())); if (!Reader) return 0; Clang->getASTContext().setExternalSource(Reader); } if (!Clang->InitializeSourceManager(InputFile)) return 0; ParseAST(Clang->getSema()); OS.flush(); Clang->getDiagnosticClient().EndSourceFile(); serialBufs.push_back( llvm::MemoryBuffer::getMemBufferCopy(StringRef(serialAST.data(), serialAST.size()))); source->CIs.push_back(Clang.take()); } assert(!serialBufs.empty()); std::string pchName = includes.back() + ".pch-final"; serialBufNames.push_back(pchName); OwningPtr<ASTReader> Reader; Reader.reset(createASTReader(CI, pchName, serialBufs, serialBufNames)); if (!Reader) return 0; source->FinalReader.reset(Reader.take()); return source.take(); }