Index: cfe/trunk/include/clang/Driver/Options.td =================================================================== --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/include/clang/Driver/Options.td @@ -798,6 +798,7 @@ Group; def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>, HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">; +def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group, Flags<[NoArgumentUnused]>; def fcreate_profile : Flag<["-"], "fcreate-profile">, Group; def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group, HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>; Index: cfe/trunk/lib/Driver/Driver.cpp =================================================================== --- cfe/trunk/lib/Driver/Driver.cpp +++ cfe/trunk/lib/Driver/Driver.cpp @@ -1291,12 +1291,13 @@ // Assume associated files are based off of the first temporary file. CrashReportInfo CrashInfo(TempFiles[0], VFS); - std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh"; + llvm::SmallString<128> Script(CrashInfo.Filename); + llvm::sys::path::replace_extension(Script, "sh"); std::error_code EC; llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew); if (EC) { Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Error generating run script: " + Script + " " + EC.message(); + << "Error generating run script: " << Script << " " << EC.message(); } else { ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" << "# Driver args: "; @@ -1308,7 +1309,7 @@ ScriptOS << "\n# Additional information: " << AdditionalInformation << "\n"; if (Report) - Report->TemporaryFiles.push_back(Script); + Report->TemporaryFiles.push_back(Script.str()); Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; } @@ -4018,8 +4019,22 @@ CCGenDiagnostics) { StringRef Name = llvm::sys::path::filename(BaseInput); std::pair Split = Name.split('.'); - std::string TmpName = GetTemporaryPath( - Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode())); + SmallString<128> TmpName; + const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode()); + Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir); + if (CCGenDiagnostics && A) { + SmallString<128> CrashDirectory(A->getValue()); + llvm::sys::path::append(CrashDirectory, Split.first); + const char *Middle = Suffix ? "-%%%%%%." : "-%%%%%%"; + std::error_code EC = + llvm::sys::fs::createUniqueFile(CrashDirectory + Middle + Suffix, TmpName); + if (EC) { + Diag(clang::diag::err_unable_to_make_temp) << EC.message(); + return ""; + } + } else { + TmpName = GetTemporaryPath(Split.first, Suffix); + } return C.addTempFile(C.getArgs().MakeArgString(TmpName)); } Index: cfe/trunk/test/Driver/crash-diagnostics-dir.c =================================================================== --- cfe/trunk/test/Driver/crash-diagnostics-dir.c +++ cfe/trunk/test/Driver/crash-diagnostics-dir.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: not %clang -fcrash-diagnostics-dir=%t -c %s 2>&1 | FileCheck %s +#pragma clang __debug parser_crash +// CHECK: Preprocessed source(s) and associated run script(s) are located at: +// CHECK: diagnostic msg: {{.*}}Output{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c