Index: cfe/trunk/docs/UsersManual.rst =================================================================== --- cfe/trunk/docs/UsersManual.rst +++ cfe/trunk/docs/UsersManual.rst @@ -562,6 +562,16 @@ The -fno-crash-diagnostics flag can be helpful for speeding the process of generating a delta reduced test case. +Clang is also capable of generating preprocessed source file(s) and associated +run script(s) even without a crash. This is specially useful when trying to +generate a reproducer for warnings or errors while using modules. + +.. option:: -gen-reproducer + + Generates preprocessed source files, a reproducer script and if relevant, a + cache containing: built module pcm's and all headers needed to rebuilt the + same modules. + .. _rpass: Options to Emit Optimization Reports Index: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td @@ -94,7 +94,7 @@ def err_drv_command_signalled : Error< "%0 command failed due to signal (use -v to see invocation)">; def err_drv_force_crash : Error< - "failing because environment variable '%0' is set">; + "failing because %select{environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set|'-gen-reproducer' is used}0">; def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; def err_drv_invalid_libcxx_deployment : Error< Index: cfe/trunk/include/clang/Driver/Driver.h =================================================================== --- cfe/trunk/include/clang/Driver/Driver.h +++ cfe/trunk/include/clang/Driver/Driver.h @@ -216,6 +216,11 @@ /// Use lazy precompiled headers for PCH support. unsigned CCCUsePCH : 1; + /// Force clang to emit reproducer for driver invocation. This is enabled + /// indirectly by setting FORCE_CLANG_DIAGNOSTICS_CRASH environment variable + /// or when using the -gen-reproducer driver flag. + unsigned GenReproducer : 1; + private: /// Certain options suppress the 'no input files' warning. unsigned SuppressMissingInputWarning : 1; Index: cfe/trunk/include/clang/Driver/Options.td =================================================================== --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/include/clang/Driver/Options.td @@ -265,6 +265,8 @@ def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">, HelpText<"Emit ARC errors even if the migrator can fix them">, Flags<[CC1Option]>; +def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt, + HelpText<"Auto-generates preprocessed source files and a reproduction script">; def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>, HelpText<"Run the migrator">; @@ -701,7 +703,8 @@ def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group; def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">, Group; -def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>; +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 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 @@ -91,7 +91,7 @@ CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), DefaultTargetTriple(DefaultTargetTriple), CCCGenericGCCName(""), CheckInputsExist(true), CCCUsePCH(true), - SuppressMissingInputWarning(false) { + GenReproducer(false), SuppressMissingInputWarning(false) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) @@ -620,6 +620,9 @@ CCCGenericGCCName = A->getValue(); CCCUsePCH = Args.hasFlag(options::OPT_ccc_pch_is_pch, options::OPT_ccc_pch_is_pth); + GenReproducer = Args.hasFlag(options::OPT_gen_reproducer, + options::OPT_fno_crash_diagnostics, + !!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")); // FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld // and getToolChain is const. if (IsCLMode()) { Index: cfe/trunk/test/Driver/crash-report-crashfile.m =================================================================== --- cfe/trunk/test/Driver/crash-report-crashfile.m +++ cfe/trunk/test/Driver/crash-report-crashfile.m @@ -3,15 +3,32 @@ // RUN: mkdir -p %t/i %t/m %t // RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ -// RUN: %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \ -// RUN: -fmodules -fmodules-cache-path=%t/m/ -DFOO=BAR 2>&1 | FileCheck %s +// RUN: %clang -fsyntax-only %s \ +// RUN: -I %S/Inputs/module -isysroot %/t/i/ \ +// RUN: -fmodules -fmodules-cache-path=%t/m/ -DFOO=BAR 2>&1 | \ +// RUN: FileCheck -check-prefix=CRASH_ENV %s + +// RUN: not env TMPDIR=%t TEMP=%t TMP=%t \ +// RUN: %clang -gen-reproducer -fsyntax-only %s \ +// RUN: -I %S/Inputs/module -isysroot %/t/i/ \ +// RUN: -fmodules -fmodules-cache-path=%t/m/ -DFOO=BAR 2>&1 | \ +// RUN: FileCheck -check-prefix=CRASH_FLAG %s @import simple; const int x = MODULE_MACRO; -// CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache -// CHECK-NEXT: note: diagnostic msg: {{.*}}.sh -// CHECK-NEXT: note: diagnostic msg: Crash backtrace is located in -// CHECK-NEXT: note: diagnostic msg: {{.*}}Library/Logs/DiagnosticReports{{.*}} +// CRASH_ENV: failing because environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set +// CRASH_ENV: Preprocessed source(s) and associated run script(s) are located at: +// CRASH_ENV-NEXT: note: diagnostic msg: {{.*}}.m +// CRASH_ENV-NEXT: note: diagnostic msg: {{.*}}.cache +// CRASH_ENV-NEXT: note: diagnostic msg: {{.*}}.sh +// CRASH_ENV-NEXT: note: diagnostic msg: Crash backtrace is located in +// CRASH_ENV-NEXT: note: diagnostic msg: {{.*}}Library/Logs/DiagnosticReports{{.*}} + +// CRASH_FLAG: failing because '-gen-reproducer' is used +// CRASH_FLAG: Preprocessed source(s) and associated run script(s) are located at: +// CRASH_FLAG-NEXT: note: diagnostic msg: {{.*}}.m +// CRASH_FLAG-NEXT: note: diagnostic msg: {{.*}}.cache +// CRASH_FLAG-NEXT: note: diagnostic msg: {{.*}}.sh +// CRASH_FLAG-NEXT: note: diagnostic msg: Crash backtrace is located in +// CRASH_FLAG-NEXT: note: diagnostic msg: {{.*}}Library/Logs/DiagnosticReports{{.*}} Index: cfe/trunk/tools/driver/driver.cpp =================================================================== --- cfe/trunk/tools/driver/driver.cpp +++ cfe/trunk/tools/driver/driver.cpp @@ -460,8 +460,9 @@ Res = TheDriver.ExecuteCompilation(*C, FailingCommands); // Force a crash to test the diagnostics. - if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) { - Diags.Report(diag::err_drv_force_crash) << "FORCE_CLANG_DIAGNOSTICS_CRASH"; + if (TheDriver.GenReproducer) { + Diags.Report(diag::err_drv_force_crash) + << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"); // Pretend that every command failed. FailingCommands.clear();