[clang] [clang][rtsan] Reland realtime sanitizer codegen and driver (#102622) (PR #105841)

via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 23 08:17:18 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Chris Apple (cjappl)

<details>
<summary>Changes</summary>

This reverts commit a1e9b7e646b76bf844e8a9a101ebd27de11992ff
This relands commit d010ec6af8162a8ae4e42d2cac5282f83db0ce07

No modifications from the original patch. It was determined that the ubsan build failure was happening even after the revert, some examples:

https://lab.llvm.org/buildbot/#/builders/159/builds/4477 
https://lab.llvm.org/buildbot/#/builders/159/builds/4478 
https://lab.llvm.org/buildbot/#/builders/159/builds/4479

---
Full diff: https://github.com/llvm/llvm-project/pull/105841.diff


16 Files Affected:

- (added) clang/docs/RealtimeSanitizer.rst (+85) 
- (modified) clang/docs/ReleaseNotes.rst (+5) 
- (modified) clang/docs/UsersManual.rst (+2) 
- (modified) clang/docs/index.rst (+1) 
- (modified) clang/include/clang/Basic/Sanitizers.def (+3) 
- (modified) clang/include/clang/Driver/SanitizerArgs.h (+1) 
- (modified) clang/lib/CodeGen/BackendUtil.cpp (+8) 
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+7) 
- (modified) clang/lib/Driver/SanitizerArgs.cpp (+9-5) 
- (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+6) 
- (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+8) 
- (modified) clang/lib/Driver/ToolChains/Linux.cpp (+1) 
- (added) clang/test/CodeGen/rtsan_attribute_inserted.c (+7) 
- (added) clang/test/CodeGen/rtsan_entry_exit_insertion.c (+13) 
- (added) clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c (+6) 
- (modified) clang/test/Driver/fsanitize.c (+46) 


``````````diff
diff --git a/clang/docs/RealtimeSanitizer.rst b/clang/docs/RealtimeSanitizer.rst
new file mode 100644
index 00000000000000..799cd43509c6e6
--- /dev/null
+++ b/clang/docs/RealtimeSanitizer.rst
@@ -0,0 +1,85 @@
+=================
+RealtimeSanitizer
+=================
+
+.. contents::
+   :local:
+
+Introduction
+============
+RealtimeSanitizer (a.k.a. RTSan) is a real-time safety testing tool for C and C++
+projects. RTSan can be used to detect real-time violations, i.e. calls to methods
+that are not safe for use in functions with deterministic runtime requirements.
+RTSan considers any function marked with the ``[[clang::nonblocking]]`` attribute
+to be a real-time function. If RTSan detects a call to ``malloc``, ``free``,
+``pthread_mutex_lock``, or anything else that could have a non-deterministic
+execution time in a function marked ``[[clang::nonblocking]]``
+RTSan raises an error.
+
+The runtime slowdown introduced by RealtimeSanitizer is negligible.
+
+How to build
+============
+
+Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>` and enable the
+``compiler-rt`` runtime. An example CMake configuration that will allow for the
+use/testing of RealtimeSanitizer:
+
+.. code-block:: console
+
+   $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
+
+Usage
+=====
+
+There are two requirements:
+
+1. The code must be compiled with the ``-fsanitize=realtime`` flag.
+2. Functions that are subject to real-time constraints must be marked
+   with the ``[[clang::nonblocking]]`` attribute.
+
+Typically, these attributes should be added onto the functions that are entry
+points for threads with real-time priority. These threads are subject to a fixed
+callback time, such as audio callback threads or rendering loops in video game
+code.
+
+.. code-block:: console
+
+   % cat example_realtime_violation.cpp
+   #include <vector>
+
+   void violation() [[clang::nonblocking]]{
+     std::vector<float> v;
+     v.resize(100);
+   }
+
+   int main() {
+     violation();
+     return 0;
+   }
+   # Compile and link
+   % clang++ -fsanitize=realtime -g example_realtime_violation.cpp
+
+If a real-time safety violation is detected in a ``[[clang::nonblocking]]``
+context, or any function invoked by that function, the program will exit with a
+non-zero exit code.
+
+.. code-block:: console
+
+   % clang++ -fsanitize=realtime -g example_realtime_violation.cpp
+   % ./a.out
+   Real-time violation: intercepted call to real-time unsafe function `malloc` in real-time context! Stack trace:
+    #0 0x000102893034 in __rtsan::PrintStackTrace() rtsan_stack.cpp:45
+    #1 0x000102892e64 in __rtsan::Context::ExpectNotRealtime(char const*) rtsan_context.cpp:78
+    #2 0x00010289397c in malloc rtsan_interceptors.cpp:286
+    #3 0x000195bd7bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0)
+    #4 0x5c7f00010230f07c  (<unknown module>)
+    #5 0x00010230f058 in std::__1::__libcpp_allocate[abi:ue170006](unsigned long, unsigned long) new:324
+    #6 0x00010230effc in std::__1::allocator<float>::allocate[abi:ue170006](unsigned long) allocator.h:114
+    ... snip ...
+    #10 0x00010230e4bc in std::__1::vector<float, std::__1::allocator<float>>::__append(unsigned long) vector:1162
+    #11 0x00010230dcdc in std::__1::vector<float, std::__1::allocator<float>>::resize(unsigned long) vector:1981
+    #12 0x00010230dc28 in violation() main.cpp:5
+    #13 0x00010230dd64 in main main.cpp:9
+    #14 0x0001958960dc  (<unknown module>)
+    #15 0x2f557ffffffffffc  (<unknown module>)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 93040c2eee2c0b..9b9f0792adce49 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -446,6 +446,11 @@ Moved checkers
 
 Sanitizers
 ----------
+- Introduced Realtime Sanitizer, activated by using the -fsanitize=realtime
+  flag. This sanitizer detects unsafe system library calls, such as memory
+  allocations and mutex locks. If any such function is called during invocation
+  of a function marked with the ``[[clang::nonblocking]]`` attribute, an error
+  is printed to the console and the process exits non-zero.
 
 - Added the ``-fsanitize-undefined-ignore-overflow-pattern`` flag which can be
   used to disable specific overflow-dependent code patterns. The supported
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index d19b77ae40b0d7..069ecba875cd59 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -2068,6 +2068,8 @@ are listed below.
       integrity.
    -  ``-fsanitize=safe-stack``: :doc:`safe stack <SafeStack>`
       protection against stack-based memory corruption errors.
+   -  ``-fsanitize=realtime``: :doc:`RealtimeSanitizer`,
+      a real-time safety checker.
 
    There are more fine-grained checks available: see
    the :ref:`list <ubsan-checks>` of specific kinds of
diff --git a/clang/docs/index.rst b/clang/docs/index.rst
index 9bae0bd83243bd..4a497f4d9bcc3c 100644
--- a/clang/docs/index.rst
+++ b/clang/docs/index.rst
@@ -32,6 +32,7 @@ Using Clang as a Compiler
    UndefinedBehaviorSanitizer
    DataFlowSanitizer
    LeakSanitizer
+   RealtimeSanitizer
    SanitizerCoverage
    SanitizerStats
    SanitizerSpecialCaseList
diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def
index bee35e9dca7c39..9223f62b3639a7 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -79,6 +79,9 @@ SANITIZER("thread", Thread)
 // Numerical stability sanitizer.
 SANITIZER("numerical", NumericalStability)
 
+// RealtimeSanitizer
+SANITIZER("realtime", Realtime)
+
 // LeakSanitizer
 SANITIZER("leak", Leak)
 
diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h
index e64ec463ca8907..0c6f3869549ef7 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -107,6 +107,7 @@ class SanitizerArgs {
   bool needsNsanRt() const {
     return Sanitizers.has(SanitizerKind::NumericalStability);
   }
+  bool needsRtsanRt() const { return Sanitizers.has(SanitizerKind::Realtime); }
 
   bool hasMemTag() const {
     return hasMemtagHeap() || hasMemtagStack() || hasMemtagGlobals();
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index fdd89edd72e109..026f16484c0949 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -78,6 +78,7 @@
 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
 #include "llvm/Transforms/Instrumentation/NumericalStabilitySanitizer.h"
 #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
+#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
 #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
@@ -990,6 +991,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
             FPM.addPass(BoundsCheckingPass());
           });
 
+    if (LangOpts.Sanitize.has(SanitizerKind::Realtime))
+      PB.registerScalarOptimizerLateEPCallback(
+          [](FunctionPassManager &FPM, OptimizationLevel Level) {
+            RealtimeSanitizerOptions Opts;
+            FPM.addPass(RealtimeSanitizerPass(Opts));
+          });
+
     // Don't add sanitizers if we are here from ThinLTO PostLink. That already
     // done on PreLink stage.
     if (!IsThinLTOPostLink) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index eff8c9f5694084..c89eaa0f4e3bfc 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -845,6 +845,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
   if (SanOpts.has(SanitizerKind::ShadowCallStack))
     Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
 
+  if (SanOpts.has(SanitizerKind::Realtime))
+    if (FD && FD->getASTContext().hasAnyFunctionEffects())
+      for (const FunctionEffectWithCondition &Fe : FD->getFunctionEffects()) {
+        if (Fe.Effect.kind() == FunctionEffect::Kind::NonBlocking)
+          Fn->addFnAttr(llvm::Attribute::SanitizeRealtime);
+      }
+
   // Apply fuzzing attribute to the function.
   if (SanOpts.hasOneOf(SanitizerKind::Fuzzer | SanitizerKind::FuzzerNoLink))
     Fn->addFnAttr(llvm::Attribute::OptForFuzzing);
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 9d9ad79d51d7f8..09262f40b5b50c 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -558,11 +558,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
                          SanitizerKind::Leak | SanitizerKind::Thread |
                          SanitizerKind::Memory | SanitizerKind::KernelAddress |
                          SanitizerKind::Scudo | SanitizerKind::SafeStack),
-      std::make_pair(SanitizerKind::MemTag,
-                     SanitizerKind::Address | SanitizerKind::KernelAddress |
-                         SanitizerKind::HWAddress |
-                         SanitizerKind::KernelHWAddress),
-      std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
+      std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |
+                                                SanitizerKind::KernelAddress |
+                                                SanitizerKind::HWAddress |
+                                                SanitizerKind::KernelHWAddress),
+      std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),
+      std::make_pair(SanitizerKind::Realtime,
+                     SanitizerKind::Address | SanitizerKind::Thread |
+                         SanitizerKind::Undefined | SanitizerKind::Memory)};
+
   // Enable toolchain specific default sanitizers if not explicitly disabled.
   SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 0738ed18f54078..0601016c3b14b8 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1456,6 +1456,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
       if (!Args.hasArg(options::OPT_shared))
         HelperStaticRuntimes.push_back("hwasan-preinit");
     }
+    if (SanArgs.needsRtsanRt() && SanArgs.linkRuntimes())
+      SharedRuntimes.push_back("rtsan");
   }
 
   // The stats_client library is also statically linked into DSOs.
@@ -1481,6 +1483,10 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
       StaticRuntimes.push_back("asan_cxx");
   }
 
+  if (!SanArgs.needsSharedRt() && SanArgs.needsRtsanRt() &&
+      SanArgs.linkRuntimes())
+    StaticRuntimes.push_back("rtsan");
+
   if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt()) {
     StaticRuntimes.push_back("memprof");
     if (SanArgs.linkCXXRuntimes())
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 2550541a438481..5e7f9290e2009d 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1519,6 +1519,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
     const char *sanitizer = nullptr;
     if (Sanitize.needsUbsanRt()) {
       sanitizer = "UndefinedBehaviorSanitizer";
+    } else if (Sanitize.needsRtsanRt()) {
+      sanitizer = "RealtimeSanitizer";
     } else if (Sanitize.needsAsanRt()) {
       sanitizer = "AddressSanitizer";
     } else if (Sanitize.needsTsanRt()) {
@@ -1541,6 +1543,11 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
         AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
       }
     }
+    if (Sanitize.needsRtsanRt()) {
+      assert(Sanitize.needsSharedRt() &&
+             "Static sanitizer runtimes not supported");
+      AddLinkSanitizerLibArgs(Args, CmdArgs, "rtsan");
+    }
     if (Sanitize.needsLsanRt())
       AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
     if (Sanitize.needsUbsanRt()) {
@@ -3539,6 +3546,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;
+  Res |= SanitizerKind::Realtime;
   Res |= SanitizerKind::Leak;
   Res |= SanitizerKind::Fuzzer;
   Res |= SanitizerKind::FuzzerNoLink;
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 2265138edbffbe..96680b3412a2db 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -800,6 +800,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;
+  Res |= SanitizerKind::Realtime;
   Res |= SanitizerKind::Fuzzer;
   Res |= SanitizerKind::FuzzerNoLink;
   Res |= SanitizerKind::KernelAddress;
diff --git a/clang/test/CodeGen/rtsan_attribute_inserted.c b/clang/test/CodeGen/rtsan_attribute_inserted.c
new file mode 100644
index 00000000000000..05a1d9a8c2047a
--- /dev/null
+++ b/clang/test/CodeGen/rtsan_attribute_inserted.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1  -triple x86_64-unknown-linux -fsanitize=realtime %s -emit-llvm -o - %s | FileCheck %s
+
+float process(float *a) [[clang::nonblocking]] { return *a; }
+
+// CHECK-LABEL: @process{{.*}}#0 {
+// CHECK: attributes #0 = {
+// CHECK-SAME: {{.*sanitize_realtime.*}}
diff --git a/clang/test/CodeGen/rtsan_entry_exit_insertion.c b/clang/test/CodeGen/rtsan_entry_exit_insertion.c
new file mode 100644
index 00000000000000..9ba0103ca1e353
--- /dev/null
+++ b/clang/test/CodeGen/rtsan_entry_exit_insertion.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -fsanitize=realtime -emit-llvm -o - %s | FileCheck %s
+
+int foo(int *a) [[clang::nonblocking]] { return *a; }
+
+// The first instruction after the function is entred should be a call to
+// enable the realtime sanitizer stack.
+// CHECK-LABEL: define{{.*}}@foo
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call{{.*}}__rtsan_realtime_enter
+
+// __rtsan_realtime_exit should be inserted at all function returns.
+// CHECK-LABEL: call{{.*}}__rtsan_realtime_exit
+// CHECK-NEXT: ret
diff --git a/clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c b/clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c
new file mode 100644
index 00000000000000..43ad6ed1a429ee
--- /dev/null
+++ b/clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+float process(float *a) [[clang::nonblocking]] { return *a; }
+
+// Without the -fsanitize=realtime flag, we shouldn't attach the attribute.
+// CHECK-NOT: {{.*sanitize_realtime.*}}
diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c
index 678fa432fb0a0a..f86c978f221cd4 100644
--- a/clang/test/Driver/fsanitize.c
+++ b/clang/test/Driver/fsanitize.c
@@ -1040,3 +1040,49 @@
 // RUN: not %clang --target=aarch64-none-elf -fsanitize=dataflow %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL
 // RUN: not %clang --target=arm-arm-none-eabi -fsanitize=shadow-call-stack %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL
 // UNSUPPORTED-BAREMETAL: unsupported option '-fsanitize={{.*}}' for target
+
+// RUN: %clang --target=x86_64-apple-darwin -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-DARWIN
+// CHECK-RTSAN-X86-64-DARWIN-NOT: unsupported option
+
+// RUN: %clang --target=x86_64-apple-darwin -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-DARWIN
+// CHECK-RTSAN-X86-64-DARWIN-NOT: unsupported option
+// RUN: %clang --target=x86_64-apple-macos -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-MACOS
+// CHECK-RTSAN-X86-64-MACOS-NOT: unsupported option
+// RUN: %clang --target=arm64-apple-macos -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-MACOS
+// CHECK-RTSAN-ARM64-MACOS-NOT: unsupported option
+
+// RUN: %clang --target=arm64-apple-ios-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-IOSSIMULATOR
+// CHECK-RTSAN-ARM64-IOSSIMULATOR-NOT: unsupported option
+
+// RUN: %clang --target=arm64-apple-watchos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-WATCHOSSIMULATOR
+// CHECK-RTSAN-ARM64-WATCHOSSIMULATOR-NOT: unsupported option
+
+// RUN: %clang --target=arm64-apple-tvos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-TVOSSIMULATOR
+// CHECK-RTSAN-ARM64-TVOSSIMULATOR-NOT: unsupported option
+
+// RUN: %clang --target=x86_64-apple-ios-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-IOSSIMULATOR
+// CHECK-RTSAN-X86-64-IOSSIMULATOR-NOT: unsupported option
+
+// RUN: %clang --target=x86_64-apple-watchos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-WATCHOSSIMULATOR
+// CHECK-RTSAN-X86-64-WATCHOSSIMULATOR-NOT: unsupported option
+
+// RUN: %clang --target=x86_64-apple-tvos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-TVOSSIMULATOR
+// CHECK-RTSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option
+
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-LINUX
+// CHECK-RTSAN-X86-64-LINUX-NOT: unsupported option
+
+// RUN: not %clang --target=i386-pc-openbsd -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-OPENBSD
+// CHECK-RTSAN-OPENBSD: unsupported option '-fsanitize=realtime' for target 'i386-pc-openbsd'
+
+// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,thread  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-TSAN
+// CHECK-REALTIME-TSAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=thread'
+
+// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,address  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-ASAN
+// CHECK-REALTIME-ASAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=address'
+
+// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,memory  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-MSAN
+// CHECK-REALTIME-MSAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=memory'
+
+// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,undefined  %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-UBSAN
+// CHECK-REALTIME-UBSAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=undefined'

``````````

</details>


https://github.com/llvm/llvm-project/pull/105841


More information about the cfe-commits mailing list