From 7581278ccccd392054f84706d7c4b4a61b51ddc0 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 8 Oct 2025 17:39:32 -0700 Subject: [PATCH] [BoundsSafety] Re-introduce `-funique-traps` as a legacy alias of `-fbounds-safety-unique-traps` In rdar://158088410 (https://github.com/swiftlang/llvm-project/pull/11455) the `-funique-traps` flag was removed in favor of a different implementation controlled by the `-fbounds-safety-unique-traps` flag. It turns out the `-funique-traps` flag is being used by an adopter of `-fbounds-safety`. To unbreak adopters of the flag this patch reintroduces the old flag (and its negation) as an alias of `-fbounds-safety-unique-traps` (`-fno-bounds-safety-unique-traps`) along with a diagnostic warning that `-funique-traps` (`-fno-unique-traps`) is deprecated. This patch doesn't use the `Alias<>` mixin in the `clang/Driver/Options.td` so "technically" at the implementation level `-funique-traps` isn't an alias of `-fbounds-safety-unique-traps`. This is done so that is possible distinguish use of the legacy flag from the new flag so that it is possible emit a deprecation warning. However, from the user's perspective `-funique-traps` and `-fbounds-safety-unique-traps` are aliases. We should remove `-funique-traps` eventually and that is tracked by rdar://162215869. rdar://162204734 --- clang/include/clang/Driver/Options.td | 16 +++++++- clang/lib/Driver/ToolChains/Clang.cpp | 39 ++++++++++++++++++- .../Driver/unique-traps-legacy-flag.c | 20 ++++++++++ clang/test/BoundsSafety/Driver/unique-traps.c | 38 ++++++++++++++++++ 4 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 clang/test/BoundsSafety/Driver/unique-traps-legacy-flag.c create mode 100644 clang/test/BoundsSafety/Driver/unique-traps.c diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e93312c58dfd6..26e6e9af934c6 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2039,14 +2039,26 @@ def fno_bounds_safety_bringup_missing_checks : Flag<["-"], "fno-bounds-safety-br defm bounds_safety_unique_traps : BoolFOption<"bounds-safety-unique-traps", CodeGenOpts<"BoundsSafetyUniqueTraps">, DefaultFalse, - PosFlag, - NegFlag>; + +// Legacy aliases +// TODO(dliew): Remove these (rdar://162215869). +// This isn't declared using `Alias` because that +// prevents identifying that this flag as distinct from +// `fbounds_safety_unique_traps`. +defm bounds_safety_legacy_unique_traps : BoolOptionWithoutMarshalling<"f", "unique-traps", + PosFlag, + NegFlag>; + // TO_UPSTREAM(BoundsSafety) OFF defm lifetime_safety : BoolFOption< diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index d562db0b58aa0..7d4471bd6943a 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7039,8 +7039,43 @@ void Clang::ConstructJob(Compilation &C, const JobAction &Job, << "-ftrap-function-returns" << "-ftrap-function="; } - Args.addOptInFlag(CmdArgs, options::OPT_fbounds_safety_unique_traps, - options::OPT_fno_bounds_safety_unique_traps); + // Diagnose uses of legacy `-funique-traps` flags. + // TODO(dliew): Remove this once all uses of the legacy flag are removed + // (rdar://162215869). + if (Arg *A = + Args.getLastArg(options::OPT_fbounds_safety_legacy_unique_traps, + options::OPT_fno_bounds_safety_legacy_unique_traps)) { + + StringRef ReplacementArg; + if (A->getOption().matches(options::OPT_fbounds_safety_legacy_unique_traps)) + ReplacementArg = getDriverOptTable().getOptionName( + options::OPT_fbounds_safety_unique_traps); + else + ReplacementArg = getDriverOptTable().getOptionName( + options::OPT_fno_bounds_safety_unique_traps); + D.Diag(diag::warn_drv_deprecated_arg) + << A->getSpelling() << 1 << ReplacementArg; + } + + // Pass the flag to enable unique traps if necessary. This handles both the + // legacy and new flag name for unique traps such that the old flags are + // treated as aliases of the new flags. + // TODO(dliew): Remove support for the legacy flag (rdar://162215869). + if (Arg *A = + Args.getLastArg(options::OPT_fbounds_safety_unique_traps, + options::OPT_fno_bounds_safety_unique_traps, + options::OPT_fbounds_safety_legacy_unique_traps, + options::OPT_fno_bounds_safety_legacy_unique_traps)) { + + // Note we only pass the flag for enabling unique traps to cc1. It isn't + // necessary to pass the flag to disable unique traps because it is cc1's + // default behavior. + if (A->getOption().matches(options::OPT_fbounds_safety_unique_traps) || + A->getOption().matches( + options::OPT_fbounds_safety_legacy_unique_traps)) { + CmdArgs.push_back("-fbounds-safety-unique-traps"); + } + } /* TO_UPSTREAM(BoundsSafety) OFF*/ // Handle -f[no-]wrapv and -f[no-]strict-overflow, which are used by both diff --git a/clang/test/BoundsSafety/Driver/unique-traps-legacy-flag.c b/clang/test/BoundsSafety/Driver/unique-traps-legacy-flag.c new file mode 100644 index 0000000000000..44d0020ed7bef --- /dev/null +++ b/clang/test/BoundsSafety/Driver/unique-traps-legacy-flag.c @@ -0,0 +1,20 @@ +// Simple use of legacy flag +// RUN: %clang -fbounds-safety -funique-traps -### %s 2>&1 | FileCheck --check-prefix=POS %s +// RUN: %clang -fbounds-safety -fno-unique-traps -### %s 2>&1 | FileCheck --check-prefix=NEG %s + +// Mix legacy flag with new flag +// RUN: %clang -fbounds-safety -funique-traps -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=POS %s +// RUN: %clang -fbounds-safety -fno-unique-traps -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=NEG %s + +// Last legacy flag wins for warning +// RUN: %clang -fbounds-safety -funique-traps -fno-unique-traps -funique-traps -### %s 2>&1 | FileCheck --check-prefix=POS %s +// RUN: %clang -fbounds-safety -funique-traps -fno-unique-traps -### %s 2>&1 | FileCheck --check-prefix=NEG %s + +// No warning +// RUN: %clang -fbounds-safety -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=NONE %s +// RUN: %clang -fbounds-safety -fno-bounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=NONE %s +// RUN: %clang -fbounds-safety -### %s 2>&1 | FileCheck --check-prefix=NONE %s + +// POS: warning: argument '-funique-traps' is deprecated, use 'fbounds-safety-unique-traps' instead [-Wdeprecated] +// NEG: warning: argument '-fno-unique-traps' is deprecated, use 'fno-bounds-safety-unique-traps' instead [-Wdeprecated] +// NONE-NOT: warning: argument '-f{{(no-)?}}unique-traps' is deprecated diff --git a/clang/test/BoundsSafety/Driver/unique-traps.c b/clang/test/BoundsSafety/Driver/unique-traps.c new file mode 100644 index 0000000000000..8a76ed53d3d9d --- /dev/null +++ b/clang/test/BoundsSafety/Driver/unique-traps.c @@ -0,0 +1,38 @@ +// RUN: %clang -fbounds-safety -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s + +// Simple use of new flag +// RUN: %clang -fbounds-safety -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s +// RUN: %clang -fbounds-safety -fno-bounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s + +// New flag used multiple times +// RUN: %clang -fbounds-safety -fbounds-safety-unique-traps -fno-bounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s +// RUN: %clang -fbounds-safety -fno-bounds-safety-unique-traps -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s +// RUN: %clang -fbounds-safety -fbounds-safety-unique-traps -fno-bounds-safety-unique-traps -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s +// RUN: %clang -fbounds-safety -fno-bounds-safety-unique-traps -fbounds-safety-unique-traps -fno-bounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s + +// Simple use of legacy flag +// RUN: %clang -fbounds-safety -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s +// RUN: %clang -fbounds-safety -fno-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s + +// Legacy flag used multiple times +// RUN: %clang -fbounds-safety -funique-traps -fno-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s +// RUN: %clang -fbounds-safety -fno-unique-traps -funique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s +// RUN: %clang -fbounds-safety -funique-traps -fno-unique-traps -funique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s +// RUN: %clang -fbounds-safety -fno-unique-traps -funique-traps -fno-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s + +// Mixed use of legacy and new flag +// RUN: %clang -fbounds-safety -funique-traps -fno-bounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s +// RUN: %clang -fbounds-safety -funique-traps -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s + +// RUN: %clang -fbounds-safety -fno-unique-traps -fno-bounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s +// RUN: %clang -fbounds-safety -fno-unique-traps -fbounds-safety-unique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s + +// RUN: %clang -fbounds-safety -fbounds-safety-unique-traps -fno-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s +// RUN: %clang -fbounds-safety -fbounds-safety-unique-traps -funique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s + +// RUN: %clang -fbounds-safety -fno-bounds-safety-unique-traps -fno-unique-traps -### %s 2>&1 | FileCheck --check-prefix=DISABLED %s +// RUN: %clang -fbounds-safety -fno-bounds-safety-unique-traps -funique-traps -### %s 2>&1 | FileCheck --check-prefix=ENABLED %s + + +// ENABLED: -fbounds-safety-unique-traps +// DISABLED-NOT: -fbounds-safety-unique-traps