bool arcmt::checkForManualIssues(CompilerInvocation &origCI, const FrontendInputFile &Input, DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors, StringRef plistOut) { if (!origCI.getLangOpts()->ObjC1) return false; LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC(); bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError; bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode, NoFinalizeRemoval); assert(!transforms.empty()); OwningPtr<CompilerInvocation> CInvok; CInvok.reset(createInvocationForMigration(origCI)); CInvok->getFrontendOpts().Inputs.clear(); CInvok->getFrontendOpts().Inputs.push_back(Input); CapturedDiagList capturedDiags; 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<ASTUnit> Unit( ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags)); if (!Unit) return true; // 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; } if (emitPremigrationARCErrors) emitPremigrationErrors(capturedDiags, origCI.getDiagnosticOpts(), Unit->getPreprocessor()); if (!plistOut.empty()) { SmallVector<StoredDiagnostic, 8> arcDiags; for (CapturedDiagList::iterator I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I) arcDiags.push_back(*I); writeARCDiagsToPlist(plistOut, arcDiags, Ctx.getSourceManager(), Ctx.getLangOpts()); } // 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()); // No macros will be added since we are just checking and we won't modify // source code. std::vector<SourceLocation> ARCMTMacroLocs; TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, ARCMTMacroLocs); pass.setNSAllocReallocError(NoNSAllocReallocError); pass.setNoFinalizeRemoval(NoFinalizeRemoval); for (unsigned i=0, e = transforms.size(); i != e; ++i) transforms[i](pass); capturedDiags.reportDiagnostics(*Diags); DiagClient->EndSourceFile(); // If we are migrating code that gets the '-fobjc-arc' flag, make sure // to remove it so that we don't get errors from normal compilation. origCI.getLangOpts()->ObjCAutoRefCount = false; return capturedDiags.hasErrors() || testAct.hasReportedErrors(); }
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(); }