bool ToolInvocation::run() { std::vector<const char*> Argv; for (int I = 0, E = CommandLine.size(); I != E; ++I) Argv.push_back(CommandLine[I].c_str()); const char *const BinaryName = Argv[0]; DiagnosticOptions DefaultDiagnosticOptions; TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), DefaultDiagnosticOptions); DiagnosticsEngine Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>( new DiagnosticIDs()), &DiagnosticPrinter, false); const llvm::OwningPtr<clang::driver::Driver> Driver( newDriver(&Diagnostics, BinaryName)); // Since the input might only be virtual, don't check whether it exists. Driver->setCheckInputsExist(false); const llvm::OwningPtr<clang::driver::Compilation> Compilation( Driver->BuildCompilation(llvm::makeArrayRef(Argv))); const clang::driver::ArgStringList *const CC1Args = getCC1Arguments( &Diagnostics, Compilation.get()); if (CC1Args == NULL) { return false; } llvm::OwningPtr<clang::CompilerInvocation> Invocation( newInvocation(&Diagnostics, *CC1Args)); return runInvocation(BinaryName, Compilation.get(), Invocation.take(), *CC1Args, ToolAction.take()); }
virtual void HandleTranslationUnit(ASTContext &C) { { PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.startTimer(); Gen->HandleTranslationUnit(C); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); } // Silently ignore if we weren't initialized for some reason. if (!TheModule) return; // Make sure IR generation is happy with the module. This is released by // the module provider. Module *M = Gen->ReleaseModule(); if (!M) { // The module has been released by IR gen on failures, do not double // free. TheModule.take(); return; } assert(TheModule.get() == M && "Unexpected module change during IR generation"); // Install an inline asm handler so that diagnostics get printed through // our diagnostics hooks. LLVMContext &Ctx = TheModule->getContext(); LLVMContext::InlineAsmDiagHandlerTy OldHandler = Ctx.getInlineAsmDiagnosticHandler(); void *OldContext = Ctx.getInlineAsmDiagnosticContext(); Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, TheModule.get(), Action, AsmOutStream); Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); }
static clang::CompilerInvocation *newCompilerInvocation(std::string &mainExecutable, std::vector<std::string> &unadjustedCmdLine, bool runClangChecker = false) { // Prepare for command lines, and convert to old-school argv llvm::OwningPtr<clang::tooling::ArgumentsAdjuster> argumentsAdjusterPtr( new clang::tooling::ClangSyntaxOnlyAdjuster()); std::vector<std::string> commandLine = argumentsAdjusterPtr->Adjust(unadjustedCmdLine); assert(!commandLine.empty()); commandLine[0] = mainExecutable; std::vector<const char*> argv; int start = 0, end = commandLine.size(); if (runClangChecker) { argv.push_back(commandLine[0].c_str()); argv.push_back("--analyze"); start = 1; end -= 1; } for (int cmdIndex = start; cmdIndex != end; cmdIndex++) { argv.push_back(commandLine[cmdIndex].c_str()); } // create diagnostic engine llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagOpts = new clang::DiagnosticOptions(); clang::DiagnosticsEngine diagnosticsEngine( llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(new clang::DiagnosticIDs()), &*diagOpts, new clang::DiagnosticConsumer(), false); // create driver const char *const mainBinaryPath = argv[0]; const llvm::OwningPtr<clang::driver::Driver> driver( newDriver(&diagnosticsEngine, mainBinaryPath)); driver->setCheckInputsExist(false); // create compilation invocation const llvm::OwningPtr<clang::driver::Compilation> compilation( driver->BuildCompilation(llvm::makeArrayRef(argv))); const llvm::opt::ArgStringList *const cc1Args = getCC1Arguments(compilation.get()); return newInvocation(&diagnosticsEngine, *cc1Args); }