int Driver::ExecuteCompilation(const Compilation &C) const { // Just print if -### was present. if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { C.PrintJob(llvm::errs(), C.getJobs(), "\n", true); return 0; } // If there were errors building the compilation, quit now. if (getDiags().getNumErrors()) return 1; const Command *FailingCommand = 0; int Res = C.ExecuteJob(C.getJobs(), FailingCommand); // Remove temp files. C.CleanupFileList(C.getTempFiles()); // If the compilation failed, remove result files as well. if (Res != 0 && !C.getArgs().hasArg(options::OPT_save_temps)) C.CleanupFileList(C.getResultFiles(), true); // Print extra information about abnormal failures, if possible. if (Res) { // This is ad-hoc, but we don't want to be excessively noisy. If the result // status was 1, assume the command failed normally. In particular, if it // was the compiler then assume it gave a reasonable error code. Failures in // other tools are less common, and they generally have worse diagnostics, // so always print the diagnostic there. const Action &Source = FailingCommand->getSource(); bool IsFriendlyTool = (isa<PreprocessJobAction>(Source) || isa<PrecompileJobAction>(Source) || isa<AnalyzeJobAction>(Source) || isa<CompileJobAction>(Source)); if (!IsFriendlyTool || Res != 1) { // FIXME: See FIXME above regarding result code interpretation. if (Res < 0) Diag(clang::diag::err_drv_command_signalled) << Source.getClassName() << -Res; else Diag(clang::diag::err_drv_command_failed) << Source.getClassName() << Res; } } return Res; }
static void ExecuteTemplightJobs(Driver &TheDriver, DiagnosticsEngine &Diags, Compilation &C, Job &J, const char* Argv0, SmallVector<std::pair<int, const Command *>, 4>& FailingCommands) { if (JobList *jobs = dyn_cast<JobList>(&J)) { for (JobList::iterator it = jobs->begin(), it_end = jobs->end(); it != it_end; ++it) ExecuteTemplightJobs(TheDriver, Diags, C, *it, Argv0, FailingCommands); return; } Command *command = dyn_cast<Command>(&J); // Since argumentsFitWithinSystemLimits() may underestimate system's capacity // if the tool does not support response files, there is a chance/ that things // will just work without a response file, so we silently just skip it. if ( command && command->getCreator().getResponseFilesSupport() != Tool::RF_None && llvm::sys::argumentsFitWithinSystemLimits(command->getArguments()) ) { std::string TmpName = TheDriver.GetTemporaryPath("response", "txt"); command->setResponseFile(C.addTempFile(C.getArgs().MakeArgString( TmpName.c_str()))); } if ( command && (StringRef(command->getCreator().getName()) == "clang") ) { // Initialize a compiler invocation object from the clang (-cc1) arguments. const ArgStringList &cc_arguments = command->getArguments(); const char** args_start = const_cast<const char**>(cc_arguments.data()); const char** args_end = args_start + cc_arguments.size(); std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); int Res = !CompilerInvocation::CreateFromArgs( Clang->getInvocation(), args_start, args_end, Diags); if(Res) FailingCommands.push_back(std::make_pair(Res, command)); Clang->getFrontendOpts().DisableFree = false; // Infer the builtin include path if unspecified. void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath; if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && Clang->getHeaderSearchOpts().ResourceDir.empty()) Clang->getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(Argv0, GetExecutablePathVP); // Create the compilers actual diagnostics engine. Clang->createDiagnostics(); if (!Clang->hasDiagnostics()) { FailingCommands.push_back(std::make_pair(1, command)); return; } LocalOutputFilename = ""; // Let the filename be created from options or output file name. std::string TemplightOutFile = TemplightAction::CreateOutputFilename( Clang.get(), "", InstProfiler, OutputToStdOut, MemoryProfile); // Check if templight filename is in a temporary path: llvm::SmallString<128> TDir; llvm::sys::path::system_temp_directory(true, TDir); if ( TDir.equals(llvm::sys::path::parent_path(llvm::StringRef(TemplightOutFile))) ) { C.addTempFile(TemplightOutFile.c_str()); TempOutputFiles.push_back(TemplightOutFile); } // Execute the frontend actions. Res = ExecuteTemplightInvocation(Clang.get()); if(Res) FailingCommands.push_back(std::make_pair(Res, command)); } else { C.ExecuteJob(J, FailingCommands); } }