Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/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: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -4036,8 +4036,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; + auto Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode()); + Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir); + if (CCGenDiagnostics && A) { + SmallString<128> CrashDirectory; + CrashDirectory = A->getValue(); + llvm::sys::path::append(CrashDirectory, Split.first); + std::error_code EC = + llvm::sys::fs::createUniqueFile(CrashDirectory, 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: clang/test/Driver/crash-diagnostics-dir.c =================================================================== --- /dev/null +++ clang/test/Driver/crash-diagnostics-dir.c @@ -0,0 +1,5 @@ +// 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 Index: llvm/include/llvm/Support/FileSystem.h =================================================================== --- llvm/include/llvm/Support/FileSystem.h +++ llvm/include/llvm/Support/FileSystem.h @@ -755,6 +755,8 @@ SmallVectorImpl &ResultPath, unsigned Mode = all_read | all_write); +std::error_code createUniqueFile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl &ResultPath); /// Represents a temporary file. /// /// The temporary file must be eventually discarded or given a final name and Index: llvm/lib/Support/Path.cpp =================================================================== --- llvm/lib/Support/Path.cpp +++ llvm/lib/Support/Path.cpp @@ -756,13 +756,7 @@ std::error_code createUniqueFile(const Twine &Model, int &ResultFd, SmallVectorImpl &ResultPath, - unsigned Mode) { - return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File); -} - -static std::error_code createUniqueFile(const Twine &Model, int &ResultFd, - SmallVectorImpl &ResultPath, - unsigned Mode, OpenFlags Flags) { + unsigned Mode, sys::fs::OpenFlags Flags) { return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File, Flags); } @@ -779,6 +773,12 @@ return EC; } +std::error_code createUniqueFile(const Twine &Prefix, StringRef Suffix, + llvm::SmallVectorImpl &ResultPath) { + const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%."; + return createUniqueFile(Prefix + Middle + Suffix, ResultPath); +} + static std::error_code createTemporaryFile(const Twine &Model, int &ResultFD, llvm::SmallVectorImpl &ResultPath, FSEntity Type) {