[clang] [Driver][BoundsSafety] Add -fbounds-safety-experimental flag (PR #70480)
Yeoul Na via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 30 12:50:24 PDT 2023
https://github.com/rapidsna updated https://github.com/llvm/llvm-project/pull/70480
>From 99ec6e055dd32a86bf6d589a6895658dcbe1d7bd Mon Sep 17 00:00:00 2001
From: Yeoul Na <yeoul_na at apple.com>
Date: Fri, 27 Oct 2023 08:34:37 -0700
Subject: [PATCH 1/2] [Driver][BoundsSafety] Add -fbounds-safety-experimental
flag
-fbounds-safety-experimental is an experimental flag for
-fbounds-safety, which is a bounds-safety extension for C.
-fbounds-safety will require substantial changes across the Clang
codebase. So we introduce this experimental flag is to gate our
incremental patches until we push the essential functionality of
the extension.
-fbounds-safety-experimental currently doesn't do anything but
reporting an error when the flag is used with an unsupported
source language (currently only supports C).
---
.../clang/Basic/DiagnosticFrontendKinds.td | 3 +++
clang/include/clang/Basic/LangOptions.def | 2 ++
clang/include/clang/Driver/Options.td | 8 +++++++
clang/lib/Driver/ToolChains/Clang.cpp | 3 +++
clang/lib/Frontend/CompilerInvocation.cpp | 23 +++++++++++++++++++
clang/test/BoundsSafety/Driver/driver.c | 9 ++++++++
.../Frontend/only_c_is_supported.c | 15 ++++++++++++
7 files changed, 63 insertions(+)
create mode 100644 clang/test/BoundsSafety/Driver/driver.c
create mode 100644 clang/test/BoundsSafety/Frontend/only_c_is_supported.c
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 715e0c0dc8fa84e..edcbbe992377e12 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -330,6 +330,9 @@ def warn_alias_with_section : Warning<
"as the %select{aliasee|resolver}2">,
InGroup<IgnoredAttributes>;
+def error_bounds_safety_lang_not_supported : Error<
+ "bounds safety is only supported for C">;
+
let CategoryName = "Instrumentation Issue" in {
def warn_profile_data_out_of_date : Warning<
"profile data may be out of date: of %0 function%s0, %1 %plural{1:has|:have}1"
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index c0ea4ecb9806a5b..222812d876a65f8 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -470,6 +470,8 @@ VALUE_LANGOPT(FuchsiaAPILevel, 32, 0, "Fuchsia API level")
// on large _BitInts.
BENIGN_VALUE_LANGOPT(MaxBitIntWidth, 32, 128, "Maximum width of a _BitInt")
+LANGOPT(BoundsSafety, 1, 0, "Bounds safety extension for C")
+
LANGOPT(IncrementalExtensions, 1, 0, " True if we want to process statements"
"on the global scope, ignore EOF token and continue later on (thus "
"avoid tearing the Lexer and etc. down). Controlled by "
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 7f3f5125d42e7a9..3eb98c8ee2950a1 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1732,6 +1732,14 @@ def fswift_async_fp_EQ : Joined<["-"], "fswift-async-fp=">,
NormalizedValues<["Auto", "Always", "Never"]>,
MarshallingInfoEnum<CodeGenOpts<"SwiftAsyncFramePointer">, "Always">;
+defm bounds_safety : BoolFOption<
+ "bounds-safety-experimental",
+ LangOpts<"BoundsSafety">, DefaultFalse,
+ PosFlag<SetTrue, [], [ClangOption], "Enable">,
+ NegFlag<SetFalse, [], [ClangOption], "Disable">,
+ BothFlags<[], [ClangOption, CC1Option],
+ " experimental bounds safety extension for C">>;
+
defm addrsig : BoolFOption<"addrsig",
CodeGenOpts<"Addrsig">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 43a92adbef64ba8..7482b852fb37958 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6689,6 +6689,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
options::OPT_fno_assume_sane_operator_new);
+ Args.addOptInFlag(CmdArgs, options::OPT_fbounds_safety,
+ options::OPT_fno_bounds_safety);
+
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
TC.IsBlocksDefault()) ||
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index fd6c250efeda2a8..f785bd504d63a81 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3618,6 +3618,23 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed);
}
+static bool SupportsBoundsSafety(Language Lang) {
+ // Currently, bounds safety is only supported for C. However, it's also
+ // possible to pass assembly files and LLVM IR through Clang, and
+ // those should be trivially supported. This is especially important because
+ // some build systems, like xcbuild and somewhat clumsy Makefiles, will pass
+ // C_FLAGS to Clang while building assembly files.
+ switch (Lang) {
+ case Language::Unknown:
+ case Language::Asm:
+ case Language::LLVM_IR:
+ case Language::C:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
InputKind IK, const llvm::Triple &T,
std::vector<std::string> &Includes,
@@ -3835,6 +3852,12 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.Trigraphs =
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
+ Opts.BoundsSafety = Args.hasFlag(OPT_fbounds_safety, OPT_fno_bounds_safety,
+ /*Default*/ Opts.BoundsSafety);
+
+ if (Opts.BoundsSafety && !SupportsBoundsSafety(IK.getLanguage()))
+ Diags.Report(diag::error_bounds_safety_lang_not_supported);
+
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
&& Opts.OpenCLVersion == 200);
diff --git a/clang/test/BoundsSafety/Driver/driver.c b/clang/test/BoundsSafety/Driver/driver.c
new file mode 100644
index 000000000000000..91759838d8e1cd0
--- /dev/null
+++ b/clang/test/BoundsSafety/Driver/driver.c
@@ -0,0 +1,9 @@
+// RUN: %clang -c %s -### 2>&1 | not grep fbounds-safety-experimental
+
+// RUN: %clang -fbounds-safety-experimental -### %s 2>&1 | FileCheck -check-prefix T0 %s
+// T0: -fbounds-safety-experimental
+
+// RUN: %clang -fbounds-safety-experimental -fno-bounds-safety-experimental -c %s -### 2>&1 | not grep -e fbounds-safety-experimental
+
+// RUN: %clang -fno-bounds-safety-experimental -fbounds-safety-experimental -c %s -### 2>&1 | FileCheck -check-prefix T1 %s
+// T1: -fbounds-safety-experimental
\ No newline at end of file
diff --git a/clang/test/BoundsSafety/Frontend/only_c_is_supported.c b/clang/test/BoundsSafety/Frontend/only_c_is_supported.c
new file mode 100644
index 000000000000000..fdfc74e8da19878
--- /dev/null
+++ b/clang/test/BoundsSafety/Frontend/only_c_is_supported.c
@@ -0,0 +1,15 @@
+// RUN: not %clang -fbounds-safety-experimental -x c++ %s 2>&1 | FileCheck %s
+
+// RUN: not %clang -fbounds-safety-experimental -x objective-c %s 2>&1 | FileCheck %s
+
+// RUN: not %clang -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck %s
+
+// RUN: not %clang -cc1 -fbounds-safety-experimental -x c++ %s 2>&1 | FileCheck %s
+
+// RUN: not %clang -cc1 -fbounds-safety-experimental -x objective-c %s 2>&1 | FileCheck %s
+
+// RUN: not %clang -cc1 -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck %s
+
+// RUN: not %clang -cc1 -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck %s
+
+// CHECK: error: bounds safety is only supported for C
>From 5f241a6a523eb075fc07df2e69e0f6d9c5a3edc8 Mon Sep 17 00:00:00 2001
From: Yeoul Na <yeoul_na at apple.com>
Date: Fri, 27 Oct 2023 16:13:16 -0700
Subject: [PATCH 2/2] Report warning when -fbounds-safety is ignored for
assembly
Also, LLVM IR and Unknown must be unreachable when parsing the language
arguments.
---
.../clang/Basic/DiagnosticFrontendKinds.td | 4 ++-
clang/lib/Frontend/CompilerInvocation.cpp | 5 +---
clang/test/BoundsSafety/Driver/driver.c | 14 +++++-----
.../BoundsSafety/Frontend/ignored_for_asm.s | 5 ++++
.../BoundsSafety/Frontend/ignored_for_ir.ll | 5 ++++
.../Frontend/only_c_is_supported.c | 26 +++++++++++++------
6 files changed, 40 insertions(+), 19 deletions(-)
create mode 100644 clang/test/BoundsSafety/Frontend/ignored_for_asm.s
create mode 100644 clang/test/BoundsSafety/Frontend/ignored_for_ir.ll
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index edcbbe992377e12..f913d36a8004cbc 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -330,8 +330,10 @@ def warn_alias_with_section : Warning<
"as the %select{aliasee|resolver}2">,
InGroup<IgnoredAttributes>;
-def error_bounds_safety_lang_not_supported : Error<
+let CategoryName = "Bounds Safety Issue" in {
+def err_bounds_safety_lang_not_supported : Error<
"bounds safety is only supported for C">;
+} // end of bounds safety issue category
let CategoryName = "Instrumentation Issue" in {
def warn_profile_data_out_of_date : Warning<
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index f785bd504d63a81..b60159f2cfa0e59 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3852,11 +3852,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.Trigraphs =
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
- Opts.BoundsSafety = Args.hasFlag(OPT_fbounds_safety, OPT_fno_bounds_safety,
- /*Default*/ Opts.BoundsSafety);
-
if (Opts.BoundsSafety && !SupportsBoundsSafety(IK.getLanguage()))
- Diags.Report(diag::error_bounds_safety_lang_not_supported);
+ Diags.Report(diag::err_bounds_safety_lang_not_supported);
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
&& Opts.OpenCLVersion == 200);
diff --git a/clang/test/BoundsSafety/Driver/driver.c b/clang/test/BoundsSafety/Driver/driver.c
index 91759838d8e1cd0..e17f6a8694c4536 100644
--- a/clang/test/BoundsSafety/Driver/driver.c
+++ b/clang/test/BoundsSafety/Driver/driver.c
@@ -1,9 +1,11 @@
-// RUN: %clang -c %s -### 2>&1 | not grep fbounds-safety-experimental
+// RUN: %clang -c %s -### 2>&1 | FileCheck -check-prefix T0 %s
+// T0-NOT: -fbounds-safety-experimental
-// RUN: %clang -fbounds-safety-experimental -### %s 2>&1 | FileCheck -check-prefix T0 %s
-// T0: -fbounds-safety-experimental
+// RUN: %clang -fbounds-safety-experimental -### %s 2>&1 | FileCheck -check-prefix T1 %s
+// T1: -fbounds-safety-experimental
-// RUN: %clang -fbounds-safety-experimental -fno-bounds-safety-experimental -c %s -### 2>&1 | not grep -e fbounds-safety-experimental
+// RUN: %clang -fbounds-safety-experimental -fno-bounds-safety-experimental -c %s -### 2>&1 | FileCheck -check-prefix T2 %s
+// T2-NOT: -fbounds-safety-experimental
-// RUN: %clang -fno-bounds-safety-experimental -fbounds-safety-experimental -c %s -### 2>&1 | FileCheck -check-prefix T1 %s
-// T1: -fbounds-safety-experimental
\ No newline at end of file
+// RUN: %clang -fno-bounds-safety-experimental -fbounds-safety-experimental -c %s -### 2>&1 | FileCheck -check-prefix T3 %s
+// T3: -fbounds-safety-experimental
\ No newline at end of file
diff --git a/clang/test/BoundsSafety/Frontend/ignored_for_asm.s b/clang/test/BoundsSafety/Frontend/ignored_for_asm.s
new file mode 100644
index 000000000000000..44072730ba92fc4
--- /dev/null
+++ b/clang/test/BoundsSafety/Frontend/ignored_for_asm.s
@@ -0,0 +1,5 @@
+
+// RUN: %clang -fbounds-safety-experimental -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fbounds-safety-experimental -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: warning: '-fbounds-safety' is ignored for assembly
diff --git a/clang/test/BoundsSafety/Frontend/ignored_for_ir.ll b/clang/test/BoundsSafety/Frontend/ignored_for_ir.ll
new file mode 100644
index 000000000000000..33219397301bbb6
--- /dev/null
+++ b/clang/test/BoundsSafety/Frontend/ignored_for_ir.ll
@@ -0,0 +1,5 @@
+; RUN: %clang -fbounds-safety-experimental -x ir -S %s -o /dev/null 2>&1 | FileCheck %s
+; RUN: %clang_cc1 -fbounds-safety-experimental -x ir -S %s -o /dev/null 2>&1 | FileCheck %s
+
+; CHECK-NOT: warning: '-fbounds-safety' is ignored for LLVM IR
+; CHECK-NOT: error: bounds safety is only supported for C
\ No newline at end of file
diff --git a/clang/test/BoundsSafety/Frontend/only_c_is_supported.c b/clang/test/BoundsSafety/Frontend/only_c_is_supported.c
index fdfc74e8da19878..d6c46cbab791888 100644
--- a/clang/test/BoundsSafety/Frontend/only_c_is_supported.c
+++ b/clang/test/BoundsSafety/Frontend/only_c_is_supported.c
@@ -1,15 +1,25 @@
-// RUN: not %clang -fbounds-safety-experimental -x c++ %s 2>&1 | FileCheck %s
+// RUN: not %clang -fbounds-safety-experimental -x c++ %s 2>&1 | FileCheck -check-prefix ERR %s
-// RUN: not %clang -fbounds-safety-experimental -x objective-c %s 2>&1 | FileCheck %s
+// RUN: not %clang -fbounds-safety-experimental -x objective-c %s 2>&1 | FileCheck -check-prefix ERR %s
-// RUN: not %clang -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck %s
+// RUN: not %clang -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck -check-prefix ERR %s
-// RUN: not %clang -cc1 -fbounds-safety-experimental -x c++ %s 2>&1 | FileCheck %s
+// RUN: not %clang -fbounds-safety-experimental -x cuda -nocudalib -nocudainc %s 2>&1 | FileCheck -check-prefix ERR %s
-// RUN: not %clang -cc1 -fbounds-safety-experimental -x objective-c %s 2>&1 | FileCheck %s
+// RUN: not %clang -fbounds-safety-experimental -x renderscript %s 2>&1 | FileCheck -check-prefix ERR %s
-// RUN: not %clang -cc1 -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fbounds-safety-experimental -x c++ %s 2>&1 | FileCheck -check-prefix ERR %s
-// RUN: not %clang -cc1 -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fbounds-safety-experimental -x objective-c %s 2>&1 | FileCheck -check-prefix ERR %s
-// CHECK: error: bounds safety is only supported for C
+// RUN: not %clang_cc1 -fbounds-safety-experimental -x objective-c++ %s 2>&1 | FileCheck -check-prefix ERR %s
+
+// RUN: not %clang_cc1 -fbounds-safety-experimental -x cuda %s 2>&1 | FileCheck -check-prefix ERR %s
+
+// RUN: not %clang_cc1 -fbounds-safety-experimental -x renderscript %s 2>&1 | FileCheck -check-prefix ERR %s
+
+// ERR: error: bounds safety is only supported for C
+
+// expected-no-diagnostics
+// RUN: %clang -fbounds-safety-experimental -fsyntax-only -Xclang -verify -c -x c %s
+// RUN: %clang_cc1 -fbounds-safety-experimental -fsyntax-only -verify -x c %s
\ No newline at end of file
More information about the cfe-commits
mailing list