diff options
Diffstat (limited to 'lib/Driver/Driver.cpp')
-rw-r--r-- | lib/Driver/Driver.cpp | 189 |
1 files changed, 147 insertions, 42 deletions
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 3ddac69..87d533d 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -59,7 +59,7 @@ Driver::Driver(StringRef ClangExecutable, CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), CCCUseClang(true), CCCUseClangCXX(true), CCCUseClangCPP(true), - CCCUsePCH(true), SuppressMissingInputWarning(false) { + ForcedClangUse(false), CCCUsePCH(true), SuppressMissingInputWarning(false) { if (IsProduction) { // In a "production" build, only use clang on architectures we expect to // work. @@ -115,9 +115,10 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { } // Warn about -mcpu= without an argument. - if (A->getOption().matches(options::OPT_mcpu_EQ) && + if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) { - Diag(clang::diag::warn_drv_empty_joined_argument) << A->getAsString(*Args); + Diag(clang::diag::warn_drv_empty_joined_argument) << + A->getAsString(*Args); } } @@ -253,7 +254,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { if (char *env = ::getenv("COMPILER_PATH")) { StringRef CompilerPath = env; while (!CompilerPath.empty()) { - std::pair<StringRef, StringRef> Split = CompilerPath.split(':'); + std::pair<StringRef, StringRef> Split = CompilerPath.split(':'); PrefixDirs.push_back(Split.first); CompilerPath = Split.second; } @@ -376,24 +377,33 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { void Driver::generateCompilationDiagnostics(Compilation &C, const Command *FailingCommand) { if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) - return; + return; // Don't try to generate diagnostics for link jobs. - if (FailingCommand->getCreator().isLinkJob()) + if (FailingCommand && FailingCommand->getCreator().isLinkJob()) return; + // Print the version of the compiler. + PrintVersion(C, llvm::errs()); + Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Please submit a bug report to " BUG_REPORT_URL " and include command" - " line arguments and all diagnostic information."; + << "PLEASE submit a bug report to " BUG_REPORT_URL " and include the " + "crash backtrace, preprocessed source, and associated run script."; // Suppress driver output and emit preprocessor output to temp file. CCCIsCPP = true; CCGenDiagnostics = true; + C.getArgs().AddFlagArg(0, Opts->getOption(options::OPT_frewrite_includes)); // Save the original job command(s). std::string Cmd; llvm::raw_string_ostream OS(Cmd); - C.PrintJob(OS, C.getJobs(), "\n", false); + if (FailingCommand) + C.PrintJob(OS, *FailingCommand, "\n", false); + else + // Crash triggered by FORCE_CLANG_DIAGNOSTICS_CRASH, which doesn't have an + // associated FailingCommand, so just pass all jobs. + C.PrintJob(OS, C.getJobs(), "\n", false); OS.flush(); // Clear stale state and suppress tool output. @@ -473,7 +483,9 @@ void Driver::generateCompilationDiagnostics(Compilation &C, // If the command succeeded, we are done. if (Res == 0) { Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Preprocessed source(s) and associated run script(s) are located at:"; + << "\n********************\n\n" + "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n" + "Preprocessed source(s) and associated run script(s) are located at:"; ArgStringList Files = C.getTempFiles(); for (ArgStringList::const_iterator it = Files.begin(), ie = Files.end(); it != ie; ++it) { @@ -489,10 +501,76 @@ void Driver::generateCompilationDiagnostics(Compilation &C, Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + Err; } else { + // Strip away options not necessary to reproduce the crash. + // FIXME: This doesn't work with quotes (e.g., -D "foo bar"). + SmallVector<std::string, 16> Flag; + Flag.push_back("-D "); + Flag.push_back("-F"); + Flag.push_back("-I "); + Flag.push_back("-M "); + Flag.push_back("-MD "); + Flag.push_back("-MF "); + Flag.push_back("-MG "); + Flag.push_back("-MM "); + Flag.push_back("-MMD "); + Flag.push_back("-MP "); + Flag.push_back("-MQ "); + Flag.push_back("-MT "); + Flag.push_back("-o "); + Flag.push_back("-coverage-file "); + Flag.push_back("-dependency-file "); + Flag.push_back("-fdebug-compilation-dir "); + Flag.push_back("-fmodule-cache-path "); + Flag.push_back("-idirafter "); + Flag.push_back("-include "); + Flag.push_back("-include-pch "); + Flag.push_back("-internal-isystem "); + Flag.push_back("-internal-externc-isystem "); + Flag.push_back("-iprefix "); + Flag.push_back("-iwithprefix "); + Flag.push_back("-iwithprefixbefore "); + Flag.push_back("-isysroot "); + Flag.push_back("-isystem "); + Flag.push_back("-iquote "); + Flag.push_back("-resource-dir "); + Flag.push_back("-serialize-diagnostic-file "); + for (unsigned i = 0, e = Flag.size(); i < e; ++i) { + size_t I = 0, E = 0; + do { + I = Cmd.find(Flag[i], I); + if (I == std::string::npos) break; + + E = Cmd.find(" ", I + Flag[i].length()); + if (E == std::string::npos) break; + // The -D option is not removed. Instead, the argument is quoted. + if (Flag[i] != "-D ") { + Cmd.erase(I, E - I + 1); + } else { + Cmd.insert(I+3, "\""); + Cmd.insert(++E, "\""); + I = E; + } + } while(1); + } + // Append the new filename with correct preprocessed suffix. + size_t I, E; + I = Cmd.find("-main-file-name "); + assert (I != std::string::npos && "Expected to find -main-file-name"); + I += 16; + E = Cmd.find(" ", I); + assert (E != std::string::npos && "-main-file-name missing argument?"); + StringRef OldFilename = StringRef(Cmd).slice(I, E); + StringRef NewFilename = llvm::sys::path::filename(*it); + I = StringRef(Cmd).rfind(OldFilename); + E = I + OldFilename.size(); + I = Cmd.rfind(" ", I) + 1; + Cmd.replace(I, E - I, NewFilename.data(), NewFilename.size()); ScriptOS << Cmd; Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; } } + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "\n\n********************"; } else { // Failure, remove preprocessed files. if (!C.getArgs().hasArg(options::OPT_save_temps)) @@ -529,14 +607,8 @@ int Driver::ExecuteCompilation(const Compilation &C, C.CleanupFileList(C.getResultFiles(), true); // Failure result files are valid unless we crashed. - if (Res < 0) { + if (Res < 0) C.CleanupFileList(C.getFailureResultFiles(), true); -#ifdef _WIN32 - // Exit status should not be negative on Win32, - // unless abnormal termination. - Res = 1; -#endif - } } // Print extra information about abnormal failures, if possible. @@ -630,7 +702,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { return false; } - if (C.getArgs().hasArg(options::OPT__help) || + if (C.getArgs().hasArg(options::OPT_help) || C.getArgs().hasArg(options::OPT__help_hidden)) { PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden)); return false; @@ -748,8 +820,7 @@ static unsigned PrintActions1(const Compilation &C, Action *A, if (InputAction *IA = dyn_cast<InputAction>(A)) { os << "\"" << IA->getInputArg().getValue(C.getArgs()) << "\""; } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) { - os << '"' << (BIA->getArchName() ? BIA->getArchName() : - C.getDefaultToolChain().getArchName()) << '"' + os << '"' << BIA->getArchName() << '"' << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}"; } else { os << "{"; @@ -823,7 +894,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, // When there is no explicit arch for this platform, make sure we still bind // the architecture (to the default) so that -Xarch_ is handled correctly. if (!Archs.size()) - Archs.push_back(0); + Archs.push_back(Args.MakeArgString(TC.getArchName())); // FIXME: We killed off some others but these aren't yet detected in a // functional manner. If we added information to jobs about which "auxiliary" @@ -873,7 +944,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, if (A && !A->getOption().matches(options::OPT_g0) && !A->getOption().matches(options::OPT_gstabs) && ContainsCompileOrAssembleAction(Actions.back())) { - + // Add a 'dsymutil' step if necessary, when debug info is enabled and we // have a compile input. We need to run 'dsymutil' ourselves in such cases // because the debug info will refer to a temporary object file which is @@ -1060,18 +1131,27 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, if (Args.hasArg(options::OPT_Qunused_arguments)) continue; + // Special case when final phase determined by binary name, rather than + // by a command-line argument with a corresponding Arg. + if (CCCIsCPP) + Diag(clang::diag::warn_drv_input_file_unused_by_cpp) + << InputArg->getAsString(Args) + << getPhaseName(InitialPhase); // Special case '-E' warning on a previously preprocessed file to make // more sense. - if (InitialPhase == phases::Compile && FinalPhase == phases::Preprocess && - getPreprocessedType(InputType) == types::TY_INVALID) + else if (InitialPhase == phases::Compile && + FinalPhase == phases::Preprocess && + getPreprocessedType(InputType) == types::TY_INVALID) Diag(clang::diag::warn_drv_preprocessed_input_file_unused) << InputArg->getAsString(Args) - << FinalPhaseArg->getOption().getName(); + << !!FinalPhaseArg + << FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""; else Diag(clang::diag::warn_drv_input_file_unused) << InputArg->getAsString(Args) << getPhaseName(InitialPhase) - << FinalPhaseArg->getOption().getName(); + << !!FinalPhaseArg + << FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""; continue; } @@ -1130,14 +1210,23 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, if (Args.hasArg(options::OPT_M, options::OPT_MM)) { OutputTy = types::TY_Dependencies; } else { - OutputTy = types::getPreprocessedType(Input->getType()); + OutputTy = Input->getType(); + if (!Args.hasFlag(options::OPT_frewrite_includes, + options::OPT_fno_rewrite_includes, false)) + OutputTy = types::getPreprocessedType(OutputTy); assert(OutputTy != types::TY_INVALID && "Cannot preprocess this input type!"); } return new PreprocessJobAction(Input, OutputTy); } - case phases::Precompile: - return new PrecompileJobAction(Input, types::TY_PCH); + case phases::Precompile: { + types::ID OutputTy = types::TY_PCH; + if (Args.hasArg(options::OPT_fsyntax_only)) { + // Syntax checks should not emit a PCH file + OutputTy = types::TY_Nothing; + } + return new PrecompileJobAction(Input, OutputTy); + } case phases::Compile: { if (Args.hasArg(options::OPT_fsyntax_only)) { return new CompileJobAction(Input, types::TY_Nothing); @@ -1332,10 +1421,13 @@ void Driver::BuildJobsForAction(Compilation &C, } if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { - const ToolChain *TC = &C.getDefaultToolChain(); + const ToolChain *TC; + const char *ArchName = BAA->getArchName(); - if (BAA->getArchName()) - TC = &getToolChain(C.getArgs(), BAA->getArchName()); + if (ArchName) + TC = &getToolChain(C.getArgs(), ArchName); + else + TC = &C.getDefaultToolChain(); BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(), AtTopLevel, LinkingOutput, Result); @@ -1453,15 +1545,24 @@ const char *Driver::GetNamedOutputPath(Compilation &C, NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str()); } - // If we're saving temps and the temp filename conflicts with the input - // filename, then avoid overwriting input file. + // If we're saving temps and the temp file conflicts with the input file, + // then avoid overwriting input file. if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) && NamedOutput == BaseName) { - StringRef Name = llvm::sys::path::filename(BaseInput); - std::pair<StringRef, StringRef> Split = Name.split('.'); - std::string TmpName = - GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType())); - return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); + + bool SameFile = false; + SmallString<256> Result; + llvm::sys::fs::current_path(Result); + llvm::sys::path::append(Result, BaseName); + llvm::sys::fs::equivalent(BaseInput, Result.c_str(), SameFile); + // Must share the same path to conflict. + if (SameFile) { + StringRef Name = llvm::sys::path::filename(BaseInput); + std::pair<StringRef, StringRef> Split = Name.split('.'); + std::string TmpName = + GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType())); + return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); + } } // As an annoying special case, PCH generation doesn't strip the pathname. @@ -1564,7 +1665,7 @@ std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC, return Name; } -std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) +std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) const { // FIXME: This is lame; sys::Path should provide this function (in particular, // it should know how to find the temporary files dir). @@ -1579,14 +1680,15 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) llvm::sys::Path P(TmpDir); P.appendComponent(Prefix); if (P.makeUnique(false, &Error)) { - Diag(clang::diag::err_drv_unable_to_make_temp) << Error; + Diag(clang::diag::err_unable_to_make_temp) << Error; return ""; } // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837. P.eraseFromDisk(false, 0); - P.appendSuffix(Suffix); + if (Suffix) + P.appendSuffix(Suffix); return P.str(); } @@ -1674,6 +1776,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::OpenBSD: TC = new toolchains::OpenBSD(*this, Target, Args); break; + case llvm::Triple::Bitrig: + TC = new toolchains::Bitrig(*this, Target, Args); + break; case llvm::Triple::NetBSD: TC = new toolchains::NetBSD(*this, Target, Args); break; |