]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix handling of -fsanitize-recover* options.
authorMartin Liska <mliska@suse.cz>
Mon, 26 Sep 2016 10:55:34 +0000 (12:55 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Mon, 26 Sep 2016 10:55:34 +0000 (10:55 +0000)
* common.opt: Exclude SANITIZE_UNREACHABLE and SANITIZE_RETURN
from default sanitize recover values.
* doc/invoke.texi: Fix documentation related to -fsanitize=leak,
-fsanitize=address, -fsanitize=thread and -fsanitize-recover.
* flag-types.h: Replace couple of 1 << x to 1UL << x, make it
consistent.
* opts.c (finish_options): Do a generic loop over options
that can be recovered.
(parse_sanitizer_options): Exclude SANITIZE_UNREACHABLE and
SANITIZE_RETURN.
(common_handle_option): Likewise.
* opts.h: Declare can_recover to sanitizer_opts_s.
* c-c++-common/ubsan/sanitize-recover-1.c: New test.
* c-c++-common/ubsan/sanitize-recover-2.c: New test.
* c-c++-common/ubsan/sanitize-recover-3.c: New test.
* c-c++-common/ubsan/sanitize-recover-4.c: New test.
* c-c++-common/ubsan/sanitize-recover-5.c: New test.
* c-c++-common/ubsan/sanitize-recover-6.c: New test.
* c-c++-common/ubsan/sanitize-recover-7.c: New test.
* c-c++-common/ubsan/sanitize-recover-8.c: New test.
* c-c++-common/ubsan/sanitize-recover-9.c: New test.

From-SVN: r240491

16 files changed:
gcc/ChangeLog
gcc/common.opt
gcc/doc/invoke.texi
gcc/flag-types.h
gcc/opts.c
gcc/opts.h
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-4.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-6.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c [new file with mode: 0644]

index 12eea1b75f844a971224dde2e19fee7a2dcef3ef..a46910dfeef93e6a4794f1711f877818750bd220 100644 (file)
@@ -1,3 +1,18 @@
+2016-09-26  Martin Liska  <mliska@suse.cz>
+
+       * common.opt: Exclude SANITIZE_UNREACHABLE and SANITIZE_RETURN
+       from default sanitize recover values.
+       * doc/invoke.texi: Fix documentation related to -fsanitize=leak,
+       -fsanitize=address, -fsanitize=thread and -fsanitize-recover.
+       * flag-types.h: Replace couple of 1 << x to 1UL << x, make it
+       consistent.
+       * opts.c (finish_options): Do a generic loop over options
+       that can be recovered.
+       (parse_sanitizer_options): Exclude SANITIZE_UNREACHABLE and
+       SANITIZE_RETURN.
+       (common_handle_option): Likewise.
+       * opts.h: Declare can_recover to sanitizer_opts_s.
+
 2016-09-26  Andre Vieira  <andre.simoesdiasvieira@arm.com>
 
        * target.def(elf_flags_numeric): Change documentation to
index b1d32fb45a25f66207378b55993eed8fee4dcdee..0e01577888d0910e1ad93dfe14674a8d5557f1a2 100644 (file)
@@ -228,7 +228,7 @@ unsigned int flag_sanitize
 
 ; What sanitizers should recover from errors
 Variable
-unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS
+unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)
 
 fsanitize-coverage=trace-pc
 Common Report Var(flag_sanitize_coverage)
index ce0eaef3c908ce4aad636a7e41cf0e2715878e56..676746237e32be7d747a5f6c854376490e58e0d6 100644 (file)
@@ -10255,6 +10255,7 @@ more details.  The run-time behavior can be influenced using the
 the available options are shown at startup of the instrumented program.  See
 @url{https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags}
 for a list of supported options.
+The option can't be combined with @option{-fsanitize=thread}.
 
 @item -fsanitize=kernel-address
 @opindex fsanitize=kernel-address
@@ -10270,17 +10271,19 @@ details. The run-time behavior can be influenced using the @env{TSAN_OPTIONS}
 environment variable; see
 @url{https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags} for a list of
 supported options.
+The option can't be combined with @option{-fsanitize=address}
+and/or @option{-fsanitize=leak}.
 
 @item -fsanitize=leak
 @opindex fsanitize=leak
 Enable LeakSanitizer, a memory leak detector.
-This option only matters for linking of executables and if neither
-@option{-fsanitize=address} nor @option{-fsanitize=thread} is used.  In that
-case the executable is linked against a library that overrides @code{malloc}
+This option only matters for linking of executables and
+the executable is linked against a library that overrides @code{malloc}
 and other allocator functions.  See
 @uref{https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer} for more
 details.  The run-time behavior can be influenced using the
 @env{LSAN_OPTIONS} environment variable.
+The option can't be combined with @option{-fsanitize=thread}.
 
 @item -fsanitize=undefined
 @opindex fsanitize=undefined
@@ -10454,6 +10457,7 @@ and program then exits with a non-zero exit code.
 Currently this feature only works for @option{-fsanitize=undefined} (and its suboptions
 except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}),
 @option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero},
+@option{-fsanitize=bounds-strict},
 @option{-fsanitize=kernel-address} and @option{-fsanitize=address}.
 For these sanitizers error recovery is turned on by default, except @option{-fsanitize=address},
 for which this feature is experimental.
@@ -10470,12 +10474,12 @@ setting the @code{halt_on_error} flag in the corresponding environment variable.
 
 Syntax without explicit @var{opts} parameter is deprecated.  It is equivalent to
 @smallexample
--fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero
+-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
 @end smallexample
 @noindent
 Similarly @option{-fno-sanitize-recover} is equivalent to
 @smallexample
--fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero
+-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
 @end smallexample
 
 @item -fsanitize-undefined-trap-on-error
index dd57e167098a334f193b4f072e45feecd975dedf..816df6b4ad987752029eab6f418ca4e3bd52e6a3 100644 (file)
@@ -203,25 +203,25 @@ enum vect_cost_model {
 /* Different instrumentation modes.  */
 enum sanitize_code {
   /* AddressSanitizer.  */
-  SANITIZE_ADDRESS = 1 << 0,
-  SANITIZE_USER_ADDRESS = 1 << 1,
-  SANITIZE_KERNEL_ADDRESS = 1 << 2,
+  SANITIZE_ADDRESS = 1UL << 0,
+  SANITIZE_USER_ADDRESS = 1UL << 1,
+  SANITIZE_KERNEL_ADDRESS = 1UL << 2,
   /* ThreadSanitizer.  */
-  SANITIZE_THREAD = 1 << 3,
+  SANITIZE_THREAD = 1UL << 3,
   /* LeakSanitizer.  */
-  SANITIZE_LEAK = 1 << 4,
+  SANITIZE_LEAK = 1UL << 4,
   /* UndefinedBehaviorSanitizer.  */
-  SANITIZE_SHIFT = 1 << 5,
-  SANITIZE_DIVIDE = 1 << 6,
-  SANITIZE_UNREACHABLE = 1 << 7,
-  SANITIZE_VLA = 1 << 8,
-  SANITIZE_NULL = 1 << 9,
-  SANITIZE_RETURN = 1 << 10,
-  SANITIZE_SI_OVERFLOW = 1 << 11,
-  SANITIZE_BOOL = 1 << 12,
-  SANITIZE_ENUM = 1 << 13,
-  SANITIZE_FLOAT_DIVIDE = 1 << 14,
-  SANITIZE_FLOAT_CAST = 1 << 15,
+  SANITIZE_SHIFT = 1UL << 5,
+  SANITIZE_DIVIDE = 1UL << 6,
+  SANITIZE_UNREACHABLE = 1UL << 7,
+  SANITIZE_VLA = 1UL << 8,
+  SANITIZE_NULL = 1UL << 9,
+  SANITIZE_RETURN = 1UL << 10,
+  SANITIZE_SI_OVERFLOW = 1UL << 11,
+  SANITIZE_BOOL = 1UL << 12,
+  SANITIZE_ENUM = 1UL << 13,
+  SANITIZE_FLOAT_DIVIDE = 1UL << 14,
+  SANITIZE_FLOAT_CAST = 1UL << 15,
   SANITIZE_BOUNDS = 1UL << 16,
   SANITIZE_ALIGNMENT = 1UL << 17,
   SANITIZE_NONNULL_ATTRIBUTE = 1UL << 18,
index f6259731263e26473fb6e3185d5a5de861be797e..45f1f89cd16cbc1fc061e50f62fc8a1cffca5075 100644 (file)
@@ -941,7 +941,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
     opts->x_debug_generate_pub_sections = 2;
 
   /* Userspace and kernel ASan conflict with each other.  */
-
   if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
       && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
     error_at (loc,
@@ -949,20 +948,23 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
              "-fsanitize=kernel-address");
 
   /* And with TSan.  */
-
   if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
       && (opts->x_flag_sanitize & SANITIZE_THREAD))
     error_at (loc,
              "-fsanitize=address and -fsanitize=kernel-address "
              "are incompatible with -fsanitize=thread");
 
-  /* Error recovery is not allowed for LSan and TSan.  */
-
-  if (opts->x_flag_sanitize_recover & SANITIZE_THREAD)
-    error_at (loc, "-fsanitize-recover=thread is not supported");
+  if ((opts->x_flag_sanitize & SANITIZE_LEAK)
+      && (opts->x_flag_sanitize & SANITIZE_THREAD))
+    error_at (loc,
+             "-fsanitize=leak is incompatible with -fsanitize=thread");
 
-  if (opts->x_flag_sanitize_recover & SANITIZE_LEAK)
-    error_at (loc, "-fsanitize-recover=leak is not supported");
+  /* Check error recovery for -fsanitize-recover option.  */
+  for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
+    if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
+       && !sanitizer_opts[i].can_recover)
+      error_at (loc, "-fsanitize-recover=%s is not supported",
+               sanitizer_opts[i].name);
 
   /* When instrumenting the pointers, we don't want to remove
      the null pointer checks.  */
@@ -1448,33 +1450,36 @@ enable_fdo_optimizations (struct gcc_options *opts,
 /* -f{,no-}sanitize{,-recover}= suboptions.  */
 const struct sanitizer_opts_s sanitizer_opts[] =
 {
-#define SANITIZER_OPT(name, flags) { #name, flags, sizeof #name - 1 }
-  SANITIZER_OPT (address, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS),
-  SANITIZER_OPT (kernel-address, SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
-  SANITIZER_OPT (thread, SANITIZE_THREAD),
-  SANITIZER_OPT (leak, SANITIZE_LEAK),
-  SANITIZER_OPT (shift, SANITIZE_SHIFT),
-  SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE),
-  SANITIZER_OPT (undefined, SANITIZE_UNDEFINED),
-  SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE),
-  SANITIZER_OPT (vla-bound, SANITIZE_VLA),
-  SANITIZER_OPT (return, SANITIZE_RETURN),
-  SANITIZER_OPT (null, SANITIZE_NULL),
-  SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW),
-  SANITIZER_OPT (bool, SANITIZE_BOOL),
-  SANITIZER_OPT (enum, SANITIZE_ENUM),
-  SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE),
-  SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST),
-  SANITIZER_OPT (bounds, SANITIZE_BOUNDS),
-  SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT),
-  SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT),
-  SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE),
-  SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE),
-  SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE),
-  SANITIZER_OPT (vptr, SANITIZE_VPTR),
-  SANITIZER_OPT (all, ~0U),
+#define SANITIZER_OPT(name, flags, recover) \
+    { #name, flags, sizeof #name - 1, recover }
+  SANITIZER_OPT (address, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS, true),
+  SANITIZER_OPT (kernel-address, SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS,
+                true),
+  SANITIZER_OPT (thread, SANITIZE_THREAD, false),
+  SANITIZER_OPT (leak, SANITIZE_LEAK, false),
+  SANITIZER_OPT (shift, SANITIZE_SHIFT, true),
+  SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE, true),
+  SANITIZER_OPT (undefined, SANITIZE_UNDEFINED, true),
+  SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE, false),
+  SANITIZER_OPT (vla-bound, SANITIZE_VLA, true),
+  SANITIZER_OPT (return, SANITIZE_RETURN, false),
+  SANITIZER_OPT (null, SANITIZE_NULL, true),
+  SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW, true),
+  SANITIZER_OPT (bool, SANITIZE_BOOL, true),
+  SANITIZER_OPT (enum, SANITIZE_ENUM, true),
+  SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE, true),
+  SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST, true),
+  SANITIZER_OPT (bounds, SANITIZE_BOUNDS, true),
+  SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT, true),
+  SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT, true),
+  SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE, true),
+  SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
+                true),
+  SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true),
+  SANITIZER_OPT (vptr, SANITIZE_VPTR, true),
+  SANITIZER_OPT (all, ~0U, true),
 #undef SANITIZER_OPT
-  { NULL, 0U, 0UL }
+  { NULL, 0U, 0UL, false }
 };
 
 /* Parse comma separated sanitizer suboptions from P for option SCODE,
@@ -1516,11 +1521,20 @@ parse_sanitizer_options (const char *p, location_t loc, int scode,
                      error_at (loc, "-fsanitize=all option is not valid");
                  }
                else
-                 flags |= ~(SANITIZE_USER_ADDRESS | SANITIZE_THREAD
-                            | SANITIZE_LEAK);
+                 flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK
+                            | SANITIZE_UNREACHABLE | SANITIZE_RETURN);
              }
            else if (value)
-             flags |= sanitizer_opts[i].flag;
+             {
+               /* Do not enable -fsanitize-recover=unreachable and
+                  -fsanitize-recover=return if -fsanitize-recover=undefined
+                  is selected.  */
+               if (sanitizer_opts[i].flag == SANITIZE_UNDEFINED)
+                 flags |= (SANITIZE_UNDEFINED
+                           & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN));
+               else
+                 flags |= sanitizer_opts[i].flag;
+             }
            else
              flags &= ~sanitizer_opts[i].flag;
            found = true;
@@ -1770,7 +1784,8 @@ common_handle_option (struct gcc_options *opts,
     case OPT_fsanitize_recover:
       if (value)
        opts->x_flag_sanitize_recover
-         |= SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT;
+         |= (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)
+            & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN);
       else
        opts->x_flag_sanitize_recover
          &= ~(SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT);
index 4132432bd7c6791c18794dc96bf6eabad9b27eea..b3e64353c8afcf4d1f16bd2702d70f2557296560 100644 (file)
@@ -414,6 +414,7 @@ extern const struct sanitizer_opts_s
   const char *const name;
   unsigned int flag;
   size_t len;
+  bool can_recover;
 } sanitizer_opts[];
 
 extern void add_misspelling_candidates (auto_vec<char *> *candidates,
index 2dd006e194065c07b144784abc1c824d1a6fdbe9..f8567e1a53cef0e21bd8a9a7f91dc896090a9980 100644 (file)
@@ -1,3 +1,15 @@
+2016-09-26  Martin Liska  <mliska@suse.cz>
+
+       * c-c++-common/ubsan/sanitize-recover-1.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-2.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-3.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-4.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-5.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-6.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-7.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-8.c: New test.
+       * c-c++-common/ubsan/sanitize-recover-9.c: New test.
+
 2016-09-26  Marek Polacek  <polacek@redhat.com>
 
        PR c/7652
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c
new file mode 100644 (file)
index 0000000..4d8c27e
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-recover=unreachable" } */
+
+int i;
+
+/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c
new file mode 100644 (file)
index 0000000..e9849bd
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-recover=return" } */
+
+int i;
+
+/* { dg-error "-fsanitize-recover=return is not supported" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-3.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-3.c
new file mode 100644 (file)
index 0000000..844f3fd
--- /dev/null
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-recover=all" } */
+
+int i;
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-4.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-4.c
new file mode 100644 (file)
index 0000000..45fa5b9
--- /dev/null
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-recover=undefined" } */
+
+int i;
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c
new file mode 100644 (file)
index 0000000..9c1ed32
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-recover=undefined,unreachable" } */
+
+int i;
+
+/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-6.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-6.c
new file mode 100644 (file)
index 0000000..e309e1b
--- /dev/null
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-recover=undefined,unreachable -fno-sanitize-recover=unreachable" } */
+
+int i;
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c
new file mode 100644 (file)
index 0000000..2e6599f
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=address -fsanitize=thread" } */
+
+int i;
+
+/* { dg-error "-fsanitize=address and -fsanitize=kernel-address are incompatible with -fsanitize=thread" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c
new file mode 100644 (file)
index 0000000..ecaf0e6
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=leak -fsanitize=thread" } */
+
+int i;
+
+/* { dg-error "-fsanitize=leak is incompatible with -fsanitize=thread" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c
new file mode 100644 (file)
index 0000000..ef80ef1
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-recover=unreachable -fsanitize-recover=undefined" } */
+
+int i;
+
+/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */