[clang] [WIP][DO NOT MERGE][Clang][Driver] Emit warning when -fsanitize-trap=<...> is passed without associated -fsanitize=<...> (PR #147997)
Anthony Tran via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 14 04:54:50 PDT 2025
https://github.com/anthonyhatran updated https://github.com/llvm/llvm-project/pull/147997
>From eadf3e52072fbae01e8de8f7f59883aec1b2c9bc Mon Sep 17 00:00:00 2001
From: Anthony Tran <anthonytran at anthonys-air.lan>
Date: Thu, 10 Jul 2025 09:18:50 -0700
Subject: [PATCH 1/5] Added warning and warning group for sanitizer argument
mismatch
---
clang/include/clang/Basic/DiagnosticDriverKinds.td | 5 +++++
clang/include/clang/Basic/DiagnosticGroups.td | 3 +++
2 files changed, 8 insertions(+)
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 34b6c0d7a8acd..49a8bdf06bda4 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -874,4 +874,9 @@ def warn_drv_openacc_without_cir
: Warning<"OpenACC directives will result in no runtime behavior; use "
"-fclangir to enable runtime effect">,
InGroup<SourceUsesOpenACC>;
+
+def warn_drv_sanitize_trap_mismatch : Warning<
+ "-fsanitize-trap=%0 has no effect because the matching sanitizer is not enabled; "
+ "did you mean to pass \"-fsanitize=%0\" as well?">,
+ InGroup<SanitizeTrapMismatch>;
}
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index f54a830b0103e..a79562cd9c2e0 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1752,3 +1752,6 @@ def ExplicitSpecializationStorageClass : DiagGroup<"explicit-specialization-stor
// A warning for options that enable a feature that is not yet complete
def ExperimentalOption : DiagGroup<"experimental-option">;
+
+// Warnings for sanitizer arguments
+def SanitizeTrapMismatch : DiagGroup<"sanitize-trap-mismatch">;
>From f1bf9b34daca5d23d1a3f518847f3ccbc8f069a7 Mon Sep 17 00:00:00 2001
From: Anthony Tran <anthonytran at anthonys-air.lan>
Date: Thu, 10 Jul 2025 13:35:52 -0700
Subject: [PATCH 2/5] Emit warning and parse mismatched arguments
---
clang/lib/Driver/SanitizerArgs.cpp | 36 ++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 4bd61c2f8deef..8b78d850e0018 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -348,6 +348,30 @@ parseSanitizeSkipHotCutoffArgs(const Driver &D, const llvm::opt::ArgList &Args,
return Cutoffs;
}
+// Given a set of mismatched bits, TrapOnly (bits the user asked to trap but
+// that aren’t actually enabled), emit a warning based on -fsanitize-trap=NAME
+static void diagnoseTrapOnly(const Driver &D, SanitizerMask &TrapOnly) {
+// Double pass: one for sanitizer groupings, one for leaves (ex: undefined vs.
+// signed-integer-overflow)
+#define SANITIZER(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ if (TrapOnly & SanitizerKind::ID##Group) { \
+ D.Diag(diag::warn_drv_sanitize_trap_mismatch) << NAME; \
+ TrapOnly &= ~SanitizerKind::ID##Group; \
+ TrapOnly &= ~SanitizerKind::ID; \
+ }
+#include "clang/Basic/Sanitizers.def"
+
+#undef SANITIZER_GROUP
+#define SANITIZER_GROUP(NAME, ID, ALIAS)
+#define SANITIZER(NAME, ID) \
+ if (TrapOnly & SanitizerKind::ID) { \
+ D.Diag(diag::warn_drv_sanitize_trap_mismatch) << NAME; \
+ TrapOnly &= ~SanitizerKind::ID; \
+ }
+#include "clang/Basic/Sanitizers.def"
+}
+
bool SanitizerArgs::needsFuzzerInterceptors() const {
return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
}
@@ -730,6 +754,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
options::OPT_fno_sanitize_recover_EQ);
RecoverableKinds &= Kinds;
+ // Parse any -fsanitize-trap=<...> flags the user provided, then
+ // diagnose any which do not have a matching -fsanitize=<...>
+ if (DiagnoseErrors) {
+ SanitizerMask ExplicitTrap = parseSanitizeArgs(
+ D, Args, false, {}, {}, {}, options::OPT_fsanitize_trap_EQ,
+ options::OPT_fno_sanitize_trap_EQ);
+ SanitizerMask TrapOnly = ExplicitTrap & ~Kinds;
+
+ if (TrapOnly)
+ diagnoseTrapOnly(D, TrapOnly);
+ }
+
TrappingKinds &= Kinds;
RecoverableKinds &= ~TrappingKinds;
>From c7b44099357ee78329f6e289ef6feb321b9b121c Mon Sep 17 00:00:00 2001
From: Anthony Tran <anthonytran at anthonys-air.lan>
Date: Mon, 14 Jul 2025 03:36:11 -0700
Subject: [PATCH 3/5] Modify warning message
---
clang/include/clang/Basic/DiagnosticDriverKinds.td | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 49a8bdf06bda4..f2a0582a364bf 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -876,7 +876,7 @@ def warn_drv_openacc_without_cir
InGroup<SourceUsesOpenACC>;
def warn_drv_sanitize_trap_mismatch : Warning<
- "-fsanitize-trap=%0 has no effect because the matching sanitizer is not enabled; "
- "did you mean to pass \"-fsanitize=%0\" as well?">,
+ "-fsanitize-trap=%0 has no effect because the \"%0\" sanitizer is disabled; "
+ "consider passing \"fsanitize=%0\" to enable the sanitizer">,
InGroup<SanitizeTrapMismatch>;
}
>From 2610c329a75c61cf9c009389fb23cce30d412431 Mon Sep 17 00:00:00 2001
From: Anthony Tran <anthonytran at anthonys-air.lan>
Date: Mon, 14 Jul 2025 04:42:14 -0700
Subject: [PATCH 4/5] Added test case (still missing warning test case for
warning suppression)
---
clang/test/Driver/fsanitize-trap-mismatch.c | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 clang/test/Driver/fsanitize-trap-mismatch.c
diff --git a/clang/test/Driver/fsanitize-trap-mismatch.c b/clang/test/Driver/fsanitize-trap-mismatch.c
new file mode 100644
index 0000000000000..8568458f1f3b8
--- /dev/null
+++ b/clang/test/Driver/fsanitize-trap-mismatch.c
@@ -0,0 +1,7 @@
+// RUN: %clang -fsyntax-only %s -fsanitize-trap=undefined 2>&1 | FileCheck %s --check-prefix=WARN
+// RUN: %clang -fsyntax-only %s -fsanitize=undefined -fsanitize-trap=undefined 2>&1 | FileCheck %s --check-prefix=NOWARN
+//
+// WARN: warning: -fsanitize-trap=undefined has no effect because the "undefined" sanitizer is disabled; consider passing "fsanitize=undefined" to enable the sanitizer
+// NOWARN-NOT: warning: -fsanitize-trap=undefined has no effect because the "undefined" sanitizer is disabled; consider passing "fsanitize=undefined" to enable the sanitizer
+
+int main(void) { return 0; }
>From a1a1c32efd15e6733ab611ce2073326c82d23a24 Mon Sep 17 00:00:00 2001
From: Anthony Tran <anthonytran at anthonys-air.lan>
Date: Mon, 14 Jul 2025 04:50:47 -0700
Subject: [PATCH 5/5] Add comments for clarity
---
clang/lib/Driver/SanitizerArgs.cpp | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 8b78d850e0018..a72aaaec02f8b 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -351,8 +351,7 @@ parseSanitizeSkipHotCutoffArgs(const Driver &D, const llvm::opt::ArgList &Args,
// Given a set of mismatched bits, TrapOnly (bits the user asked to trap but
// that aren’t actually enabled), emit a warning based on -fsanitize-trap=NAME
static void diagnoseTrapOnly(const Driver &D, SanitizerMask &TrapOnly) {
-// Double pass: one for sanitizer groupings, one for leaves (ex: undefined vs.
-// signed-integer-overflow)
+// One pass for sanitizer groupings
#define SANITIZER(NAME, ID)
#define SANITIZER_GROUP(NAME, ID, ALIAS) \
if (TrapOnly & SanitizerKind::ID##Group) { \
@@ -363,6 +362,7 @@ static void diagnoseTrapOnly(const Driver &D, SanitizerMask &TrapOnly) {
#include "clang/Basic/Sanitizers.def"
#undef SANITIZER_GROUP
+// One pass for individual sanitizer names/leaves
#define SANITIZER_GROUP(NAME, ID, ALIAS)
#define SANITIZER(NAME, ID) \
if (TrapOnly & SanitizerKind::ID) { \
@@ -754,9 +754,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
options::OPT_fno_sanitize_recover_EQ);
RecoverableKinds &= Kinds;
+ // FIXME: `DiagnoseErrors` name seems a little wrong as we emit warnings here,
+ // not errors but that seems to be done elsewhere in this method.
+
// Parse any -fsanitize-trap=<...> flags the user provided, then
// diagnose any which do not have a matching -fsanitize=<...>
if (DiagnoseErrors) {
+ // parseSanitizeTrapArgs was not used because it sets a TrappingDefault
+ // which causes the emission of warnings beyond what the user entered
SanitizerMask ExplicitTrap = parseSanitizeArgs(
D, Args, false, {}, {}, {}, options::OPT_fsanitize_trap_EQ,
options::OPT_fno_sanitize_trap_EQ);
More information about the cfe-commits
mailing list