[llvm-branch-commits] [clang] [Clang] Enable UBSan for AMDGPU device offload (PR #219973)
Joseph Huber via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Sep 14 05:38:33 PDT 2026
https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/219973
>From ec054db1345edf3d5da8ec2631db1b29641df80a Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Sat, 29 Aug 2026 11:19:57 -0500
Subject: [PATCH 1/6] [Clang] Enable UBSan for AMDGPU device offload
Summary:
This enables the device UBSan runtime for AMDGPU decides. Primarily this
required modifications to the `addSanitizerRuntime` interface so we can
query the compilation's offload status. Also need to forward it through
the linker wrapper interface. Works on all AMDGPU offload, slight hacks
around the other targets as they do not advertise sanitizer
runtimes properly.
This is linked in via a new `-u __ubsan_device_initialize` hook to pull
in the side library. This is standard behavior and keeps the core logic
mostly unchanged and re-used.
---
clang/include/clang/Driver/CommonArgs.h | 2 +-
clang/lib/Driver/ToolChains/AMDGPU.cpp | 2 +-
clang/lib/Driver/ToolChains/Clang.cpp | 3 +-
clang/lib/Driver/ToolChains/CommonArgs.cpp | 35 +++++++++++--
clang/lib/Driver/ToolChains/Cuda.cpp | 2 +-
clang/lib/Driver/ToolChains/Cygwin.cpp | 2 +-
clang/lib/Driver/ToolChains/FreeBSD.cpp | 2 +-
clang/lib/Driver/ToolChains/Fuchsia.cpp | 2 +-
clang/lib/Driver/ToolChains/Gnu.cpp | 2 +-
clang/lib/Driver/ToolChains/Haiku.cpp | 2 +-
clang/lib/Driver/ToolChains/Hexagon.cpp | 4 +-
clang/lib/Driver/ToolChains/NetBSD.cpp | 2 +-
clang/lib/Driver/ToolChains/OpenBSD.cpp | 2 +-
clang/lib/Driver/ToolChains/Solaris.cpp | 2 +-
clang/lib/Driver/ToolChains/UEFI.cpp | 2 +-
.../libclang_rt.ubsan_standalone.a | 0
.../libclang_rt.ubsan_device.a | 0
.../libclang_rt.ubsan_standalone.a | 0
.../fsanitize-undefined-device-offload.c | 50 +++++++++++++++++++
19 files changed, 98 insertions(+), 18 deletions(-)
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/amdgpu-amd-amdhsa/libclang_rt.ubsan_standalone.a
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_device.a
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone.a
create mode 100644 clang/test/Driver/fsanitize-undefined-device-offload.c
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index f631cdbd23d03e..6ba7657e283b8d 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -57,7 +57,7 @@ void renderDebugInfoCompressionArgs(const llvm::opt::ArgList &Args,
void claimNoWarnArgs(const llvm::opt::ArgList &Args);
bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs);
+ llvm::opt::ArgStringList &CmdArgs, Compilation &C);
void linkSanitizerRuntimeDeps(const ToolChain &TC,
const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 6bc6a537328817..d6dacb4ccba839 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -667,7 +667,7 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
getToolChain().addProfileRTLibs(Args, CmdArgs);
- addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
+ addSanitizerRuntimes(getToolChain(), Args, CmdArgs, C);
if (Args.hasArg(options::OPT_stdlib))
CmdArgs.append({"-lc", "-lm"});
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index ab852bf0e0043d..7923d72ae2d402 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -9799,7 +9799,8 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
return false;
// Don't forward sanitizer arguments if the toolchain doesn't support it.
// Without this check using it on the host would result in linker errors.
- if (requiresUBSanRT(ID) && !ToolChainHasRT(TC, "ubsan_minimal"))
+ if (requiresUBSanRT(ID) && !ToolChainHasRT(TC, "ubsan_minimal") &&
+ !ToolChainHasRT(TC, "ubsan_standalone"))
return false;
// Don't forward -mllvm to toolchains that don't support LLVM.
return TC.HasNativeLLVMSupport() || ID != OPT_mllvm;
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 64859a318485b3..a7faac5c2c8da0 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1669,8 +1669,33 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
CmdArgs.push_back("-lresolv");
}
+// Host interceptor library for UBSan on the device. Enabled if we are
+// offloading to a target that supports UBSan.
+static bool hostNeedsUbsanDeviceRt(Compilation &C, const ToolChain &HostTC) {
+ if (HostTC.getTriple().isGPU())
+ return false;
+
+ static constexpr Action::OffloadKind Kinds[] = {
+ Action::OFK_Cuda, Action::OFK_OpenMP, Action::OFK_HIP, Action::OFK_SYCL};
+ for (Action::OffloadKind Kind : Kinds) {
+ for (const auto &Entry : llvm::make_range(C.getOffloadToolChains(Kind))) {
+ const ToolChain *DevTC = Entry.second;
+ // FIXME: CUDA/HIPSPV copy the host mask and ignore device sanitizers.
+ if (DevTC->getTriple().isNVPTX() || DevTC->getTriple().isSPIROrSPIRV())
+ continue;
+
+ const ArgList &DevArgs = C.getArgsForToolChain(DevTC, {}, Kind);
+ SanitizerArgs DevSan = DevTC->getSanitizerArgs(DevArgs, {}, Kind);
+ if (DevSan.needsUbsanRt() && !DevSan.requiresMinimalRuntime())
+ return true;
+ }
+ }
+ return false;
+}
+
static void
-collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
+collectSanitizerRuntimes(Compilation &C, const ToolChain &TC,
+ const ArgList &Args,
SmallVectorImpl<StringRef> &SharedRuntimes,
SmallVectorImpl<StringRef> &StaticRuntimes,
SmallVectorImpl<StringRef> &NonWholeStaticRuntimes,
@@ -1812,17 +1837,21 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
}
if (SanArgs.needsUbsanLoopDetectRt())
NonWholeStaticRuntimes.push_back("ubsan_loop_detect");
+ if (hostNeedsUbsanDeviceRt(C, TC)) {
+ NonWholeStaticRuntimes.push_back("ubsan_device");
+ RequiredSymbols.push_back("__ubsan_device_init");
+ }
}
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
// C runtime, etc). Returns true if sanitizer system deps need to be linked in.
bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs, Compilation &C) {
const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols;
if (SanArgs.linkRuntimes()) {
- collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
+ collectSanitizerRuntimes(C, TC, Args, SharedRuntimes, StaticRuntimes,
NonWholeStaticRuntimes, HelperStaticRuntimes,
RequiredSymbols);
}
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 3e33871eb66189..096a7429dac027 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -670,7 +670,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Twine("-L") + DefaultLibPath));
getToolChain().addProfileRTLibs(Args, CmdArgs);
- addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
+ addSanitizerRuntimes(getToolChain(), Args, CmdArgs, C);
if (Args.hasArg(options::OPT_stdlib))
CmdArgs.append({"-lc", "-lm"});
diff --git a/clang/lib/Driver/ToolChains/Cygwin.cpp b/clang/lib/Driver/ToolChains/Cygwin.cpp
index f4854e9c6ce642..fa4e0ce686c7c1 100644
--- a/clang/lib/Driver/ToolChains/Cygwin.cpp
+++ b/clang/lib/Driver/ToolChains/Cygwin.cpp
@@ -283,7 +283,7 @@ void cygwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--disable-nxcompat");
bool NeedsSanitizerDeps =
- tools::addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ tools::addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
bool NeedsXRayDeps = tools::addXRayRuntime(ToolChain, Args, CmdArgs);
tools::addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
tools::AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index dcf2973c364d16..273cb3bb89607b 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -275,7 +275,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None)
addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 028d94b3fa1033..3b5729b45e7e8e 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -173,7 +173,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Note that Fuchsia never needs to link in sanitizer runtime deps. Any
// sanitizer runtimes with system dependencies use the `.deplibs` feature
// instead.
- addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
addXRayRuntime(ToolChain, Args, CmdArgs);
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 5285f558977321..fb1a6dc09d1fc3 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -445,7 +445,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp
index a155f22b75a796..36b07f888cc66c 100644
--- a/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -90,7 +90,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None)
addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 76c5cafd77bc9c..933b9f2ea5412d 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -218,7 +218,7 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
"-mcpu=hexagon" +
toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
- addSanitizerRuntimes(HTC, Args, CmdArgs);
+ addSanitizerRuntimes(HTC, Args, CmdArgs, C);
assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
@@ -304,7 +304,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
bool UseShared = IsShared && !IsStatic;
StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs, C);
bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);
//----------------------------------------------------------------------------
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index f03114b53bb616..dd53606351b24c 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -274,7 +274,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_s, options::OPT_t});
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index de5284ddf6e605..03bd56e5f4e459 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -206,7 +206,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None)
addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index e5f1cbb033c3b0..8eafe18a1eb309 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -202,7 +202,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group});
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs, C);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
diff --git a/clang/lib/Driver/ToolChains/UEFI.cpp b/clang/lib/Driver/ToolChains/UEFI.cpp
index e26403ebe90303..6e93f7c4be193e 100644
--- a/clang/lib/Driver/ToolChains/UEFI.cpp
+++ b/clang/lib/Driver/ToolChains/UEFI.cpp
@@ -90,7 +90,7 @@ void tools::uefi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool NoLibc = Args.hasArg(options::OPT_nolibc);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
options::OPT_r)) {
- addSanitizerRuntimes(TC, Args, CmdArgs);
+ addSanitizerRuntimes(TC, Args, CmdArgs, C);
addXRayRuntime(TC, Args, CmdArgs);
diff --git a/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/amdgpu-amd-amdhsa/libclang_rt.ubsan_standalone.a b/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/amdgpu-amd-amdhsa/libclang_rt.ubsan_standalone.a
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_device.a b/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_device.a
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone.a b/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone.a
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/clang/test/Driver/fsanitize-undefined-device-offload.c b/clang/test/Driver/fsanitize-undefined-device-offload.c
new file mode 100644
index 00000000000000..36772e4606b7d7
--- /dev/null
+++ b/clang/test/Driver/fsanitize-undefined-device-offload.c
@@ -0,0 +1,50 @@
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -fopenmp=libomp --offload-arch=gfx908 -fsanitize=undefined -nogpuinc \
+// RUN: --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-OPENMP
+// CHECK-OPENMP-DAG: "--device-compiler=amdgpu-amd-amdhsa=-fsanitize=undefined"
+// CHECK-OPENMP-DAG: "-u" "__ubsan_device_init"
+// CHECK-OPENMP-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_device.a"
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -fsanitize=undefined -nogpuinc -nogpulib \
+// RUN: --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-HIP-HOST
+// CHECK-HIP-HOST-DAG: "-u" "__ubsan_device_init"
+// CHECK-HIP-HOST-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_device.a"
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -Xarch_device -fsanitize=undefined \
+// RUN: -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-DEV
+// CHECK-XARCH-DEV-DAG: "-u" "__ubsan_device_init"
+// CHECK-XARCH-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_device.a"
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -Xarch_host -fsanitize=undefined \
+// RUN: -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-HOST
+// CHECK-XARCH-HOST-NOT: ubsan_device
+// CHECK-XARCH-HOST-NOT: __ubsan_device_init
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -fsanitize=undefined \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-HOST
+// CHECK-HOST-NOT: ubsan_device
+// CHECK-HOST-NOT: __ubsan_device_init
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -fsanitize=undefined \
+// RUN: -fsanitize-minimal-runtime -nogpuinc -nogpulib \
+// RUN: --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-MINIMAL
+// CHECK-MINIMAL-NOT: ubsan_device
+// CHECK-MINIMAL-NOT: __ubsan_device_init
+
+int main(void) { return 0; }
>From 92431b3611d6655d61c0ee7cbe59deec26364cf8 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Mon, 31 Aug 2026 16:45:45 -0500
Subject: [PATCH 2/6] [Clang] Link libclang_rt.ubsan_offload.a for device
offload
Match the compiler-rt rename of the host interceptor and the
-u __ubsan_offload_init hook.
---
clang/lib/Driver/ToolChains/CommonArgs.cpp | 10 ++++----
...n_device.a => libclang_rt.ubsan_offload.a} | 0
...ffload.c => fsanitize-undefined-offload.c} | 24 +++++++++----------
3 files changed, 17 insertions(+), 17 deletions(-)
rename clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/{libclang_rt.ubsan_device.a => libclang_rt.ubsan_offload.a} (100%)
rename clang/test/Driver/{fsanitize-undefined-device-offload.c => fsanitize-undefined-offload.c} (83%)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index a7faac5c2c8da0..c3b6fbaaf2bd14 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1669,9 +1669,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
CmdArgs.push_back("-lresolv");
}
-// Host interceptor library for UBSan on the device. Enabled if we are
+// Host interceptor library for offload UBSan. Enabled if we are
// offloading to a target that supports UBSan.
-static bool hostNeedsUbsanDeviceRt(Compilation &C, const ToolChain &HostTC) {
+static bool hostNeedsUbsanOffloadRt(Compilation &C, const ToolChain &HostTC) {
if (HostTC.getTriple().isGPU())
return false;
@@ -1837,9 +1837,9 @@ collectSanitizerRuntimes(Compilation &C, const ToolChain &TC,
}
if (SanArgs.needsUbsanLoopDetectRt())
NonWholeStaticRuntimes.push_back("ubsan_loop_detect");
- if (hostNeedsUbsanDeviceRt(C, TC)) {
- NonWholeStaticRuntimes.push_back("ubsan_device");
- RequiredSymbols.push_back("__ubsan_device_init");
+ if (hostNeedsUbsanOffloadRt(C, TC)) {
+ NonWholeStaticRuntimes.push_back("ubsan_offload");
+ RequiredSymbols.push_back("__ubsan_offload_init");
}
}
diff --git a/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_device.a b/clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_offload.a
similarity index 100%
rename from clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_device.a
rename to clang/test/Driver/Inputs/resource_dir_with_amdgpu_per_target_subdir/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_offload.a
diff --git a/clang/test/Driver/fsanitize-undefined-device-offload.c b/clang/test/Driver/fsanitize-undefined-offload.c
similarity index 83%
rename from clang/test/Driver/fsanitize-undefined-device-offload.c
rename to clang/test/Driver/fsanitize-undefined-offload.c
index 36772e4606b7d7..49f8b8d506bf28 100644
--- a/clang/test/Driver/fsanitize-undefined-device-offload.c
+++ b/clang/test/Driver/fsanitize-undefined-offload.c
@@ -4,39 +4,39 @@
// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-OPENMP
// CHECK-OPENMP-DAG: "--device-compiler=amdgpu-amd-amdhsa=-fsanitize=undefined"
-// CHECK-OPENMP-DAG: "-u" "__ubsan_device_init"
-// CHECK-OPENMP-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_device.a"
+// CHECK-OPENMP-DAG: "-u" "__ubsan_offload_init"
+// CHECK-OPENMP-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 -fsanitize=undefined -nogpuinc -nogpulib \
// RUN: --rocm-path=%S/Inputs/rocm \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-HIP-HOST
-// CHECK-HIP-HOST-DAG: "-u" "__ubsan_device_init"
-// CHECK-HIP-HOST-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_device.a"
+// CHECK-HIP-HOST-DAG: "-u" "__ubsan_offload_init"
+// CHECK-HIP-HOST-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 -Xarch_device -fsanitize=undefined \
// RUN: -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-DEV
-// CHECK-XARCH-DEV-DAG: "-u" "__ubsan_device_init"
-// CHECK-XARCH-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_device.a"
+// CHECK-XARCH-DEV-DAG: "-u" "__ubsan_offload_init"
+// CHECK-XARCH-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 -Xarch_host -fsanitize=undefined \
// RUN: -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-HOST
-// CHECK-XARCH-HOST-NOT: ubsan_device
-// CHECK-XARCH-HOST-NOT: __ubsan_device_init
+// CHECK-XARCH-HOST-NOT: ubsan_offload
+// CHECK-XARCH-HOST-NOT: __ubsan_offload_init
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -fsanitize=undefined \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-HOST
-// CHECK-HOST-NOT: ubsan_device
-// CHECK-HOST-NOT: __ubsan_device_init
+// CHECK-HOST-NOT: ubsan_offload
+// CHECK-HOST-NOT: __ubsan_offload_init
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 -fsanitize=undefined \
@@ -44,7 +44,7 @@
// RUN: --rocm-path=%S/Inputs/rocm \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-MINIMAL
-// CHECK-MINIMAL-NOT: ubsan_device
-// CHECK-MINIMAL-NOT: __ubsan_device_init
+// CHECK-MINIMAL-NOT: ubsan_offload
+// CHECK-MINIMAL-NOT: __ubsan_offload_init
int main(void) { return 0; }
>From d6de64e32d8564f0e2cf617ba11392d229025bf8 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Mon, 31 Aug 2026 17:45:41 -0500
Subject: [PATCH 3/6] Device only and -shared fix
---
clang/lib/Driver/ToolChains/CommonArgs.cpp | 24 ++++++++++-------
.../test/Driver/fsanitize-undefined-offload.c | 26 +++++++++++++++++++
2 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index c3b6fbaaf2bd14..e4865d4c3a8c82 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1669,8 +1669,7 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
CmdArgs.push_back("-lresolv");
}
-// Host interceptor library for offload UBSan. Enabled if we are
-// offloading to a target that supports UBSan.
+// Host interceptor library for offload UBSan.
static bool hostNeedsUbsanOffloadRt(Compilation &C, const ToolChain &HostTC) {
if (HostTC.getTriple().isGPU())
return false;
@@ -1681,7 +1680,8 @@ static bool hostNeedsUbsanOffloadRt(Compilation &C, const ToolChain &HostTC) {
for (const auto &Entry : llvm::make_range(C.getOffloadToolChains(Kind))) {
const ToolChain *DevTC = Entry.second;
// FIXME: CUDA/HIPSPV copy the host mask and ignore device sanitizers.
- if (DevTC->getTriple().isNVPTX() || DevTC->getTriple().isSPIROrSPIRV())
+ const llvm::Triple &TT = DevTC->getTriple();
+ if (!TT.isAMDGCN() || TT.getOS() != llvm::Triple::AMDHSA)
continue;
const ArgList &DevArgs = C.getArgsForToolChain(DevTC, {}, Kind);
@@ -1703,6 +1703,8 @@ collectSanitizerRuntimes(Compilation &C, const ToolChain &TC,
SmallVectorImpl<StringRef> &RequiredSymbols) {
assert(!TC.getTriple().isOSDarwin() && "it's not used by Darwin");
const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
+ const bool NeedsOffloadRt = hostNeedsUbsanOffloadRt(C, TC);
+ const bool NeedsUbsanRt = SanArgs.needsUbsanRt() || NeedsOffloadRt;
// Collect shared runtimes.
if (SanArgs.needsSharedRt()) {
if (SanArgs.needsAsanRt()) {
@@ -1717,7 +1719,7 @@ collectSanitizerRuntimes(Compilation &C, const ToolChain &TC,
}
if (SanArgs.needsNsanRt())
SharedRuntimes.push_back("nsan");
- if (SanArgs.needsUbsanRt()) {
+ if (NeedsUbsanRt) {
if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("ubsan_minimal");
else
@@ -1750,9 +1752,17 @@ collectSanitizerRuntimes(Compilation &C, const ToolChain &TC,
if (SanArgs.needsAsanRt())
HelperStaticRuntimes.push_back("asan_static");
+ // Offloading images can live in DSOs, the host interceptors must follow.
+ if (NeedsOffloadRt) {
+ NonWholeStaticRuntimes.push_back("ubsan_offload");
+ RequiredSymbols.push_back("__ubsan_offload_init");
+ }
+
// Collect static runtimes.
if (Args.hasArg(options::OPT_shared)) {
// Don't link static runtimes into DSOs.
+ if (NeedsOffloadRt && !SanArgs.needsSharedRt() && !SanArgs.needsUbsanRt())
+ StaticRuntimes.push_back("ubsan_standalone");
return;
}
@@ -1804,7 +1814,7 @@ collectSanitizerRuntimes(Compilation &C, const ToolChain &TC,
}
if (!SanArgs.needsSharedRt() && SanArgs.needsTysanRt())
StaticRuntimes.push_back("tysan");
- if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) {
+ if (!SanArgs.needsSharedRt() && NeedsUbsanRt) {
if (SanArgs.requiresMinimalRuntime()) {
StaticRuntimes.push_back("ubsan_minimal");
} else {
@@ -1837,10 +1847,6 @@ collectSanitizerRuntimes(Compilation &C, const ToolChain &TC,
}
if (SanArgs.needsUbsanLoopDetectRt())
NonWholeStaticRuntimes.push_back("ubsan_loop_detect");
- if (hostNeedsUbsanOffloadRt(C, TC)) {
- NonWholeStaticRuntimes.push_back("ubsan_offload");
- RequiredSymbols.push_back("__ubsan_offload_init");
- }
}
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
diff --git a/clang/test/Driver/fsanitize-undefined-offload.c b/clang/test/Driver/fsanitize-undefined-offload.c
index 49f8b8d506bf28..bed6cbbd58972b 100644
--- a/clang/test/Driver/fsanitize-undefined-offload.c
+++ b/clang/test/Driver/fsanitize-undefined-offload.c
@@ -22,6 +22,7 @@
// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-DEV
// CHECK-XARCH-DEV-DAG: "-u" "__ubsan_offload_init"
// CHECK-XARCH-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
+// CHECK-XARCH-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_standalone.a"
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 -Xarch_host -fsanitize=undefined \
@@ -47,4 +48,29 @@
// CHECK-MINIMAL-NOT: ubsan_offload
// CHECK-MINIMAL-NOT: __ubsan_offload_init
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -Xarch_device -fsanitize=undefined \
+// RUN: -fPIC -shared -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-SHARED-DEV
+// CHECK-SHARED-DEV-DAG: "-u" "__ubsan_offload_init"
+// CHECK-SHARED-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
+// CHECK-SHARED-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_standalone.a"
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -fsanitize=undefined \
+// RUN: -fPIC -shared -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-SHARED
+// CHECK-SHARED-DAG: "-u" "__ubsan_offload_init"
+// CHECK-SHARED-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -fopenmp=libomp -fopenmp-targets=x86_64-unknown-linux-gnu \
+// RUN: -fsanitize=undefined \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-OMP-CPU
+// CHECK-OMP-CPU-NOT: ubsan_offload
+// CHECK-OMP-CPU-NOT: __ubsan_offload_init
+
int main(void) { return 0; }
>From 038af69d99bdc97e4b804432f348320b8b13b68e Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Mon, 31 Aug 2026 20:46:03 -0500
Subject: [PATCH 4/6] [Clang] Honor -Xarch_gfx* when linking the UBSan offload
runtime
Empty bound architecture misses per-GPU sanitizer flags, so inspect each
offload arch when deciding whether the host interceptor is required.
---
clang/lib/Driver/ToolChains/CommonArgs.cpp | 11 +++++++----
clang/test/Driver/fsanitize-undefined-offload.c | 16 ++++++++++++++++
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index e4865d4c3a8c82..a43745b6349bef 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1684,10 +1684,13 @@ static bool hostNeedsUbsanOffloadRt(Compilation &C, const ToolChain &HostTC) {
if (!TT.isAMDGCN() || TT.getOS() != llvm::Triple::AMDHSA)
continue;
- const ArgList &DevArgs = C.getArgsForToolChain(DevTC, {}, Kind);
- SanitizerArgs DevSan = DevTC->getSanitizerArgs(DevArgs, {}, Kind);
- if (DevSan.needsUbsanRt() && !DevSan.requiresMinimalRuntime())
- return true;
+ for (BoundArch BA :
+ C.getDriver().getOffloadArchs(C, C.getArgs(), Kind, *DevTC)) {
+ const ArgList &DevArgs = C.getArgsForToolChain(DevTC, BA, Kind);
+ SanitizerArgs DevSan = DevTC->getSanitizerArgs(DevArgs, BA, Kind);
+ if (DevSan.needsUbsanRt() && !DevSan.requiresMinimalRuntime())
+ return true;
+ }
}
}
return false;
diff --git a/clang/test/Driver/fsanitize-undefined-offload.c b/clang/test/Driver/fsanitize-undefined-offload.c
index bed6cbbd58972b..d4fd4462d7db77 100644
--- a/clang/test/Driver/fsanitize-undefined-offload.c
+++ b/clang/test/Driver/fsanitize-undefined-offload.c
@@ -65,6 +65,22 @@
// CHECK-SHARED-DAG: "-u" "__ubsan_offload_init"
// CHECK-SHARED-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -Xarch_gfx908 -fsanitize=undefined \
+// RUN: -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-GPU
+// CHECK-XARCH-GPU-DAG: "-u" "__ubsan_offload_init"
+// CHECK-XARCH-GPU-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
+
+// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
+// RUN: -x hip --offload-arch=gfx908 -Xarch_gfx90a -fsanitize=undefined \
+// RUN: -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-OTHER
+// CHECK-XARCH-OTHER-NOT: ubsan_offload
+// CHECK-XARCH-OTHER-NOT: __ubsan_offload_init
+
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -fopenmp=libomp -fopenmp-targets=x86_64-unknown-linux-gnu \
// RUN: -fsanitize=undefined \
>From bcbab5abef032b5b2f9a2997ac551da93cc8170c Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Tue, 8 Sep 2026 21:54:41 -0500
Subject: [PATCH 5/6] remove not
---
clang/test/Driver/fsanitize-undefined-offload.c | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/clang/test/Driver/fsanitize-undefined-offload.c b/clang/test/Driver/fsanitize-undefined-offload.c
index d4fd4462d7db77..424ae23f709672 100644
--- a/clang/test/Driver/fsanitize-undefined-offload.c
+++ b/clang/test/Driver/fsanitize-undefined-offload.c
@@ -24,21 +24,6 @@
// CHECK-XARCH-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_offload.a"
// CHECK-XARCH-DEV-DAG: "{{[^"]*}}x86_64-unknown-linux-gnu{{/|\\\\}}libclang_rt.ubsan_standalone.a"
-// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
-// RUN: -x hip --offload-arch=gfx908 -Xarch_host -fsanitize=undefined \
-// RUN: -nogpuinc -nogpulib --rocm-path=%S/Inputs/rocm \
-// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-XARCH-HOST
-// CHECK-XARCH-HOST-NOT: ubsan_offload
-// CHECK-XARCH-HOST-NOT: __ubsan_offload_init
-
-// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
-// RUN: -fsanitize=undefined \
-// RUN: -resource-dir=%S/Inputs/resource_dir_with_amdgpu_per_target_subdir %s 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-HOST
-// CHECK-HOST-NOT: ubsan_offload
-// CHECK-HOST-NOT: __ubsan_offload_init
-
// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 -fsanitize=undefined \
// RUN: -fsanitize-minimal-runtime -nogpuinc -nogpulib \
>From bc437a3029d6be8baa3b54cae5b5641a901f0b66 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Mon, 14 Sep 2026 07:38:21 -0500
Subject: [PATCH 6/6] Update CommonArgs.cpp
---
clang/lib/Driver/ToolChains/CommonArgs.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index a43745b6349bef..11a16a0342bad6 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1681,7 +1681,7 @@ static bool hostNeedsUbsanOffloadRt(Compilation &C, const ToolChain &HostTC) {
const ToolChain *DevTC = Entry.second;
// FIXME: CUDA/HIPSPV copy the host mask and ignore device sanitizers.
const llvm::Triple &TT = DevTC->getTriple();
- if (!TT.isAMDGCN() || TT.getOS() != llvm::Triple::AMDHSA)
+ if (!TT.isAMDGCN())
continue;
for (BoundArch BA :
More information about the llvm-branch-commits
mailing list