Skip to content

Commit 0e1c734

Browse files
aganeazmodem
authored andcommitted
Re-land "[Clang][Driver] Remove -M group options ..." and "[Clang] Avoid crashing when generating crash diagnostics when '#pragma clang __debug ..."
This re-lands commits f41ec70 (https://reviews.llvm.org/D74076) and commit 5fedc2b (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. (cherry picked from commit 75f09b5)
1 parent 4759c6e commit 0e1c734

File tree

8 files changed

+118
-17
lines changed

8 files changed

+118
-17
lines changed

clang/include/clang/Driver/CC1Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,8 @@ def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">
859859
HelpText<"include a detailed record of preprocessing actions">;
860860
def setup_static_analyzer : Flag<["-"], "setup-static-analyzer">,
861861
HelpText<"Set up preprocessor for static analyzer (done automatically when static analyzer is run).">;
862+
def disable_pragma_debug_crash : Flag<["-"], "disable-pragma-debug-crash">,
863+
HelpText<"Disable any #pragma clang __debug that can lead to crashing behavior. This is meant for testing.">;
862864

863865
//===----------------------------------------------------------------------===//
864866
// OpenCL Options

clang/include/clang/Lex/PreprocessorOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ class PreprocessorOptions {
189189
/// Set up preprocessor for RunAnalysis action.
190190
bool SetUpStaticAnalyzer = false;
191191

192+
/// Prevents intended crashes when using #pragma clang __debug. For testing.
193+
bool DisablePragmaDebugCrash = false;
194+
192195
public:
193196
PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {}
194197

clang/lib/Driver/Compilation.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,23 @@ void Compilation::initCompilationForDiagnostics() {
258258

259259
// Remove any user specified output. Claim any unclaimed arguments, so as
260260
// to avoid emitting warnings about unused args.
261-
OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
262-
options::OPT_MMD };
261+
OptSpecifier OutputOpts[] = {
262+
options::OPT_o, options::OPT_MD, options::OPT_MMD, options::OPT_M,
263+
options::OPT_MM, options::OPT_MF, options::OPT_MG, options::OPT_MJ,
264+
options::OPT_MQ, options::OPT_MT, options::OPT_MV};
263265
for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
264266
if (TranslatedArgs->hasArg(OutputOpts[i]))
265267
TranslatedArgs->eraseArg(OutputOpts[i]);
266268
}
267269
TranslatedArgs->ClaimAllArgs();
268270

271+
// Force re-creation of the toolchain Args, otherwise our modifications just
272+
// above will have no effect.
273+
for (auto Arg : TCArgs)
274+
if (Arg.second != TranslatedArgs)
275+
delete Arg.second;
276+
TCArgs.clear();
277+
269278
// Redirect stdout/stderr to /dev/null.
270279
Redirects = {None, {""}, {""}};
271280

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4679,6 +4679,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
46794679
: "-");
46804680
}
46814681

4682+
// Give the gen diagnostics more chances to succeed, by avoiding intentional
4683+
// crashes.
4684+
if (D.CCGenDiagnostics)
4685+
CmdArgs.push_back("-disable-pragma-debug-crash");
4686+
46824687
bool UseSeparateSections = isUseSeparateSections(Triple);
46834688

46844689
if (Args.hasFlag(options::OPT_ffunction_sections,

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3440,6 +3440,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
34403440
Opts.LexEditorPlaceholders = false;
34413441

34423442
Opts.SetUpStaticAnalyzer = Args.hasArg(OPT_setup_static_analyzer);
3443+
Opts.DisablePragmaDebugCrash = Args.hasArg(OPT_disable_pragma_debug_crash);
34433444
}
34443445

34453446
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,

clang/lib/Lex/Pragma.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "clang/Lex/PPCallbacks.h"
3131
#include "clang/Lex/Preprocessor.h"
3232
#include "clang/Lex/PreprocessorLexer.h"
33+
#include "clang/Lex/PreprocessorOptions.h"
3334
#include "clang/Lex/Token.h"
3435
#include "clang/Lex/TokenLexer.h"
3536
#include "llvm/ADT/ArrayRef.h"
@@ -1034,15 +1035,19 @@ struct PragmaDebugHandler : public PragmaHandler {
10341035
IdentifierInfo *II = Tok.getIdentifierInfo();
10351036

10361037
if (II->isStr("assert")) {
1037-
llvm_unreachable("This is an assertion!");
1038+
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
1039+
llvm_unreachable("This is an assertion!");
10381040
} else if (II->isStr("crash")) {
1039-
LLVM_BUILTIN_TRAP;
1041+
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
1042+
LLVM_BUILTIN_TRAP;
10401043
} else if (II->isStr("parser_crash")) {
1041-
Token Crasher;
1042-
Crasher.startToken();
1043-
Crasher.setKind(tok::annot_pragma_parser_crash);
1044-
Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
1045-
PP.EnterToken(Crasher, /*IsReinject*/false);
1044+
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) {
1045+
Token Crasher;
1046+
Crasher.startToken();
1047+
Crasher.setKind(tok::annot_pragma_parser_crash);
1048+
Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
1049+
PP.EnterToken(Crasher, /*IsReinject*/ false);
1050+
}
10461051
} else if (II->isStr("dump")) {
10471052
Token Identifier;
10481053
PP.LexUnexpandedToken(Identifier);
@@ -1074,9 +1079,11 @@ struct PragmaDebugHandler : public PragmaHandler {
10741079
<< II->getName();
10751080
}
10761081
} else if (II->isStr("llvm_fatal_error")) {
1077-
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
1082+
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
1083+
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
10781084
} else if (II->isStr("llvm_unreachable")) {
1079-
llvm_unreachable("#pragma clang __debug llvm_unreachable");
1085+
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
1086+
llvm_unreachable("#pragma clang __debug llvm_unreachable");
10801087
} else if (II->isStr("macro")) {
10811088
Token MacroName;
10821089
PP.LexUnexpandedToken(MacroName);
@@ -1103,7 +1110,8 @@ struct PragmaDebugHandler : public PragmaHandler {
11031110
}
11041111
M->dump();
11051112
} else if (II->isStr("overflow_stack")) {
1106-
DebugOverflowStack();
1113+
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
1114+
DebugOverflowStack();
11071115
} else if (II->isStr("captured")) {
11081116
HandleCaptured(PP);
11091117
} else {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir %t
3+
4+
// RUN: echo '-fsyntax-only \
5+
// RUN: -F/tmp/ -I /tmp/ -idirafter /tmp/ -iquote /tmp/ -isystem /tmp/ \
6+
// RUN: -iprefix /the/prefix -iwithprefix /tmp -iwithprefixbefore /tmp/ \
7+
// RUN: -Xclang -internal-isystem -Xclang /tmp/ \
8+
// RUN: -Xclang -internal-externc-isystem -Xclang /tmp/ \
9+
// RUN: -Xclang -main-file-name -Xclang foo.c \
10+
// RUN: -DFOO=BAR -DBAR="BAZ QUX"' > %t.rsp
11+
12+
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
13+
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
14+
// RUN: not %clang %s @%t.rsp -DASSERT 2>&1 | FileCheck %s
15+
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
16+
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
17+
18+
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
19+
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
20+
// RUN: not %clang %s @%t.rsp -DUNREACHABLE 2>&1 | FileCheck %s
21+
// RUN: cat %t/crash-report-with-asserts-*.c | FileCheck --check-prefix=CHECKSRC %s
22+
// RUN: cat %t/crash-report-with-asserts-*.sh | FileCheck --check-prefix=CHECKSH %s
23+
24+
// REQUIRES: crash-recovery, asserts
25+
26+
#ifdef ASSERT
27+
#pragma clang __debug assert
28+
#elif UNREACHABLE
29+
#pragma clang __debug llvm_unreachable
30+
#endif
31+
32+
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
33+
// CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-with-asserts-{{.*}}.c
34+
FOO
35+
// CHECKSRC: FOO
36+
// CHECKSH: # Crash reproducer
37+
// CHECKSH-NEXT: # Driver args: {{.*}}"-fsyntax-only"
38+
// CHECKSH-SAME: "-D" "FOO=BAR"
39+
// CHECKSH-SAME: "-D" "BAR=BAZ QUX"
40+
// CHECKSH-NEXT: # Original command: {{.*$}}
41+
// CHECKSH-NEXT: "-cc1"
42+
// CHECKSH: "-main-file-name" "crash-report-with-asserts.c"
43+
// CHECKSH-NOT: "-header-include-file"
44+
// CHECKSH-NOT: "-diagnostic-log-file"
45+
// CHECKSH: "-D" "FOO=BAR"
46+
// CHECKSH: "-D" "BAR=BAZ QUX"
47+
// CHECKSH-NOT: "-F/tmp/"
48+
// CHECKSH-NOT: "-I" "/tmp/"
49+
// CHECKSH-NOT: "-idirafter" "/tmp/"
50+
// CHECKSH-NOT: "-iquote" "/tmp/"
51+
// CHECKSH-NOT: "-isystem" "/tmp/"
52+
// CHECKSH-NOT: "-iprefix" "/the/prefix"
53+
// CHECKSH-NOT: "-iwithprefix" "/tmp/"
54+
// CHECKSH-NOT: "-iwithprefixbefore" "/tmp/"
55+
// CHECKSH-NOT: "-internal-isystem" "/tmp/"
56+
// CHECKSH-NOT: "-internal-externc-isystem" "/tmp/"
57+
// CHECKSH-NOT: "-dwarf-debug-flags"
58+
// CHECKSH: "crash-report-with-asserts-{{[^ ]*}}.c"

clang/test/Driver/crash-report.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,40 @@
11
// RUN: rm -rf %t
22
// RUN: mkdir %t
3-
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
4-
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
5-
// RUN: not %clang -fsyntax-only %s \
3+
4+
// RUN: echo '-fsyntax-only \
65
// RUN: -F/tmp/ -I /tmp/ -idirafter /tmp/ -iquote /tmp/ -isystem /tmp/ \
76
// RUN: -iprefix /the/prefix -iwithprefix /tmp -iwithprefixbefore /tmp/ \
87
// RUN: -Xclang -internal-isystem -Xclang /tmp/ \
98
// RUN: -Xclang -internal-externc-isystem -Xclang /tmp/ \
109
// RUN: -Xclang -main-file-name -Xclang foo.c \
11-
// RUN: -DFOO=BAR -DBAR="BAZ QUX" 2>&1 | FileCheck %s
10+
// RUN: -DFOO=BAR -DBAR="BAZ QUX"' > %t.rsp
11+
12+
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
13+
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
14+
// RUN: not %clang %s @%t.rsp -DPARSER 2>&1 | FileCheck %s
1215
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
1316
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
17+
18+
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
19+
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
20+
// RUN: not %clang %s @%t.rsp -DCRASH 2>&1 | FileCheck %s
21+
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
22+
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
23+
1424
// REQUIRES: crash-recovery
1525

26+
#ifdef PARSER
1627
#pragma clang __debug parser_crash
28+
#elif CRASH
29+
#pragma clang __debug crash
30+
#endif
31+
1732
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
1833
// CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-{{.*}}.c
1934
FOO
2035
// CHECKSRC: FOO
2136
// CHECKSH: # Crash reproducer
22-
// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
37+
// CHECKSH-NEXT: # Driver args: {{.*}}"-fsyntax-only"
2338
// CHECKSH-SAME: "-D" "FOO=BAR"
2439
// CHECKSH-SAME: "-D" "BAR=BAZ QUX"
2540
// CHECKSH-NEXT: # Original command: {{.*$}}

0 commit comments

Comments
 (0)