Author: Alexandre Ganea Date: 2020-02-07T09:51:09-05:00 New Revision: 75f09b54429bee17a96e2ba7a2ac0f0a8a7f7e74
URL: https://github.com/llvm/llvm-project/commit/75f09b54429bee17a96e2ba7a2ac0f0a8a7f7e74 DIFF: https://github.com/llvm/llvm-project/commit/75f09b54429bee17a96e2ba7a2ac0f0a8a7f7e74.diff LOG: Re-land "[Clang][Driver] Remove -M group options ..." and "[Clang] Avoid crashing when generating crash diagnostics when '#pragma clang __debug ..." This re-lands commits f41ec709d9d388dc43469e6ac7f51b6313f7e4af (https://reviews.llvm.org/D74076) and commit 5fedc2b410853a6aef05e8edf19ebfc4e071e28f (https://reviews.llvm.org/D74070) The previous build break was caused by '#pragma clang __debug llvm_unreachable' used in a non-assert build. Move it to a separate test in crash-report-with-asserts.c. Added: clang/test/Driver/crash-report-with-asserts.c Modified: clang/include/clang/Driver/CC1Options.td clang/include/clang/Lex/PreprocessorOptions.h clang/lib/Driver/Compilation.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Lex/Pragma.cpp clang/test/Driver/crash-report.c Removed: ################################################################################ diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 0d0b05f8961c..733a1080be52 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -866,6 +866,8 @@ def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record"> HelpText<"include a detailed record of preprocessing actions">; def setup_static_analyzer : Flag<["-"], "setup-static-analyzer">, HelpText<"Set up preprocessor for static analyzer (done automatically when static analyzer is run).">; +def disable_pragma_debug_crash : Flag<["-"], "disable-pragma-debug-crash">, + HelpText<"Disable any #pragma clang __debug that can lead to crashing behavior. This is meant for testing.">; //===----------------------------------------------------------------------===// // OpenCL Options diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index c281cd51e266..c551f87e0d7b 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -189,6 +189,9 @@ class PreprocessorOptions { /// Set up preprocessor for RunAnalysis action. bool SetUpStaticAnalyzer = false; + /// Prevents intended crashes when using #pragma clang __debug. For testing. + bool DisablePragmaDebugCrash = false; + public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp index 25aec3690f21..52477576b2eb 100644 --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -258,14 +258,23 @@ void Compilation::initCompilationForDiagnostics() { // Remove any user specified output. Claim any unclaimed arguments, so as // to avoid emitting warnings about unused args. - OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD, - options::OPT_MMD }; + OptSpecifier OutputOpts[] = { + options::OPT_o, options::OPT_MD, options::OPT_MMD, options::OPT_M, + options::OPT_MM, options::OPT_MF, options::OPT_MG, options::OPT_MJ, + options::OPT_MQ, options::OPT_MT, options::OPT_MV}; for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) { if (TranslatedArgs->hasArg(OutputOpts[i])) TranslatedArgs->eraseArg(OutputOpts[i]); } TranslatedArgs->ClaimAllArgs(); + // Force re-creation of the toolchain Args, otherwise our modifications just + // above will have no effect. + for (auto Arg : TCArgs) + if (Arg.second != TranslatedArgs) + delete Arg.second; + TCArgs.clear(); + // Redirect stdout/stderr to /dev/null. Redirects = {None, {""}, {""}}; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 65039ac64b5a..9e2279e90b7e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4750,6 +4750,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, : "-"); } + // Give the gen diagnostics more chances to succeed, by avoiding intentional + // crashes. + if (D.CCGenDiagnostics) + CmdArgs.push_back("-disable-pragma-debug-crash"); + bool UseSeparateSections = isUseSeparateSections(Triple); if (Args.hasFlag(options::OPT_ffunction_sections, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d1d9a773f959..17e190627881 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3471,6 +3471,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.LexEditorPlaceholders = false; Opts.SetUpStaticAnalyzer = Args.hasArg(OPT_setup_static_analyzer); + Opts.DisablePragmaDebugCrash = Args.hasArg(OPT_disable_pragma_debug_crash); } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index c881bcac9f38..a8cd18b123b0 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -30,6 +30,7 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorLexer.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/Token.h" #include "clang/Lex/TokenLexer.h" #include "llvm/ADT/ArrayRef.h" @@ -1034,15 +1035,19 @@ struct PragmaDebugHandler : public PragmaHandler { IdentifierInfo *II = Tok.getIdentifierInfo(); if (II->isStr("assert")) { - llvm_unreachable("This is an assertion!"); + if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) + llvm_unreachable("This is an assertion!"); } else if (II->isStr("crash")) { - LLVM_BUILTIN_TRAP; + if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) + LLVM_BUILTIN_TRAP; } else if (II->isStr("parser_crash")) { - Token Crasher; - Crasher.startToken(); - Crasher.setKind(tok::annot_pragma_parser_crash); - Crasher.setAnnotationRange(SourceRange(Tok.getLocation())); - PP.EnterToken(Crasher, /*IsReinject*/false); + if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) { + Token Crasher; + Crasher.startToken(); + Crasher.setKind(tok::annot_pragma_parser_crash); + Crasher.setAnnotationRange(SourceRange(Tok.getLocation())); + PP.EnterToken(Crasher, /*IsReinject*/ false); + } } else if (II->isStr("dump")) { Token Identifier; PP.LexUnexpandedToken(Identifier); @@ -1074,9 +1079,11 @@ struct PragmaDebugHandler : public PragmaHandler { << II->getName(); } } else if (II->isStr("llvm_fatal_error")) { - llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error"); + if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) + llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error"); } else if (II->isStr("llvm_unreachable")) { - llvm_unreachable("#pragma clang __debug llvm_unreachable"); + if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) + llvm_unreachable("#pragma clang __debug llvm_unreachable"); } else if (II->isStr("macro")) { Token MacroName; PP.LexUnexpandedToken(MacroName); @@ -1103,7 +1110,8 @@ struct PragmaDebugHandler : public PragmaHandler { } M->dump(); } else if (II->isStr("overflow_stack")) { - DebugOverflowStack(); + if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) + DebugOverflowStack(); } else if (II->isStr("captured")) { HandleCaptured(PP); } else { diff --git a/clang/test/Driver/crash-report-with-asserts.c b/clang/test/Driver/crash-report-with-asserts.c new file mode 100644 index 000000000000..7a614aa8fe02 --- /dev/null +++ b/clang/test/Driver/crash-report-with-asserts.c @@ -0,0 +1,58 @@ +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: echo '-fsyntax-only \ +// RUN: -F/tmp/ -I /tmp/ -idirafter /tmp/ -iquote /tmp/ -isystem /tmp/ \ +// RUN: -iprefix /the/prefix -iwithprefix /tmp -iwithprefixbefore /tmp/ \ +// RUN: -Xclang -internal-isystem -Xclang /tmp/ \ +// RUN: -Xclang -internal-externc-isystem -Xclang /tmp/ \ +// RUN: -Xclang -main-file-name -Xclang foo.c \ +// RUN: -DFOO=BAR -DBAR="BAZ QUX"' > %t.rsp + +// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ +// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ +// RUN: not %clang %s @%t.rsp -DASSERT 2>&1 | FileCheck %s +// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s +// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s + +// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ +// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ +// RUN: not %clang %s @%t.rsp -DUNREACHABLE 2>&1 | FileCheck %s +// RUN: cat %t/crash-report-with-asserts-*.c | FileCheck --check-prefix=CHECKSRC %s +// RUN: cat %t/crash-report-with-asserts-*.sh | FileCheck --check-prefix=CHECKSH %s + +// REQUIRES: crash-recovery, asserts + +#ifdef ASSERT +#pragma clang __debug assert +#elif UNREACHABLE +#pragma clang __debug llvm_unreachable +#endif + +// CHECK: Preprocessed source(s) and associated run script(s) are located at: +// CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-with-asserts-{{.*}}.c +FOO +// CHECKSRC: FOO +// CHECKSH: # Crash reproducer +// CHECKSH-NEXT: # Driver args: {{.*}}"-fsyntax-only" +// CHECKSH-SAME: "-D" "FOO=BAR" +// CHECKSH-SAME: "-D" "BAR=BAZ QUX" +// CHECKSH-NEXT: # Original command: {{.*$}} +// CHECKSH-NEXT: "-cc1" +// CHECKSH: "-main-file-name" "crash-report-with-asserts.c" +// CHECKSH-NOT: "-header-include-file" +// CHECKSH-NOT: "-diagnostic-log-file" +// CHECKSH: "-D" "FOO=BAR" +// CHECKSH: "-D" "BAR=BAZ QUX" +// CHECKSH-NOT: "-F/tmp/" +// CHECKSH-NOT: "-I" "/tmp/" +// CHECKSH-NOT: "-idirafter" "/tmp/" +// CHECKSH-NOT: "-iquote" "/tmp/" +// CHECKSH-NOT: "-isystem" "/tmp/" +// CHECKSH-NOT: "-iprefix" "/the/prefix" +// CHECKSH-NOT: "-iwithprefix" "/tmp/" +// CHECKSH-NOT: "-iwithprefixbefore" "/tmp/" +// CHECKSH-NOT: "-internal-isystem" "/tmp/" +// CHECKSH-NOT: "-internal-externc-isystem" "/tmp/" +// CHECKSH-NOT: "-dwarf-debug-flags" +// CHECKSH: "crash-report-with-asserts-{{[^ ]*}}.c" diff --git a/clang/test/Driver/crash-report.c b/clang/test/Driver/crash-report.c index 711b04ea4da0..3a77a21c62b4 100644 --- a/clang/test/Driver/crash-report.c +++ b/clang/test/Driver/crash-report.c @@ -1,25 +1,40 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ -// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ -// RUN: not %clang -fsyntax-only %s \ + +// RUN: echo '-fsyntax-only \ // RUN: -F/tmp/ -I /tmp/ -idirafter /tmp/ -iquote /tmp/ -isystem /tmp/ \ // RUN: -iprefix /the/prefix -iwithprefix /tmp -iwithprefixbefore /tmp/ \ // RUN: -Xclang -internal-isystem -Xclang /tmp/ \ // RUN: -Xclang -internal-externc-isystem -Xclang /tmp/ \ // RUN: -Xclang -main-file-name -Xclang foo.c \ -// RUN: -DFOO=BAR -DBAR="BAZ QUX" 2>&1 | FileCheck %s +// RUN: -DFOO=BAR -DBAR="BAZ QUX"' > %t.rsp + +// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ +// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ +// RUN: not %clang %s @%t.rsp -DPARSER 2>&1 | FileCheck %s // RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s // RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s + +// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ +// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ +// RUN: not %clang %s @%t.rsp -DCRASH 2>&1 | FileCheck %s +// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s +// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s + // REQUIRES: crash-recovery +#ifdef PARSER #pragma clang __debug parser_crash +#elif CRASH +#pragma clang __debug crash +#endif + // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-{{.*}}.c FOO // CHECKSRC: FOO // CHECKSH: # Crash reproducer -// CHECKSH-NEXT: # Driver args: "-fsyntax-only" +// CHECKSH-NEXT: # Driver args: {{.*}}"-fsyntax-only" // CHECKSH-SAME: "-D" "FOO=BAR" // CHECKSH-SAME: "-D" "BAR=BAZ QUX" // CHECKSH-NEXT: # Original command: {{.*$}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits