https://github.com/ro-i updated https://github.com/llvm/llvm-project/pull/166851

>From bc0aad0726eda18a9aa984f6e16dcd25580aef86 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <[email protected]>
Date: Thu, 6 Nov 2025 15:36:50 -0600
Subject: [PATCH 1/7] [AMDGPU][clang] Fix clang driver check for multiple
 sanitizer arguments

`-fsanitize=address,fuzzer` should be rejected like
`-fsanitize=fuzzer,address`.
The address sanitizer enables the device sanitizer pipeline. The fuzzer
implicitly turns on LLVMs SanitizerCoverage, which the driver then
forwards to the device cc1.  SanitizerCoverage is not supported on
amdgcn.
---
 clang/lib/Driver/ToolChains/AMDGPU.cpp             |  8 +++++---
 clang/lib/Driver/ToolChains/AMDGPU.h               | 12 +++++++-----
 clang/test/Driver/amdgpu-openmp-sanitize-options.c | 13 +++++++++++++
 3 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp 
b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 1a243fef9532d..2f6ad4c4fa327 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -1092,9 +1092,11 @@ bool AMDGPUToolChain::shouldSkipSanitizeOption(
   auto &Diags = TC.getDriver().getDiags();
 
   // For simplicity, we only allow -fsanitize=address
-  SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
-  if (K != SanitizerKind::Address)
-    return true;
+  for (const char *Value : A->getValues()) {
+    SanitizerMask K = parseSanitizerValue(Value, /*AllowGroups=*/false);
+    if (K != SanitizerKind::Address)
+      return true;
+  }
 
   // Check 'xnack+' availability by default
   llvm::StringRef Processor =
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h 
b/clang/lib/Driver/ToolChains/AMDGPU.h
index e90a5736911e4..c5680a9d486bd 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -161,11 +161,13 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public 
AMDGPUToolChain {
       return;
     auto &Diags = getDriver().getDiags();
     for (auto *A : Args.filtered(options::OPT_fsanitize_EQ)) {
-      SanitizerMask K =
-          parseSanitizerValue(A->getValue(), /*Allow Groups*/ false);
-      if (K != SanitizerKind::Address)
-        Diags.Report(clang::diag::warn_drv_unsupported_option_for_target)
-            << A->getAsString(Args) << getTriple().str();
+      for (const char *Value : A->getValues()) {
+        SanitizerMask K =
+            parseSanitizerValue(Value, /*Allow Groups*/ false);
+        if (K != SanitizerKind::Address)
+          Diags.Report(clang::diag::warn_drv_unsupported_option_for_target)
+              << A->getAsString(Args) << getTriple().str();
+      }
     }
   }
 };
diff --git a/clang/test/Driver/amdgpu-openmp-sanitize-options.c 
b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
index 10d64984918e6..59ecbcf7b35ba 100644
--- a/clang/test/Driver/amdgpu-openmp-sanitize-options.c
+++ b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
@@ -52,6 +52,18 @@
 // RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ --offload-arch=gfx900:xnack+ 
-fsanitize=address -fno-gpu-sanitize --rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=HOSTSAN,NOGPUSAN,SAN %s
 
+// Catch invalid combination of sanitizers regardless of their order.
+// The address sanitizer enables the device sanitizer pipeline. The fuzzer
+// implicitly turns on LLVMs SanitizerCoverage, which the driver then forwards
+// to the device cc1. SanitizerCoverage is not supported on amdgcn
+// RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=address,fuzzer 
--rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION1 %s
+// RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=fuzzer,address 
--rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION2 %s
+
+// INVALIDCOMBINATION1: warning: ignoring '-fsanitize=address,fuzzer' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
+// INVALIDCOMBINATION2: warning: ignoring '-fsanitize=fuzzer,address' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
+
 // FAIL-DAG: error: cannot find ROCm device library for ABI version 5; provide 
its path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to 
build without ROCm device library
 // NOTSUPPORTED-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa'
 
@@ -59,6 +71,7 @@
 // XNACKNEG: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx908:xnack-' as it is not currently supported there. Use it with an offload 
arch containing 'xnack+' instead
 
 // HOSTSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* 
"-fopenmp".* "-fsanitize=address".* "--offload-targets=amdgcn-amd-amdhsa".* 
"-x" "c".*}}
+// HOSTSANCOMBINATION: {{"[^"]*clang[^"]*" "-cc1" "-triple" 
"x86_64-unknown-linux-gnu".* "-fopenmp".* 
"-fsanitize=address,fuzzer,fuzzer-no-link".* 
"--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}}
 
 // GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" 
"-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* 
"-mlink-bitcode-file" "[^"]*asanrtl.bc".* "-mlink-bitcode-file" 
"[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900|gfx1250|gfx1251)".* "-fopenmp".* 
"-fsanitize=address".* "-x" "c".*}}
 // NOGPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" 
"-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-target-cpu" 
"(gfx908|gfx900)".* "-fopenmp".* "-x" "c".*}}

>From e2a11d36551fccd16ad5e96c76a0a0e1f70cc959 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <[email protected]>
Date: Thu, 6 Nov 2025 15:44:06 -0600
Subject: [PATCH 2/7] fix formatting

---
 clang/lib/Driver/ToolChains/AMDGPU.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h 
b/clang/lib/Driver/ToolChains/AMDGPU.h
index c5680a9d486bd..95d2a53ed5be8 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -162,8 +162,7 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public 
AMDGPUToolChain {
     auto &Diags = getDriver().getDiags();
     for (auto *A : Args.filtered(options::OPT_fsanitize_EQ)) {
       for (const char *Value : A->getValues()) {
-        SanitizerMask K =
-            parseSanitizerValue(Value, /*Allow Groups*/ false);
+        SanitizerMask K = parseSanitizerValue(Value, /*Allow Groups*/ false);
         if (K != SanitizerKind::Address)
           Diags.Report(clang::diag::warn_drv_unsupported_option_for_target)
               << A->getAsString(Args) << getTriple().str();

>From cfa15f4c389aa97fdab748a147119be561799b31 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <[email protected]>
Date: Fri, 7 Nov 2025 08:09:11 -0600
Subject: [PATCH 3/7] ignore sanitizers selectively

---
 clang/lib/Driver/ToolChains/AMDGPU.cpp        | 22 +++++++++++--------
 clang/lib/Driver/ToolChains/AMDGPU.h          | 16 ++++++++------
 clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp  | 14 +++++++-----
 clang/lib/Driver/ToolChains/HIPAMD.cpp        | 12 +++++++++-
 .../Driver/amdgpu-openmp-sanitize-options.c   | 13 ++++++-----
 clang/test/Driver/hip-sanitize-options.hip    | 19 +++++++++++++++-
 6 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp 
b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 2f6ad4c4fa327..333711e8ba844 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -1074,29 +1074,32 @@ ROCMToolChain::getCommonDeviceLibNames(
       getSanitizerArgs(DriverArgs).needsAsanRt());
 }
 
-bool AMDGPUToolChain::shouldSkipSanitizeOption(
+std::optional<std::string> AMDGPUToolChain::filterSanitizeOption(
     const ToolChain &TC, const llvm::opt::ArgList &DriverArgs,
     StringRef TargetID, const llvm::opt::Arg *A) const {
   // For actions without targetID, do nothing.
   if (TargetID.empty())
-    return false;
+    return std::nullopt;
   Option O = A->getOption();
 
   if (!O.matches(options::OPT_fsanitize_EQ))
-    return false;
+    return std::nullopt;
 
   if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
                           options::OPT_fno_gpu_sanitize, true))
-    return true;
+    return "";
 
   auto &Diags = TC.getDriver().getDiags();
 
-  // For simplicity, we only allow -fsanitize=address
+  // We only allow the address sanitizer and ignore all other sanitizers.
+  SmallVector<std::string, 4> SupportedSanitizers;
   for (const char *Value : A->getValues()) {
     SanitizerMask K = parseSanitizerValue(Value, /*AllowGroups=*/false);
-    if (K != SanitizerKind::Address)
-      return true;
+    if (K == SanitizerKind::Address)
+      SupportedSanitizers.push_back(std::string(Value));
   }
+  if (SupportedSanitizers.empty())
+    return "";
 
   // Check 'xnack+' availability by default
   llvm::StringRef Processor =
@@ -1120,7 +1123,8 @@ bool AMDGPUToolChain::shouldSkipSanitizeOption(
     Diags.Report(
         clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature)
         << A->getAsString(DriverArgs) << TargetID << "xnack+";
-    return true;
+    return "";
   }
-  return false;
+
+  return llvm::join(SupportedSanitizers, ",");
 }
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h 
b/clang/lib/Driver/ToolChains/AMDGPU.h
index 95d2a53ed5be8..7c4dcfef8b7f1 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -101,11 +101,13 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public 
Generic_ELF {
   /// Needed for translating LTO options.
   const char *getDefaultLinker() const override { return "ld.lld"; }
 
-  /// Should skip sanitize options.
-  bool shouldSkipSanitizeOption(const ToolChain &TC,
-                                const llvm::opt::ArgList &DriverArgs,
-                                StringRef TargetID,
-                                const llvm::opt::Arg *A) const;
+  /// Filter supported sanitizers from the sanitize option and return them. If
+  /// there should be no filtering and Arg should be kept as-is, return
+  /// std::nullopt. If no sanitizers are supported, return an empty string.
+  std::optional<std::string>
+  filterSanitizeOption(const ToolChain &TC,
+                       const llvm::opt::ArgList &DriverArgs, StringRef 
TargetID,
+                       const llvm::opt::Arg *A) const;
 
   /// Uses amdgpu-arch tool to get arch of the system GPU. Will return error
   /// if unable to find one.
@@ -164,8 +166,8 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public 
AMDGPUToolChain {
       for (const char *Value : A->getValues()) {
         SanitizerMask K = parseSanitizerValue(Value, /*Allow Groups*/ false);
         if (K != SanitizerKind::Address)
-          Diags.Report(clang::diag::warn_drv_unsupported_option_for_target)
-              << A->getAsString(Args) << getTriple().str();
+          
Diags.Report(clang::diag::warn_drv_unsupported_option_part_for_target)
+              << Value << A->getAsString(Args) << getTriple().str();
       }
     }
   }
diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp 
b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
index 2b41d54a9eb73..8d59116f3cc13 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -66,16 +66,20 @@ llvm::opt::DerivedArgList 
*AMDGPUOpenMPToolChain::TranslateArgs(
 
   const OptTable &Opts = getDriver().getOpts();
 
-  // Skip sanitize options passed from the HostTC. Claim them early.
+  // Skip sanitize options passed from the HostTC. Remove them early.
   // The decision to sanitize device code is computed only by
   // 'shouldSkipSanitizeOption'.
   if (DAL->hasArg(options::OPT_fsanitize_EQ))
-    DAL->claimAllArgs(options::OPT_fsanitize_EQ);
+    DAL->eraseArg(options::OPT_fsanitize_EQ);
 
-  for (Arg *A : Args)
-    if (!shouldSkipSanitizeOption(*this, Args, BoundArch, A) &&
-        !llvm::is_contained(*DAL, A))
+  for (Arg *A : Args) {
+    std::optional<std::string> SupportedSanitizers =
+        filterSanitizeOption(*this, Args, BoundArch, A);
+    if (!SupportedSanitizers)
       DAL->append(A);
+    else if (!SupportedSanitizers->empty())
+      DAL->AddJoinedArg(A, A->getOption(), *SupportedSanitizers);
+  }
 
   if (!BoundArch.empty()) {
     DAL->eraseArg(options::OPT_march_EQ);
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp 
b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index c0c8afec07264..648be0ac2db08 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -291,9 +291,19 @@ HIPAMDToolChain::TranslateArgs(const 
llvm::opt::DerivedArgList &Args,
 
   const OptTable &Opts = getDriver().getOpts();
 
+  // Skip sanitize options passed from the HostTC. Remove them early.
+  // The decision to sanitize device code is computed only by
+  // 'shouldSkipSanitizeOption'.
+  if (DAL->hasArg(options::OPT_fsanitize_EQ))
+    DAL->eraseArg(options::OPT_fsanitize_EQ);
+
   for (Arg *A : Args) {
-    if (!shouldSkipSanitizeOption(*this, Args, BoundArch, A))
+    std::optional<std::string> SupportedSanitizers =
+        filterSanitizeOption(*this, Args, BoundArch, A);
+    if (!SupportedSanitizers)
       DAL->append(A);
+    else if (!SupportedSanitizers->empty())
+      DAL->AddJoinedArg(A, A->getOption(), *SupportedSanitizers);
   }
 
   if (!BoundArch.empty()) {
diff --git a/clang/test/Driver/amdgpu-openmp-sanitize-options.c 
b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
index 59ecbcf7b35ba..d197db08cc720 100644
--- a/clang/test/Driver/amdgpu-openmp-sanitize-options.c
+++ b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
@@ -52,20 +52,21 @@
 // RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ --offload-arch=gfx900:xnack+ 
-fsanitize=address -fno-gpu-sanitize --rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=HOSTSAN,NOGPUSAN,SAN %s
 
-// Catch invalid combination of sanitizers regardless of their order.
-// The address sanitizer enables the device sanitizer pipeline. The fuzzer
+// Catch invalid combination of sanitizers regardless of their order and ignore
+// them selectively.
+// (The address sanitizer enables the device sanitizer pipeline. The fuzzer
 // implicitly turns on LLVMs SanitizerCoverage, which the driver then forwards
-// to the device cc1. SanitizerCoverage is not supported on amdgcn
+// to the device cc1. SanitizerCoverage is not supported on amdgcn.)
 // RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=address,fuzzer 
--rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION1 %s
 // RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=fuzzer,address 
--rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION2 %s
 
-// INVALIDCOMBINATION1: warning: ignoring '-fsanitize=address,fuzzer' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
-// INVALIDCOMBINATION2: warning: ignoring '-fsanitize=fuzzer,address' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
+// INVALIDCOMBINATION1: warning: ignoring 'fuzzer' in 
'-fsanitize=address,fuzzer' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
+// INVALIDCOMBINATION2: warning: ignoring 'fuzzer' in 
'-fsanitize=fuzzer,address' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
 
 // FAIL-DAG: error: cannot find ROCm device library for ABI version 5; provide 
its path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to 
build without ROCm device library
-// NOTSUPPORTED-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa'
+// NOTSUPPORTED-DAG: warning: ignoring 'leak' in '-fsanitize=leak' option as 
it is not currently supported for target 'amdgcn-amd-amdhsa'
 
 // NOXNACK: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx908' as it is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
 // XNACKNEG: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx908:xnack-' as it is not currently supported there. Use it with an offload 
arch containing 'xnack+' instead
diff --git a/clang/test/Driver/hip-sanitize-options.hip 
b/clang/test/Driver/hip-sanitize-options.hip
index 490385173a4cb..2fce25461ab34 100644
--- a/clang/test/Driver/hip-sanitize-options.hip
+++ b/clang/test/Driver/hip-sanitize-options.hip
@@ -52,6 +52,18 @@
 // RUN:   -fsanitize=leak -nogpuinc --rocm-path=%S/Inputs/rocm \
 // RUN:   %s 2>&1 | FileCheck -check-prefixes=NOGPUNEG %s
 
+// Catch invalid combination of sanitizers regardless of their order and ignore
+// them selectively.
+// (The address sanitizer enables the device sanitizer pipeline. The fuzzer
+// implicitly turns on LLVMs SanitizerCoverage, which the driver then forwards
+// to the device cc1. SanitizerCoverage is not supported on amdgcn.)
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
+// RUN:   -fsanitize=address,fuzzer --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATION,INVALIDCOMBINATION1 %s
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
+// RUN:   -fsanitize=fuzzer,address --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATION,INVALIDCOMBINATION2 %s
+
 // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-fsanitize=address"}}
 // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-mlink-bitcode-file" 
".*asanrtl.bc"}}
 // CHECK-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}}
@@ -67,7 +79,7 @@
 
 // FAIL: error: cannot find ROCm device library for ABI version 5; provide its 
path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to 
build without ROCm device library
 
-// XNACK-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa'
+// XNACK-DAG: warning: ignoring 'leak' in '-fsanitize=leak' option as it is 
not currently supported for target 'amdgcn-amd-amdhsa'
 // XNACK-DAG: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx900:xnack-' as it is not currently supported there. Use it with an offload 
arch containing 'xnack+' instead
 // XNACK-DAG: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx906' as it is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
 // XNACK-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* 
"-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}}
@@ -101,3 +113,8 @@
 // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* 
"-target-cpu" "gfx900".* "-target-feature" "-xnack"}}
 // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* 
"-target-cpu" "gfx906"}}
 // NOGPUNEG-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}}
+
+// INVALIDCOMBINATION1-DAG: warning: ignoring 'fuzzer' in 
'-fsanitize=address,fuzzer' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
+// INVALIDCOMBINATION2-DAG: warning: ignoring 'fuzzer' in 
'-fsanitize=fuzzer,address' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
+// INVALIDCOMBINATION-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" 
".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* 
"-fsanitize=address"}}
+// INVALIDCOMBINATION-DAG: {{"[^"]*clang[^"]*".* "-triple" 
"x86_64-unknown-linux-gnu".* "-fsanitize=address,fuzzer,fuzzer-no-link"}}

>From 1d0052b347b6c63f66dd136ef8e2f5fcf1dc5361 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <[email protected]>
Date: Fri, 7 Nov 2025 08:37:30 -0600
Subject: [PATCH 4/7] add forgotten diagnostic

---
 clang/include/clang/Basic/DiagnosticDriverKinds.td | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index afd44a110bc74..863236cacd61e 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -133,6 +133,9 @@ def 
warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
 def warn_drv_unsupported_option_for_target : Warning<
   "ignoring '%0' option as it is not currently supported for target '%1'">,
   InGroup<OptionIgnored>;
+def warn_drv_unsupported_option_part_for_target : Warning<
+  "ignoring '%0' in '%1' option as it is not currently supported for target 
'%2'">,
+  InGroup<OptionIgnored>;
 def warn_drv_invalid_argument_for_flang : Warning<
   "'%0' is not valid for Fortran">,
   InGroup<OptionIgnored>;

>From da9e71593799dd263f3f936a17c9691553da96f9 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <[email protected]>
Date: Fri, 7 Nov 2025 09:50:33 -0600
Subject: [PATCH 5/7] fix after rebase

---
 clang/lib/Driver/ToolChains/AMDGPU.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp 
b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 333711e8ba844..ca6ab13f8a28a 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -1111,7 +1111,7 @@ std::optional<std::string> 
AMDGPUToolChain::filterSanitizeOption(
                       ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
                       : llvm::AMDGPU::getArchAttrR600(ProcKind);
   if (Features & llvm::AMDGPU::FEATURE_XNACK_ALWAYS)
-    return false;
+    return std::nullopt;
 
   // Look for the xnack feature in TargetID
   llvm::StringMap<bool> FeatureMap;

>From 0ee2fac3dd3cdd485fb2b5861fc3761df26a19d1 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <[email protected]>
Date: Thu, 13 Nov 2025 05:28:57 -0600
Subject: [PATCH 6/7] refactor code; support errors for explicit -Xarch_device;
 improve testing

---
 .../clang/Basic/DiagnosticDriverKinds.td      |  7 ++
 clang/lib/Driver/ToolChains/AMDGPU.cpp        | 44 ++++-------
 clang/lib/Driver/ToolChains/AMDGPU.h          | 75 +++++++++++++++----
 clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp  | 20 +----
 clang/lib/Driver/ToolChains/HIPAMD.cpp        | 20 +----
 .../Driver/amdgpu-openmp-sanitize-options.c   | 28 ++++++-
 clang/test/Driver/hip-sanitize-options.hip    | 46 +++++++++++-
 7 files changed, 161 insertions(+), 79 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 863236cacd61e..2dd2354da7ec9 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -126,6 +126,9 @@ def err_drv_bad_offload_arch_combo : Error<
   "invalid offload arch combinations: '%0' and '%1' (for a specific processor, 
"
   "a feature should either exist in all offload archs, or not exist in any "
   "offload archs)">;
+def err_drv_unsupported_option_for_offload_arch_req_feature : Error<
+  "'%0' option for offload arch '%1' is not currently supported "
+  "there. Use it with an offload arch containing '%2' instead">;
 def warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
   "ignoring '%0' option for offload arch '%1' as it is not currently supported 
"
   "there. Use it with an offload arch containing '%2' instead">,
@@ -133,9 +136,13 @@ def 
warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
 def warn_drv_unsupported_option_for_target : Warning<
   "ignoring '%0' option as it is not currently supported for target '%1'">,
   InGroup<OptionIgnored>;
+def err_drv_unsupported_option_for_target : Error<
+  "'%0' option is not currently supported for target '%1'">;
 def warn_drv_unsupported_option_part_for_target : Warning<
   "ignoring '%0' in '%1' option as it is not currently supported for target 
'%2'">,
   InGroup<OptionIgnored>;
+def err_drv_unsupported_option_part_for_target : Error<
+  "'%0' in '%1' option is not currently supported for target '%2'">;
 def warn_drv_invalid_argument_for_flang : Warning<
   "'%0' is not valid for Fortran">,
   InGroup<OptionIgnored>;
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp 
b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index ca6ab13f8a28a..fe96d238036e8 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -1074,32 +1074,12 @@ ROCMToolChain::getCommonDeviceLibNames(
       getSanitizerArgs(DriverArgs).needsAsanRt());
 }
 
-std::optional<std::string> AMDGPUToolChain::filterSanitizeOption(
+bool AMDGPUToolChain::shouldSkipSanitizeOption(
     const ToolChain &TC, const llvm::opt::ArgList &DriverArgs,
     StringRef TargetID, const llvm::opt::Arg *A) const {
-  // For actions without targetID, do nothing.
-  if (TargetID.empty())
-    return std::nullopt;
-  Option O = A->getOption();
-
-  if (!O.matches(options::OPT_fsanitize_EQ))
-    return std::nullopt;
-
-  if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
-                          options::OPT_fno_gpu_sanitize, true))
-    return "";
-
   auto &Diags = TC.getDriver().getDiags();
-
-  // We only allow the address sanitizer and ignore all other sanitizers.
-  SmallVector<std::string, 4> SupportedSanitizers;
-  for (const char *Value : A->getValues()) {
-    SanitizerMask K = parseSanitizerValue(Value, /*AllowGroups=*/false);
-    if (K == SanitizerKind::Address)
-      SupportedSanitizers.push_back(std::string(Value));
-  }
-  if (SupportedSanitizers.empty())
-    return "";
+  bool IsExplicitDevice =
+      A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
 
   // Check 'xnack+' availability by default
   llvm::StringRef Processor =
@@ -1111,7 +1091,7 @@ std::optional<std::string> 
AMDGPUToolChain::filterSanitizeOption(
                       ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
                       : llvm::AMDGPU::getArchAttrR600(ProcKind);
   if (Features & llvm::AMDGPU::FEATURE_XNACK_ALWAYS)
-    return std::nullopt;
+    return false;
 
   // Look for the xnack feature in TargetID
   llvm::StringMap<bool> FeatureMap;
@@ -1120,11 +1100,17 @@ std::optional<std::string> 
AMDGPUToolChain::filterSanitizeOption(
   (void)OptionalGpuArch;
   auto Loc = FeatureMap.find("xnack");
   if (Loc == FeatureMap.end() || !Loc->second) {
-    Diags.Report(
-        clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature)
-        << A->getAsString(DriverArgs) << TargetID << "xnack+";
-    return "";
+    if (IsExplicitDevice) {
+      Diags.Report(
+          clang::diag::err_drv_unsupported_option_for_offload_arch_req_feature)
+          << A->getAsString(DriverArgs) << TargetID << "xnack+";
+    } else {
+      Diags.Report(
+          
clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature)
+          << A->getAsString(DriverArgs) << TargetID << "xnack+";
+    }
+    return true;
   }
 
-  return llvm::join(SupportedSanitizers, ",");
+  return false;
 }
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h 
b/clang/lib/Driver/ToolChains/AMDGPU.h
index 7c4dcfef8b7f1..5614b72a872ce 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -101,13 +101,11 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public 
Generic_ELF {
   /// Needed for translating LTO options.
   const char *getDefaultLinker() const override { return "ld.lld"; }
 
-  /// Filter supported sanitizers from the sanitize option and return them. If
-  /// there should be no filtering and Arg should be kept as-is, return
-  /// std::nullopt. If no sanitizers are supported, return an empty string.
-  std::optional<std::string>
-  filterSanitizeOption(const ToolChain &TC,
-                       const llvm::opt::ArgList &DriverArgs, StringRef 
TargetID,
-                       const llvm::opt::Arg *A) const;
+  /// Should skip sanitize option.
+  bool shouldSkipSanitizeOption(const ToolChain &TC,
+                                const llvm::opt::ArgList &DriverArgs,
+                                StringRef TargetID,
+                                const llvm::opt::Arg *A) const;
 
   /// Uses amdgpu-arch tool to get arch of the system GPU. Will return error
   /// if unable to find one.
@@ -157,19 +155,64 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public 
AMDGPUToolChain {
     return SanitizerKind::Address;
   }
 
-  void diagnoseUnsupportedSanitizers(const llvm::opt::ArgList &Args) const {
-    if (!Args.hasFlag(options::OPT_fgpu_sanitize, 
options::OPT_fno_gpu_sanitize,
-                      true))
-      return;
+  bool handleSanitizeOption(const ToolChain &TC, llvm::opt::DerivedArgList 
&DAL,
+                            const llvm::opt::ArgList &DriverArgs,
+                            StringRef TargetID, const llvm::opt::Arg *A) const 
{
+    if (TargetID.empty())
+      return false;
+    // If this isn't a sanitizer option, don't handle it.
+    if (!A->getOption().matches(options::OPT_fsanitize_EQ))
+      return false;
+    // If we shouldn't do sanitizing, skip it.
+    if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
+                            options::OPT_fno_gpu_sanitize, true))
+      return true;
+
     auto &Diags = getDriver().getDiags();
-    for (auto *A : Args.filtered(options::OPT_fsanitize_EQ)) {
-      for (const char *Value : A->getValues()) {
-        SanitizerMask K = parseSanitizerValue(Value, /*Allow Groups*/ false);
-        if (K != SanitizerKind::Address)
+    bool IsExplicitDevice =
+        A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
+
+    SmallVector<const char *, 4> SupportedSanitizers;
+    SmallVector<const char *, 4> UnSupportedSanitizers;
+
+    for (const char *Value : A->getValues()) {
+      SanitizerMask K = parseSanitizerValue(Value, /*Allow Groups*/ false);
+      if (K & ROCMToolChain::getSupportedSanitizers())
+        SupportedSanitizers.push_back(Value);
+      else
+        UnSupportedSanitizers.push_back(Value);
+    }
+
+    // If there are no supported sanitizers, drop the whole argument.
+    if (SupportedSanitizers.empty()) {
+      if (IsExplicitDevice) {
+        Diags.Report(clang::diag::err_drv_unsupported_option_for_target)
+            << A->getAsString(DAL) << getTriple().str();
+      } else {
+        Diags.Report(clang::diag::warn_drv_unsupported_option_for_target)
+            << A->getAsString(DAL) << getTriple().str();
+      }
+      return true;
+    }
+    // If only some sanitizers are unsupported, report each one individually.
+    if (!UnSupportedSanitizers.empty()) {
+      for (const char *Value : UnSupportedSanitizers) {
+        if (IsExplicitDevice) {
+          Diags.Report(clang::diag::err_drv_unsupported_option_part_for_target)
+              << Value << A->getAsString(DriverArgs) << getTriple().str();
+        } else {
           
Diags.Report(clang::diag::warn_drv_unsupported_option_part_for_target)
-              << Value << A->getAsString(Args) << getTriple().str();
+              << Value << A->getAsString(DriverArgs) << getTriple().str();
+        }
       }
     }
+    // If we know the target arch, check if the sanitizer is supported for it.
+    if (shouldSkipSanitizeOption(TC, DriverArgs, TargetID, A))
+      return true;
+
+    // Add a new argument with only the supported sanitizers.
+    DAL.AddJoinedArg(A, A->getOption(), llvm::join(SupportedSanitizers, ","));
+    return true;
   }
 };
 
diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp 
b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
index 8d59116f3cc13..66ae1fa7b6c34 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -28,8 +28,6 @@ AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D,
   // Lookup binaries into the driver directory, this is used to
   // discover the 'amdgpu-arch' executable.
   getProgramPaths().push_back(getDriver().Dir);
-  // Diagnose unsupported sanitizer options only once.
-  diagnoseUnsupportedSanitizers(Args);
 }
 
 void AMDGPUOpenMPToolChain::addClangTargetOptions(
@@ -66,19 +64,10 @@ llvm::opt::DerivedArgList 
*AMDGPUOpenMPToolChain::TranslateArgs(
 
   const OptTable &Opts = getDriver().getOpts();
 
-  // Skip sanitize options passed from the HostTC. Remove them early.
-  // The decision to sanitize device code is computed only by
-  // 'shouldSkipSanitizeOption'.
-  if (DAL->hasArg(options::OPT_fsanitize_EQ))
-    DAL->eraseArg(options::OPT_fsanitize_EQ);
-
   for (Arg *A : Args) {
-    std::optional<std::string> SupportedSanitizers =
-        filterSanitizeOption(*this, Args, BoundArch, A);
-    if (!SupportedSanitizers)
+    // Filter unsupported sanitizers passed from the HostTC.
+    if (!handleSanitizeOption(*this, *DAL, Args, BoundArch, A))
       DAL->append(A);
-    else if (!SupportedSanitizers->empty())
-      DAL->AddJoinedArg(A, A->getOption(), *SupportedSanitizers);
   }
 
   if (!BoundArch.empty()) {
@@ -119,9 +108,8 @@ void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const 
ArgList &Args,
 SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const {
   // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
   // allows sanitizer arguments on the command line if they are supported by 
the
-  // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command
-  // line arguments for any of these "supported" sanitizers. That means that no
-  // sanitization of device code is actually supported at this time.
+  // host toolchain. The AMDGPUOpenMPToolChain will later filter unsupported
+  // sanitizers from the command line arguments.
   //
   // This behavior is necessary because the host and device toolchains
   // invocations often share the command line, so the device toolchain must
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp 
b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index 648be0ac2db08..d666456881780 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -219,8 +219,6 @@ HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const 
llvm::Triple &Triple,
   // Lookup binaries into the driver directory, this is used to
   // discover the clang-offload-bundler executable.
   getProgramPaths().push_back(getDriver().Dir);
-  // Diagnose unsupported sanitizer options only once.
-  diagnoseUnsupportedSanitizers(Args);
 }
 
 void HIPAMDToolChain::addClangTargetOptions(
@@ -291,19 +289,10 @@ HIPAMDToolChain::TranslateArgs(const 
llvm::opt::DerivedArgList &Args,
 
   const OptTable &Opts = getDriver().getOpts();
 
-  // Skip sanitize options passed from the HostTC. Remove them early.
-  // The decision to sanitize device code is computed only by
-  // 'shouldSkipSanitizeOption'.
-  if (DAL->hasArg(options::OPT_fsanitize_EQ))
-    DAL->eraseArg(options::OPT_fsanitize_EQ);
-
   for (Arg *A : Args) {
-    std::optional<std::string> SupportedSanitizers =
-        filterSanitizeOption(*this, Args, BoundArch, A);
-    if (!SupportedSanitizers)
+    // Filter unsupported sanitizers passed from the HostTC.
+    if (!handleSanitizeOption(*this, *DAL, Args, BoundArch, A))
       DAL->append(A);
-    else if (!SupportedSanitizers->empty())
-      DAL->AddJoinedArg(A, A->getOption(), *SupportedSanitizers);
   }
 
   if (!BoundArch.empty()) {
@@ -358,9 +347,8 @@ void HIPAMDToolChain::AddHIPIncludeArgs(const ArgList 
&DriverArgs,
 SanitizerMask HIPAMDToolChain::getSupportedSanitizers() const {
   // The HIPAMDToolChain only supports sanitizers in the sense that it allows
   // sanitizer arguments on the command line if they are supported by the host
-  // toolchain. The HIPAMDToolChain will actually ignore any command line
-  // arguments for any of these "supported" sanitizers. That means that no
-  // sanitization of device code is actually supported at this time.
+  // toolchain. The HIPAMDToolChain will later filter unsupported sanitizers
+  // from the command line arguments.
   //
   // This behavior is necessary because the host and device toolchains
   // invocations often share the command line, so the device toolchain must
diff --git a/clang/test/Driver/amdgpu-openmp-sanitize-options.c 
b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
index d197db08cc720..b9cd315520d94 100644
--- a/clang/test/Driver/amdgpu-openmp-sanitize-options.c
+++ b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
@@ -57,22 +57,44 @@
 // (The address sanitizer enables the device sanitizer pipeline. The fuzzer
 // implicitly turns on LLVMs SanitizerCoverage, which the driver then forwards
 // to the device cc1. SanitizerCoverage is not supported on amdgcn.)
+
 // RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=address,fuzzer 
--rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION1 %s
 // RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=fuzzer,address 
--rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION2 %s
 
+// Do the same for multiple -fsanitize arguments and multi-arch scenarios.
+
+// RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ --offload-arch=gfx900:xnack- 
-fsanitize=address,fuzzer --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION1 %s
+// RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+,gfx900:xnack- 
-fsanitize=address,fuzzer --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=HOSTSANCOMBINATION,INVALIDCOMBINATION1 %s
+// RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+,gfx900:xnack- 
-fsanitize=fuzzer,address -fsanitize=leak --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck 
-check-prefixes=HOSTSANCOMBINATION2,NOTSUPPORTED-DAG,INVALIDCOMBINATION2 %s
+
+// Test -Xarch_device error scenario
+
+// RUN:   not %clang -no-canonical-prefixes -### 
--target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack+ 
-Xarch_device -fsanitize=leak --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=UNSUPPORTEDERROR %s
+
+// RUN:   not %clang -no-canonical-prefixes -### 
--target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack- 
-Xarch_device -fsanitize=address --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=XNACKERROR %s
+
+// RUN:   not %clang -no-canonical-prefixes -### 
--target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack+ 
-Xarch_device -fsanitize=fuzzer,address --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATIONERROR %s
+
 // INVALIDCOMBINATION1: warning: ignoring 'fuzzer' in 
'-fsanitize=address,fuzzer' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
 // INVALIDCOMBINATION2: warning: ignoring 'fuzzer' in 
'-fsanitize=fuzzer,address' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
 
 // FAIL-DAG: error: cannot find ROCm device library for ABI version 5; provide 
its path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to 
build without ROCm device library
-// NOTSUPPORTED-DAG: warning: ignoring 'leak' in '-fsanitize=leak' option as 
it is not currently supported for target 'amdgcn-amd-amdhsa'
+// NOTSUPPORTED-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa'
 
 // NOXNACK: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx908' as it is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
 // XNACKNEG: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx908:xnack-' as it is not currently supported there. Use it with an offload 
arch containing 'xnack+' instead
 
 // HOSTSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* 
"-fopenmp".* "-fsanitize=address".* "--offload-targets=amdgcn-amd-amdhsa".* 
"-x" "c".*}}
 // HOSTSANCOMBINATION: {{"[^"]*clang[^"]*" "-cc1" "-triple" 
"x86_64-unknown-linux-gnu".* "-fopenmp".* 
"-fsanitize=address,fuzzer,fuzzer-no-link".* 
"--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}}
+// HOSTSANCOMBINATION2: {{"[^"]*clang[^"]*" "-cc1" "-triple" 
"x86_64-unknown-linux-gnu".* "-fopenmp".* 
"-fsanitize=address,fuzzer,fuzzer-no-link,leak".* 
"--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}}
 
 // GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" 
"-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* 
"-mlink-bitcode-file" "[^"]*asanrtl.bc".* "-mlink-bitcode-file" 
"[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900|gfx1250|gfx1251)".* "-fopenmp".* 
"-fsanitize=address".* "-x" "c".*}}
 // NOGPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" 
"-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-target-cpu" 
"(gfx908|gfx900)".* "-fopenmp".* "-x" "c".*}}
@@ -80,3 +102,7 @@
 // SAN: {{"[^"]*llvm-offload-binary[^"]*" "-o".* 
"--image=file=.*.bc,triple=amdgcn-amd-amdhsa,arch=(gfx908|gfx1250|gfx1251)(:xnack\-|:xnack\+)?,kind=openmp(,feature=(\-xnack|\+xnack))?"}}
 // SAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* 
"-fopenmp".* "-fsanitize=address".* "--offload-targets=amdgcn-amd-amdhsa".* 
"-x" "ir".*}}
 // SAN: {{"[^"]*clang-linker-wrapper[^"]*".* 
"--host-triple=x86_64-unknown-linux-gnu".* "--linker-path=[^"]*".* 
"--whole-archive" 
"[^"]*(libclang_rt.asan_static.a|libclang_rt.asan_static-x86_64.a)".* 
"--whole-archive" "[^"]*(libclang_rt.asan.a|libclang_rt.asan-x86_64.a)".*}}
+
+// UNSUPPORTEDERROR: error: '-fsanitize=leak' option is not currently 
supported for target 'amdgcn-amd-amdhsa'
+// XNACKERROR: error: '-fsanitize=address' option for offload arch 
'gfx908:xnack-' is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
+// INVALIDCOMBINATIONERROR: error: 'fuzzer' in '-fsanitize=fuzzer,address' 
option is not currently supported for target 'amdgcn-amd-amdhsa'
diff --git a/clang/test/Driver/hip-sanitize-options.hip 
b/clang/test/Driver/hip-sanitize-options.hip
index 2fce25461ab34..3fc3de9a66ff2 100644
--- a/clang/test/Driver/hip-sanitize-options.hip
+++ b/clang/test/Driver/hip-sanitize-options.hip
@@ -57,6 +57,7 @@
 // (The address sanitizer enables the device sanitizer pipeline. The fuzzer
 // implicitly turns on LLVMs SanitizerCoverage, which the driver then forwards
 // to the device cc1. SanitizerCoverage is not supported on amdgcn.)
+
 // RUN: %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
 // RUN:   -fsanitize=address,fuzzer --rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATION,INVALIDCOMBINATION1 %s
@@ -64,6 +65,29 @@
 // RUN:   -fsanitize=fuzzer,address --rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATION,INVALIDCOMBINATION2 %s
 
+// Do the same for multiple -fsanitize arguments and multi-arch scenarios.
+
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ --offload-arch=gfx908:xnack- \
+// RUN:   -fsanitize=address,fuzzer -fsanitize=leak --rocm-path=%S/Inputs/rocm 
%s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=MULT1,XNACK2 %s
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+,gfx908:xnack- \
+// RUN:   -fsanitize=fuzzer,address -fsanitize=leak --rocm-path=%S/Inputs/rocm 
%s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=MULT2,XNACK2 %s
+
+// Test -Xarch_device error scenario
+
+// RUN:   not %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
+// RUN:   -Xarch_device -fsanitize=leak --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=UNSUPPORTEDERROR %s
+
+// RUN:   not %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack- \
+// RUN:   -Xarch_device -fsanitize=address --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=XNACKERROR %s
+
+// RUN:   not %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
+// RUN:   -Xarch_device -fsanitize=fuzzer,address --rocm-path=%S/Inputs/rocm 
%s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATIONERROR %s
+
 // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-fsanitize=address"}}
 // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-mlink-bitcode-file" 
".*asanrtl.bc"}}
 // CHECK-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}}
@@ -79,7 +103,7 @@
 
 // FAIL: error: cannot find ROCm device library for ABI version 5; provide its 
path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to 
build without ROCm device library
 
-// XNACK-DAG: warning: ignoring 'leak' in '-fsanitize=leak' option as it is 
not currently supported for target 'amdgcn-amd-amdhsa'
+// XNACK-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa'
 // XNACK-DAG: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx900:xnack-' as it is not currently supported there. Use it with an offload 
arch containing 'xnack+' instead
 // XNACK-DAG: warning: ignoring '-fsanitize=address' option for offload arch 
'gfx906' as it is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
 // XNACK-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* 
"-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}}
@@ -118,3 +142,23 @@
 // INVALIDCOMBINATION2-DAG: warning: ignoring 'fuzzer' in 
'-fsanitize=fuzzer,address' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
 // INVALIDCOMBINATION-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" 
".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* 
"-fsanitize=address"}}
 // INVALIDCOMBINATION-DAG: {{"[^"]*clang[^"]*".* "-triple" 
"x86_64-unknown-linux-gnu".* "-fsanitize=address,fuzzer,fuzzer-no-link"}}
+
+// MULT1-DAG: warning: ignoring 'fuzzer' in '-fsanitize=address,fuzzer' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
+// MULT1-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored]
+// MULT1-DAG: warning: ignoring 'fuzzer' in '-fsanitize=address,fuzzer' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
+// MULT1-DAG: warning: ignoring '-fsanitize=address,fuzzer' option for offload 
arch 'gfx908:xnack-' as it is not currently supported there. Use it with an 
offload arch containing 'xnack+' instead [-Woption-ignored]
+// MULT1-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored]
+
+// MULT2-DAG: warning: ignoring 'fuzzer' in '-fsanitize=fuzzer,address' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
+// MULT2-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored]
+// MULT2-DAG: warning: ignoring 'fuzzer' in '-fsanitize=fuzzer,address' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa' 
[-Woption-ignored]
+// MULT2-DAG: warning: ignoring '-fsanitize=fuzzer,address' option for offload 
arch 'gfx908:xnack-' as it is not currently supported there. Use it with an 
offload arch containing 'xnack+' instead [-Woption-ignored]
+// MULT2-DAG: warning: ignoring '-fsanitize=leak' option as it is not 
currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored]
+
+// XNACK2-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* 
"-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}}
+// XNACK2-DAG: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx908"}}
+// XNACK2-DAG: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* 
"-fsanitize=address,fuzzer,fuzzer-no-link,leak"}}
+
+// UNSUPPORTEDERROR: error: '-fsanitize=leak' option is not currently 
supported for target 'amdgcn-amd-amdhsa'
+// XNACKERROR: error: '-fsanitize=address' option for offload arch 
'gfx900:xnack-' is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
+// INVALIDCOMBINATIONERROR: error: 'fuzzer' in '-fsanitize=fuzzer,address' 
option is not currently supported for target 'amdgcn-amd-amdhsa'

>From 53fe7b7d943f600eb9d9fcd8f0a21653de704563 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <[email protected]>
Date: Mon, 17 Nov 2025 06:25:31 -0600
Subject: [PATCH 7/7] add fsan_cov_group

---
 clang/include/clang/Driver/Options.td         | 31 ++++++++--
 clang/lib/Driver/ToolChains/AMDGPU.h          | 57 ++++++++++++-------
 .../Driver/amdgpu-openmp-sanitize-options.c   | 11 ++++
 clang/test/Driver/hip-sanitize-options.hip    | 12 ++++
 4 files changed, 85 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 11e81e032d5fc..4b2f87f5c04d9 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -201,6 +201,10 @@ def hlsl_Group : OptionGroup<"<HLSL group>">, 
Group<f_Group>,
                    DocName<"HLSL options">,
                    Visibility<[ClangOption]>;
 
+def fsan_cov_Group : OptionGroup<"<-fsanitize-coverage group>">,
+                   Group<f_clang_Group>,
+                   DocName<"Sanitizer Coverage options">;
+
 // Feature groups - these take command line options that correspond directly to
 // target specific features and can be translated directly from command line
 // options.
@@ -2407,26 +2411,26 @@ def : Flag<["-"], "fno-sanitize-blacklist">,
   Group<f_clang_Group>, Flags<[HelpHidden]>, Alias<fno_sanitize_ignorelist>;
 
 def fsanitize_coverage : CommaJoined<["-"], "fsanitize-coverage=">,
-  Group<f_clang_Group>,
+  Group<fsan_cov_Group>,
   HelpText<"Specify the type of coverage instrumentation for Sanitizers">;
 def fno_sanitize_coverage : CommaJoined<["-"], "fno-sanitize-coverage=">,
-  Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>,
+  Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
   HelpText<"Disable features of coverage instrumentation for Sanitizers">,
   Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,"
          "8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters,"
          "inline-bool-flag">;
 def fsanitize_coverage_allowlist : Joined<["-"], 
"fsanitize-coverage-allowlist=">,
-    Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>,
+    Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
     HelpText<"Restrict sanitizer coverage instrumentation exclusively to 
modules and functions that match the provided special case list, except the 
blocked ones">,
     MarshallingInfoStringVector<CodeGenOpts<"SanitizeCoverageAllowlistFiles">>;
 def fsanitize_coverage_ignorelist : Joined<["-"], 
"fsanitize-coverage-ignorelist=">,
-    Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>,
+    Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
     HelpText<"Disable sanitizer coverage instrumentation for modules and 
functions "
              "that match the provided special case list, even the allowed 
ones">,
     
MarshallingInfoStringVector<CodeGenOpts<"SanitizeCoverageIgnorelistFiles">>;
 def fsanitize_coverage_stack_depth_callback_min_EQ
     : Joined<["-"], "fsanitize-coverage-stack-depth-callback-min=">,
-      Group<f_clang_Group>,
+      Group<fsan_cov_Group>,
       MetaVarName<"<M>">,
       HelpText<"Use callback for max stack depth tracing with minimum stack "
                "depth M">,
@@ -7898,70 +7902,87 @@ def linker_option : Joined<["--"], "linker-option=">,
   HelpText<"Add linker option">,
   MarshallingInfoStringVector<CodeGenOpts<"LinkerOptions">>;
 def fsanitize_coverage_type : Joined<["-"], "fsanitize-coverage-type=">,
+                              Group<fsan_cov_Group>,
                               HelpText<"Sanitizer coverage type">,
                               
MarshallingInfoInt<CodeGenOpts<"SanitizeCoverageType">>;
 def fsanitize_coverage_indirect_calls
     : Flag<["-"], "fsanitize-coverage-indirect-calls">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable sanitizer coverage for indirect calls">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageIndirectCalls">>;
 def fsanitize_coverage_trace_bb
     : Flag<["-"], "fsanitize-coverage-trace-bb">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable basic block tracing in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceBB">>;
 def fsanitize_coverage_trace_cmp
     : Flag<["-"], "fsanitize-coverage-trace-cmp">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable cmp instruction tracing in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceCmp">>;
 def fsanitize_coverage_trace_div
     : Flag<["-"], "fsanitize-coverage-trace-div">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable div instruction tracing in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceDiv">>;
 def fsanitize_coverage_trace_gep
     : Flag<["-"], "fsanitize-coverage-trace-gep">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable gep instruction tracing in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceGep">>;
 def fsanitize_coverage_8bit_counters
     : Flag<["-"], "fsanitize-coverage-8bit-counters">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable frequency counters in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverage8bitCounters">>;
 def fsanitize_coverage_inline_8bit_counters
     : Flag<["-"], "fsanitize-coverage-inline-8bit-counters">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable inline 8-bit counters in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageInline8bitCounters">>;
 def fsanitize_coverage_inline_bool_flag
     : Flag<["-"], "fsanitize-coverage-inline-bool-flag">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable inline bool flag in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageInlineBoolFlag">>;
 def fsanitize_coverage_pc_table
     : Flag<["-"], "fsanitize-coverage-pc-table">,
+      Group<fsan_cov_Group>,
       HelpText<"Create a table of coverage-instrumented PCs">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoveragePCTable">>;
 def fsanitize_coverage_control_flow
     : Flag<["-"], "fsanitize-coverage-control-flow">,
+      Group<fsan_cov_Group>,
       HelpText<"Collect control flow of function">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageControlFlow">>;
 def fsanitize_coverage_trace_pc
     : Flag<["-"], "fsanitize-coverage-trace-pc">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable PC tracing in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTracePC">>;
 def fsanitize_coverage_trace_pc_guard
     : Flag<["-"], "fsanitize-coverage-trace-pc-guard">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable PC tracing with guard in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTracePCGuard">>;
 def fsanitize_coverage_no_prune
     : Flag<["-"], "fsanitize-coverage-no-prune">,
+      Group<fsan_cov_Group>,
       HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageNoPrune">>;
 def fsanitize_coverage_stack_depth
     : Flag<["-"], "fsanitize-coverage-stack-depth">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable max stack depth tracing">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageStackDepth">>;
 def fsanitize_coverage_trace_loads
     : Flag<["-"], "fsanitize-coverage-trace-loads">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable tracing of loads">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceLoads">>;
 def fsanitize_coverage_trace_stores
     : Flag<["-"], "fsanitize-coverage-trace-stores">,
+      Group<fsan_cov_Group>,
       HelpText<"Enable tracing of stores">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceStores">>;
 def fexperimental_sanitize_metadata_EQ_covered
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h 
b/clang/lib/Driver/ToolChains/AMDGPU.h
index 5614b72a872ce..fb4b918c44aab 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -155,22 +155,49 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public 
AMDGPUToolChain {
     return SanitizerKind::Address;
   }
 
+  bool diagnoseUnsupportedOption(const llvm::opt::Arg *A,
+                                 const llvm::opt::DerivedArgList &DAL,
+                                 const llvm::opt::ArgList &DriverArgs,
+                                 const char *Value = nullptr) const {
+    auto &Diags = getDriver().getDiags();
+    bool IsExplicitDevice =
+        A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
+
+    if (Value) {
+      unsigned DiagID =
+          IsExplicitDevice
+              ? clang::diag::err_drv_unsupported_option_part_for_target
+              : clang::diag::warn_drv_unsupported_option_part_for_target;
+      Diags.Report(DiagID) << Value << A->getAsString(DriverArgs)
+                           << getTriple().str();
+    } else {
+      unsigned DiagID =
+          IsExplicitDevice
+              ? clang::diag::err_drv_unsupported_option_for_target
+              : clang::diag::warn_drv_unsupported_option_for_target;
+      Diags.Report(DiagID) << A->getAsString(DAL) << getTriple().str();
+    }
+    return true;
+  }
+
   bool handleSanitizeOption(const ToolChain &TC, llvm::opt::DerivedArgList 
&DAL,
                             const llvm::opt::ArgList &DriverArgs,
                             StringRef TargetID, const llvm::opt::Arg *A) const 
{
     if (TargetID.empty())
       return false;
-    // If this isn't a sanitizer option, don't handle it.
-    if (!A->getOption().matches(options::OPT_fsanitize_EQ))
-      return false;
     // If we shouldn't do sanitizing, skip it.
     if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
                             options::OPT_fno_gpu_sanitize, true))
       return true;
-
-    auto &Diags = getDriver().getDiags();
-    bool IsExplicitDevice =
-        A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
+    const llvm::opt::Option &Opt = A->getOption();
+    // Sanitizer coverage is currently not supported for AMDGPU, so warn/error
+    // on every related option.
+    if (Opt.matches(options::OPT_fsan_cov_Group)) {
+      diagnoseUnsupportedOption(A, DAL, DriverArgs);
+    }
+    // If this isn't a sanitizer option, don't handle it.
+    if (!Opt.matches(options::OPT_fsanitize_EQ))
+      return false;
 
     SmallVector<const char *, 4> SupportedSanitizers;
     SmallVector<const char *, 4> UnSupportedSanitizers;
@@ -185,25 +212,13 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public 
AMDGPUToolChain {
 
     // If there are no supported sanitizers, drop the whole argument.
     if (SupportedSanitizers.empty()) {
-      if (IsExplicitDevice) {
-        Diags.Report(clang::diag::err_drv_unsupported_option_for_target)
-            << A->getAsString(DAL) << getTriple().str();
-      } else {
-        Diags.Report(clang::diag::warn_drv_unsupported_option_for_target)
-            << A->getAsString(DAL) << getTriple().str();
-      }
+      diagnoseUnsupportedOption(A, DAL, DriverArgs);
       return true;
     }
     // If only some sanitizers are unsupported, report each one individually.
     if (!UnSupportedSanitizers.empty()) {
       for (const char *Value : UnSupportedSanitizers) {
-        if (IsExplicitDevice) {
-          Diags.Report(clang::diag::err_drv_unsupported_option_part_for_target)
-              << Value << A->getAsString(DriverArgs) << getTriple().str();
-        } else {
-          
Diags.Report(clang::diag::warn_drv_unsupported_option_part_for_target)
-              << Value << A->getAsString(DriverArgs) << getTriple().str();
-        }
+        diagnoseUnsupportedOption(A, DAL, DriverArgs, Value);
       }
     }
     // If we know the target arch, check if the sanitizer is supported for it.
diff --git a/clang/test/Driver/amdgpu-openmp-sanitize-options.c 
b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
index b9cd315520d94..fd7d11803249c 100644
--- a/clang/test/Driver/amdgpu-openmp-sanitize-options.c
+++ b/clang/test/Driver/amdgpu-openmp-sanitize-options.c
@@ -72,6 +72,10 @@
 // RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+,gfx900:xnack- 
-fsanitize=fuzzer,address -fsanitize=leak --rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck 
-check-prefixes=HOSTSANCOMBINATION2,NOTSUPPORTED-DAG,INVALIDCOMBINATION2 %s
 
+// Check for -fsanitize-coverage options
+// RUN:   %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu 
-fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=address 
-fsanitize-coverage=inline-bool-flag --rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=WARNSANCOV %s
+
 // Test -Xarch_device error scenario
 
 // RUN:   not %clang -no-canonical-prefixes -### 
--target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack+ 
-Xarch_device -fsanitize=leak --rocm-path=%S/Inputs/rocm %s 2>&1 \
@@ -83,6 +87,10 @@
 // RUN:   not %clang -no-canonical-prefixes -### 
--target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack+ 
-Xarch_device -fsanitize=fuzzer,address --rocm-path=%S/Inputs/rocm %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATIONERROR %s
 
+// RUN:   not %clang -no-canonical-prefixes -### 
--target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack+ 
-fsanitize=address -Xarch_device 
-fsanitize-coverage-stack-depth-callback-min=42 --rocm-path=%S/Inputs/rocm %s 
2>&1 \
+// RUN:   | FileCheck -check-prefixes=ERRSANCOV %s
+
+
 // INVALIDCOMBINATION1: warning: ignoring 'fuzzer' in 
'-fsanitize=address,fuzzer' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
 // INVALIDCOMBINATION2: warning: ignoring 'fuzzer' in 
'-fsanitize=fuzzer,address' option as it is not currently supported for target 
'amdgcn-amd-amdhsa' [-Woption-ignored]
 
@@ -106,3 +114,6 @@
 // UNSUPPORTEDERROR: error: '-fsanitize=leak' option is not currently 
supported for target 'amdgcn-amd-amdhsa'
 // XNACKERROR: error: '-fsanitize=address' option for offload arch 
'gfx908:xnack-' is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
 // INVALIDCOMBINATIONERROR: error: 'fuzzer' in '-fsanitize=fuzzer,address' 
option is not currently supported for target 'amdgcn-amd-amdhsa'
+
+// WARNSANCOV: warning: ignoring '-fsanitize-coverage=inline-bool-flag' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa'
+// ERRSANCOV: error: '-fsanitize-coverage-stack-depth-callback-min=42' option 
is not currently supported for target 'amdgcn-amd-amdhsa'
diff --git a/clang/test/Driver/hip-sanitize-options.hip 
b/clang/test/Driver/hip-sanitize-options.hip
index 3fc3de9a66ff2..d436756ee046b 100644
--- a/clang/test/Driver/hip-sanitize-options.hip
+++ b/clang/test/Driver/hip-sanitize-options.hip
@@ -74,6 +74,11 @@
 // RUN:   -fsanitize=fuzzer,address -fsanitize=leak --rocm-path=%S/Inputs/rocm 
%s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=MULT2,XNACK2 %s
 
+// Check for -fsanitize-coverage options
+// RUN:   %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
+// RUN:   -fsanitize=address -fsanitize-coverage=inline-bool-flag 
--rocm-path=%S/Inputs/rocm %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=WARNSANCOV %s
+
 // Test -Xarch_device error scenario
 
 // RUN:   not %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
@@ -88,6 +93,10 @@
 // RUN:   -Xarch_device -fsanitize=fuzzer,address --rocm-path=%S/Inputs/rocm 
%s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=INVALIDCOMBINATIONERROR %s
 
+// RUN:   not %clang -### --target=x86_64-unknown-linux-gnu 
--offload-arch=gfx900:xnack+ \
+// RUN:   -fsanitize=address -Xarch_device 
-fsanitize-coverage-stack-depth-callback-min=42 --rocm-path=%S/Inputs/rocm %s 
2>&1 \
+// RUN:   | FileCheck -check-prefixes=ERRSANCOV %s
+
 // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-fsanitize=address"}}
 // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-mlink-bitcode-file" 
".*asanrtl.bc"}}
 // CHECK-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}}
@@ -162,3 +171,6 @@
 // UNSUPPORTEDERROR: error: '-fsanitize=leak' option is not currently 
supported for target 'amdgcn-amd-amdhsa'
 // XNACKERROR: error: '-fsanitize=address' option for offload arch 
'gfx900:xnack-' is not currently supported there. Use it with an offload arch 
containing 'xnack+' instead
 // INVALIDCOMBINATIONERROR: error: 'fuzzer' in '-fsanitize=fuzzer,address' 
option is not currently supported for target 'amdgcn-amd-amdhsa'
+
+// WARNSANCOV: warning: ignoring '-fsanitize-coverage=inline-bool-flag' option 
as it is not currently supported for target 'amdgcn-amd-amdhsa'
+// ERRSANCOV: error: '-fsanitize-coverage-stack-depth-callback-min=42' option 
is not currently supported for target 'amdgcn-amd-amdhsa'

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to