https://github.com/schittir updated 
https://github.com/llvm/llvm-project/pull/215620

>From e465e699bacb7e0be98902a68a7c53c04270f32f Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Tue, 11 Aug 2026 10:05:44 -0700
Subject: [PATCH 1/8] [clang] Diagnose host/device pointer width mismatches in
 offload compilations

SPIR, physical SPIR-V, and NVPTX device targets take their pointer
related types from the host target, so a host whose pointer width
differs from the device's leaves size_t, ptrdiff_t, and intptr_t
inconsistent with the device data layout. Such pairings were previously
accepted and silently miscompiled.

This patch diagnoses these invalid combinations by calling the
diagnostic at:
1. Driver::CreateOffloadingDeviceToolChains(), covering --offload=,
  --offload-targets=, and -fsycl.
2. TargetInfo::CreateTargetInfo(), covering -cc1 -triple X -aux-triple Y
  and anything else that bypasses the driver.

This is the follow-up to #208196, as discussed during review.
---
 clang/docs/ReleaseNotes.md                    |  6 +++
 .../clang/Basic/DiagnosticCommonKinds.td      |  3 ++
 clang/lib/Basic/Targets.cpp                   | 24 +++++++++
 clang/lib/Basic/Targets/SPIR.h                | 50 +++++++++++--------
 clang/lib/Driver/Driver.cpp                   | 16 ++++++
 clang/test/CodeGenCUDA/anon-ns.cu             |  4 +-
 clang/test/CodeGenCUDA/long-double.cu         |  2 +-
 .../CodeGenCUDASPIRV/copy-aggregate-byval.cu  |  4 +-
 .../test/CodeGenCUDASPIRV/kernel-argument.cu  |  4 +-
 .../CodeGenSYCL/kernel-caller-entry-point.cpp |  9 ----
 clang/test/Driver/cuda-device-triple.cu       |  2 +-
 clang/test/Frontend/sycl-aux-triple.cpp       |  4 +-
 clang/test/SemaCUDA/allow-int128.cu           |  2 +-
 .../SemaCUDA/cuda-inherits-calling-conv.cu    |  2 +-
 ...v-implicit-alloc-function-calling-conv.hip |  2 -
 15 files changed, 91 insertions(+), 43 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 2f13ec59483ee4..d1651cdb925815 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -51,6 +51,12 @@ The previous behavior can be restored with 
`-Wno-error=unicode-whitespace`.
 Clang will stop accepting non-ascii whitespaces as token separators
 in a future version of Clang.
 
+- Offload compilations that pair a SPIR, physical SPIR-V, or NVPTX device 
target
+  with a host of a different pointer width are now rejected, for example
+  `--offload=spirv32` with an `x86_64` host. These targets take `size_t`,
+  `ptrdiff_t`, and `intptr_t` from the host, so a mismatch disagreed with the
+  device data layout. Select a device target whose width matches the host's.
+
 ### C++ Specific Potentially Breaking Changes
 
 ### ABI Changes in This Version
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 192fdf9299eb44..ece27b02f840ee 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -338,6 +338,9 @@ def err_target_unknown_cpu : Error<"unknown target CPU 
'%0'">;
 def note_valid_options : Note<"valid target CPU values are: %0">;
 def err_target_unsupported_cpu_for_micromips : Error<
   "micromips is not supported for target CPU '%0'">;
+def err_target_unsupported_host_device_pointer_width : Error<
+  "device target '%0' with %1-bit pointers is incompatible with host target "
+  "'%2' with %3-bit pointers">;
 def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
 def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU 
'%1'">;
 def err_target_unsupported_abi_for_triple : Error<
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 8c01cfca8ccb48..a939eb9b944707 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -835,6 +835,15 @@ std::unique_ptr<TargetInfo> AllocateTarget(const 
llvm::Triple &Triple,
 } // namespace clang
 
 using namespace clang::targets;
+
+/// Returns true if Triple names a target that takes its pointer related types
+/// from a host target. Logical SPIR-V is excluded; it uses fixed values for
+/// those types regardless of the host.
+static bool adaptsToHostTarget(const llvm::Triple &Triple) {
+  return (Triple.isSPIROrSPIRV() && Triple.getArch() != llvm::Triple::spirv) ||
+         Triple.isNVPTX();
+}
+
 /// CreateTargetInfo - Return the target info object for the specified target
 /// options.
 TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
@@ -843,6 +852,21 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine 
&Diags,
 
   llvm::Triple Triple(llvm::Triple::normalize(Opts->Triple));
 
+  // Host and device pointer related type widths must match. Reject a mismatch
+  // before constructing the device target, which asserts on this.
+  if (adaptsToHostTarget(Triple) && !Opts->HostTriple.empty()) {
+    llvm::Triple HostTriple(llvm::Triple::normalize(Opts->HostTriple));
+    if (!adaptsToHostTarget(HostTriple) &&
+        HostTriple.getArch() != llvm::Triple::UnknownArch &&
+        Triple.getArchPointerBitWidth() !=
+            HostTriple.getArchPointerBitWidth()) {
+      Diags.Report(diag::err_target_unsupported_host_device_pointer_width)
+          << Triple.str() << Triple.getArchPointerBitWidth() << 
HostTriple.str()
+          << HostTriple.getArchPointerBitWidth();
+      return nullptr;
+    }
+  }
+
   // Construct the target
   std::unique_ptr<TargetInfo> Target = AllocateTarget(Triple, *Opts);
   if (!Target) {
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 20d8efdc832343..17f90e80dc5fdd 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -254,16 +254,18 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public 
SPIRTargetInfo {
       : SPIRTargetInfo(Triple, Opts) {
     assert(Triple.getArch() == llvm::Triple::spir &&
            "Invalid architecture for 32-bit SPIR.");
-    // FIXME: Assert that a present host target's pointer types match the ones
-    // set below, once the driver diagnoses unsupported host/device 
combinations
-    // (until then such an assert would fire on existing tests).
     PointerWidth = PointerAlign = 32;
-    const TargetInfo *HostTarget = getHostTarget();
-    if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 32) {
+    if (!getHostTarget()) {
       SizeType = TargetInfo::UnsignedInt;
       PtrDiffType = IntPtrType = TargetInfo::SignedInt;
     }
 
+    // Host and device pointer related type widths must match.
+    assert(PointerWidth == 32 && PointerAlign == 32 &&
+           getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 &&
+           getTypeWidth(IntPtrType) == 32 &&
+           "Invalid pointer related types for SPIR32");
+
     // SPIR32 has support for atomic ops if atomic extension is enabled.
     // Take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
@@ -281,16 +283,18 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public 
SPIRTargetInfo {
       : SPIRTargetInfo(Triple, Opts) {
     assert(Triple.getArch() == llvm::Triple::spir64 &&
            "Invalid architecture for 64-bit SPIR.");
-    // FIXME: Assert that a present host target's pointer types match the ones
-    // set below, once the driver diagnoses unsupported host/device 
combinations
-    // (until then such an assert would fire on existing tests).
     PointerWidth = PointerAlign = 64;
-    const TargetInfo *HostTarget = getHostTarget();
-    if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 64) {
+    if (!getHostTarget()) {
       SizeType = TargetInfo::UnsignedLong;
       PtrDiffType = IntPtrType = TargetInfo::SignedLong;
     }
 
+    // Host and device pointer related type widths must match.
+    assert(PointerWidth == 64 && PointerAlign == 64 &&
+           getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 &&
+           getTypeWidth(IntPtrType) == 64 &&
+           "Invalid pointer related types for SPIR64");
+
     // SPIR64 has support for atomic ops if atomic extension is enabled.
     // Take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
@@ -379,15 +383,18 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public 
BaseSPIRVTargetInfo {
            "32-bit SPIR-V target must use unknown, chipstar, or vulkan OS");
     assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
            "32-bit SPIR-V target must use unknown environment type");
-    // FIXME: Assert that a present host target's pointer types match the ones
-    // set below, once the driver diagnoses unsupported host/device 
combinations
-    // (until then such an assert would fire on existing tests).
     PointerWidth = PointerAlign = 32;
-    const TargetInfo *HostTarget = getHostTarget();
-    if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 32) {
+    if (!getHostTarget()) {
       SizeType = TargetInfo::UnsignedInt;
       PtrDiffType = IntPtrType = TargetInfo::SignedInt;
     }
+
+    // Host and device pointer related type widths must match.
+    assert(PointerWidth == 32 && PointerAlign == 32 &&
+           getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 &&
+           getTypeWidth(IntPtrType) == 32 &&
+           "Invalid pointer related types for SPIR-V 32");
+
     // SPIR-V has core support for atomic ops, and Int32 is always available;
     // we take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
@@ -410,15 +417,18 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public 
BaseSPIRVTargetInfo {
            "64-bit SPIR-V target must use unknown, chipstar, or vulkan OS");
     assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
            "64-bit SPIR-V target must use unknown environment type");
-    // FIXME: Assert that a present host target's pointer types match the ones
-    // set below, once the driver diagnoses unsupported host/device 
combinations
-    // (until then such an assert would fire on existing tests).
     PointerWidth = PointerAlign = 64;
-    const TargetInfo *HostTarget = getHostTarget();
-    if (!HostTarget || HostTarget->getPointerWidth(LangAS::Default) != 64) {
+    if (!getHostTarget()) {
       SizeType = TargetInfo::UnsignedLong;
       PtrDiffType = IntPtrType = TargetInfo::SignedLong;
     }
+
+    // Host and device pointer related type widths must match.
+    assert(PointerWidth == 64 && PointerAlign == 64 &&
+           getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 &&
+           getTypeWidth(IntPtrType) == 64 &&
+           "Invalid pointer related types for SPIR-V 64");
+
     // SPIR-V has core support for atomic ops, and Int64 is always available;
     // we take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 3b5d0c0aad9819..cf7e49932a1a25 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1129,6 +1129,22 @@ void 
Driver::CreateOffloadingDeviceToolChains(Compilation &C,
         continue;
       }
 
+      const llvm::Triple &HostTriple = C.getDefaultToolChain().getTriple();
+      // Logical SPIR-V is excluded; it overrides those types with fixed 
values.
+      auto AdaptsToHostTarget = [](const llvm::Triple &T) {
+        return (T.isSPIROrSPIRV() && T.getArch() != llvm::Triple::spirv) ||
+               T.isNVPTX();
+      };
+      // Target and host pointer related type widths must match.
+      if (AdaptsToHostTarget(Target) && !AdaptsToHostTarget(HostTriple) &&
+          Target.getArchPointerBitWidth() !=
+              HostTriple.getArchPointerBitWidth()) {
+        Diag(diag::err_target_unsupported_host_device_pointer_width)
+            << Target.str() << Target.getArchPointerBitWidth()
+            << HostTriple.str() << HostTriple.getArchPointerBitWidth();
+        continue;
+      }
+
       std::string NormalizedName = Target.normalize();
       auto [TripleIt, Inserted] =
           FoundNormalizedTriples.try_emplace(NormalizedName, Target.str());
diff --git a/clang/test/CodeGenCUDA/anon-ns.cu 
b/clang/test/CodeGenCUDA/anon-ns.cu
index 651a20c653458c..e2b290bd21c3d5 100644
--- a/clang/test/CodeGenCUDA/anon-ns.cu
+++ b/clang/test/CodeGenCUDA/anon-ns.cu
@@ -11,12 +11,12 @@
 
 // RUN: echo "GPU binary" > %t.fatbin
 
-// RUN: %clang_cc1 -triple nvptx -fcuda-is-device -cuid=abc \
+// RUN: %clang_cc1 -triple nvptx64 -fcuda-is-device -cuid=abc \
 // RUN:   -aux-triple x86_64-unknown-linux-gnu -std=c++17 -fgpu-rdc \
 // RUN:   -emit-llvm -o - %s > %t.dev
 
 // RUN: %clang_cc1 -triple x86_64-gnu-linux -cuid=abc \
-// RUN:   -aux-triple nvptx -std=c++17 -fgpu-rdc -fcuda-include-gpubinary 
%t.fatbin \
+// RUN:   -aux-triple nvptx64 -std=c++17 -fgpu-rdc -fcuda-include-gpubinary 
%t.fatbin \
 // RUN:   -emit-llvm -o - %s > %t.host
 
 // RUN: cat %t.dev %t.host | FileCheck -check-prefixes=CUDA,COMMON %s
diff --git a/clang/test/CodeGenCUDA/long-double.cu 
b/clang/test/CodeGenCUDA/long-double.cu
index b4116c0b815944..0a06fbe5db6d07 100644
--- a/clang/test/CodeGenCUDA/long-double.cu
+++ b/clang/test/CodeGenCUDA/long-double.cu
@@ -6,7 +6,7 @@
 // RUN:   -aux-triple x86_64-unknown-gnu-linux -fcuda-is-device \
 // RUN:   -emit-llvm -o - -x hip %s 2>&1 | FileCheck %s
 
-// RUN: %clang_cc1 -triple nvptx \
+// RUN: %clang_cc1 -triple nvptx64 \
 // RUN:   -aux-triple x86_64-unknown-gnu-linux -fcuda-is-device \
 // RUN:   -emit-llvm -o - %s 2>&1 | FileCheck %s
 
diff --git a/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu 
b/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu
index 2692ce4c92b288..fa6521b1fa5e3f 100644
--- a/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu
+++ b/clang/test/CodeGenCUDASPIRV/copy-aggregate-byval.cu
@@ -2,12 +2,12 @@
 // destructor, copy constructor or move constructor defined by user.
 
 // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv32 \
-// RUN:   -nocudalib -nocudainc %s -o %t.bc -c 2>&1
+// RUN:   --target=i386-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc -c 
2>&1
 // RUN: llvm-dis %t.bc -o %t.ll
 // RUN: FileCheck %s --input-file=%t.ll
 
 // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv64 \
-// RUN:   -nocudalib -nocudainc %s -o %t.bc -c 2>&1
+// RUN:   --target=x86_64-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc 
-c 2>&1
 // RUN: llvm-dis %t.bc -o %t.ll
 // RUN: FileCheck %s --input-file=%t.ll
 
diff --git a/clang/test/CodeGenCUDASPIRV/kernel-argument.cu 
b/clang/test/CodeGenCUDASPIRV/kernel-argument.cu
index ab885eb3d85c4a..8ec47949d0092f 100644
--- a/clang/test/CodeGenCUDASPIRV/kernel-argument.cu
+++ b/clang/test/CodeGenCUDASPIRV/kernel-argument.cu
@@ -2,12 +2,12 @@
 
 
 // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv32 \
-// RUN:   -nocudalib -nocudainc %s -o %t.bc -c 2>&1
+// RUN:   --target=i386-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc -c 
2>&1
 // RUN: llvm-dis %t.bc -o %t.ll
 // RUN: FileCheck %s --input-file=%t.ll
 
 // RUN: %clang -emit-llvm --cuda-device-only --offload=spirv64 \
-// RUN:   -nocudalib -nocudainc %s -o %t.bc -c 2>&1
+// RUN:   --target=x86_64-unknown-linux-gnu -nocudalib -nocudainc %s -o %t.bc 
-c 2>&1
 // RUN: llvm-dis %t.bc -o %t.ll
 // RUN: FileCheck %s --input-file=%t.ll
 
diff --git a/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp 
b/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp
index cc751cc683b594..bbbf4c037f7609 100644
--- a/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp
+++ b/clang/test/CodeGenSYCL/kernel-caller-entry-point.cpp
@@ -1,26 +1,17 @@
 // RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64-unknown-linux-gnu 
-std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-HOST,CHECK-HOST-LINUX %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-unknown-linux-gnu -triple amdgpu-amd-amdhsa -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-AMDGCN %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-unknown-linux-gnu -triple nvptx-nvidia-cuda -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-unknown-linux-gnu -triple nvptx64-nvidia-cuda -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-unknown-linux-gnu -triple spir-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-unknown-linux-gnu -triple spir64-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-unknown-linux-gnu -triple spirv32-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-unknown-linux-gnu -triple spirv64-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s
 // RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64-pc-windows-msvc 
-std=c++17 %s -o - | FileCheck --check-prefixes=CHECK-HOST,CHECK-HOST-WINDOWS %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-pc-windows-msvc -triple amdgpu-amd-amdhsa -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-AMDGCN %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-pc-windows-msvc -triple nvptx-nvidia-cuda -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-pc-windows-msvc -triple nvptx64-nvidia-cuda -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-pc-windows-msvc -triple spir-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-pc-windows-msvc -triple spir64-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-pc-windows-msvc -triple spirv32-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple 
x86_64-pc-windows-msvc -triple spirv64-unknown-unknown -std=c++17 %s -o - | 
FileCheck --check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s
 // RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64-uefi -std=c++17 %s 
-o - | FileCheck --check-prefixes=CHECK-HOST,CHECK-HOST-WINDOWS %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple 
amdgpu-amd-amdhsa -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-AMDGCN %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple 
nvptx-nvidia-cuda -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple 
nvptx64-nvidia-cuda -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-NVPTX %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple 
spir-unknown-unknown -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple 
spir64-unknown-unknown -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRNV %s
-// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple 
spirv32-unknown-unknown -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s
 // RUN: %clang_cc1 -fsycl-is-device -emit-llvm -aux-triple x86_64-uefi -triple 
spirv64-unknown-unknown -std=c++17 %s -o - | FileCheck 
--check-prefixes=CHECK-DEVICE,CHECK-SPIR,CHECK-SPIRV %s
 
 // Test code generation for functions declared with the sycl_kernel_entry_point
diff --git a/clang/test/Driver/cuda-device-triple.cu 
b/clang/test/Driver/cuda-device-triple.cu
index 8acd4585b8c828..5abdcbf2b7381a 100644
--- a/clang/test/Driver/cuda-device-triple.cu
+++ b/clang/test/Driver/cuda-device-triple.cu
@@ -1,4 +1,4 @@
-// RUN: %clang -### -emit-llvm --cuda-device-only \
+// RUN: %clang -### -emit-llvm --cuda-device-only 
--target=i386-unknown-linux-gnu \
 // RUN:   -nocudalib -nocudainc --offload=spirv32-unknown-unknown -c %s 2>&1 | 
FileCheck %s
 
 // Make sure there's no sm_* suffix on the output name
diff --git a/clang/test/Frontend/sycl-aux-triple.cpp 
b/clang/test/Frontend/sycl-aux-triple.cpp
index 38b6a24fb3ce99..2ab23fd1cf7e80 100644
--- a/clang/test/Frontend/sycl-aux-triple.cpp
+++ b/clang/test/Frontend/sycl-aux-triple.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -triple spir -aux-triple x86_64-unknown-linux-gnu -E -dM 
| FileCheck %s
-// RUN: %clang_cc1 %s -fsycl-is-device -triple spir -aux-triple 
x86_64-unknown-linux-gnu -E -dM | FileCheck --check-prefix=CHECK-SYCL %s
+// RUN: %clang_cc1 %s -triple spir64 -aux-triple x86_64-unknown-linux-gnu -E 
-dM | FileCheck %s
+// RUN: %clang_cc1 %s -fsycl-is-device -triple spir64 -aux-triple 
x86_64-unknown-linux-gnu -E -dM | FileCheck --check-prefix=CHECK-SYCL %s
 
 // CHECK-NOT:#define __x86_64__ 1
 // CHECK-SYCL:#define __x86_64__ 1
diff --git a/clang/test/SemaCUDA/allow-int128.cu 
b/clang/test/SemaCUDA/allow-int128.cu
index 44f8fefa3aa051..5d2f484bcd44d9 100644
--- a/clang/test/SemaCUDA/allow-int128.cu
+++ b/clang/test/SemaCUDA/allow-int128.cu
@@ -4,7 +4,7 @@
 // RUN: %clang_cc1 -triple spirv64-amd-amdhsa \
 // RUN:   -aux-triple x86_64-unknown-linux-gnu \
 // RUN:   -fcuda-is-device -verify -fsyntax-only %s
-// RUN: %clang_cc1 -triple nvptx \
+// RUN: %clang_cc1 -triple nvptx64 \
 // RUN:   -aux-triple x86_64-unknown-linux-gnu \
 // RUN:   -fcuda-is-device -verify -fsyntax-only %s
 
diff --git a/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu 
b/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu
index a6928e71f3ae09..a4a6292e012e44 100644
--- a/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu
+++ b/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu
@@ -5,7 +5,7 @@
 // RUN:   -aux-triple i386-windows-msvc -fsyntax-only \
 // RUN:   -fcuda-is-device -verify %s
 
-// RUN: %clang_cc1 -std=c++11 -triple nvptx-nvidia-cuda \
+// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda \
 // RUN:   -aux-triple x86_64-linux-gnu -fsyntax-only \
 // RUN:   -fcuda-is-device -verify -verify-ignore-unexpected=note \
 // RUN:   -DEXPECT_ERR %s
diff --git 
a/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip 
b/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip
index c3e7e1a5cd59ee..66bf9b359e65ad 100644
--- a/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip
+++ b/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip
@@ -1,10 +1,8 @@
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa 
-verify
-// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -aux-triple 
x86_64-unknown-linux-gnu -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -aux-triple 
x86_64-unknown-linux-gnu -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa 
-aux-triple x86_64-unknown-linux-gnu -verify
-// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -aux-triple 
x86_64-pc-windows-msvc -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -aux-triple 
x86_64-pc-windows-msvc -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa 
-aux-triple x86_64-pc-windows-msvc -verify
 

>From 306f69d8643631f04d935f9b3834f1031f61576a Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Fri, 28 Aug 2026 10:44:07 -0700
Subject: [PATCH 2/8] Diagnose other type and size mismatches in addition to
 pointer width

---
 clang/docs/ReleaseNotes.md                    |  9 ++-
 .../clang/Basic/DiagnosticCommonKinds.td      |  7 +-
 clang/include/clang/Basic/TargetInfo.h        | 30 +++++++
 clang/lib/Basic/Targets.cpp                   | 79 ++++++++++++++-----
 clang/lib/Basic/Targets/SPIR.h                | 32 +-------
 clang/lib/Driver/Driver.cpp                   | 18 ++---
 clang/lib/Frontend/CompilerInstance.cpp       |  8 +-
 clang/test/Driver/hip-autolink.hip            |  6 +-
 clang/test/SemaCUDA/amdgpu-bf16.cu            |  4 +-
 9 files changed, 121 insertions(+), 72 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index d1651cdb925815..42f52a2fd1a835 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -51,11 +51,12 @@ The previous behavior can be restored with 
`-Wno-error=unicode-whitespace`.
 Clang will stop accepting non-ascii whitespaces as token separators
 in a future version of Clang.
 
-- Offload compilations that pair a SPIR, physical SPIR-V, or NVPTX device 
target
-  with a host of a different pointer width are now rejected, for example
-  `--offload=spirv32` with an `x86_64` host. These targets take `size_t`,
+- Offload compilations that pair a SPIR, physical SPIR-V, NVPTX, or AMDGPU 
device
+  target with an incompatible host target are now rejected, for example
+  `--offload=spirv32` with an `x86_64` host, or `--offload-arch=gfx906` with an
+  `i386` host. These targets take the pointer width and alignment, `size_t`,
   `ptrdiff_t`, and `intptr_t` from the host, so a mismatch disagreed with the
-  device data layout. Select a device target whose width matches the host's.
+  device data layout. Select a host and device target that agree on those 
types.
 
 ### C++ Specific Potentially Breaking Changes
 
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index ece27b02f840ee..bbf9882ffda069 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -338,9 +338,10 @@ def err_target_unknown_cpu : Error<"unknown target CPU 
'%0'">;
 def note_valid_options : Note<"valid target CPU values are: %0">;
 def err_target_unsupported_cpu_for_micromips : Error<
   "micromips is not supported for target CPU '%0'">;
-def err_target_unsupported_host_device_pointer_width : Error<
-  "device target '%0' with %1-bit pointers is incompatible with host target "
-  "'%2' with %3-bit pointers">;
+def err_target_unsupported_host_pointer_related_type : Error<
+  "device target '%0' takes %select{a pointer width|a pointer alignment|"
+  "a 'size_t' width|a 'ptrdiff_t' width|an 'intptr_t' width}2 of %3 bits from "
+  "host target '%1', but requires %4 bits">;
 def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
 def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU 
'%1'">;
 def err_target_unsupported_abi_for_triple : Error<
diff --git a/clang/include/clang/Basic/TargetInfo.h 
b/clang/include/clang/Basic/TargetInfo.h
index 6311b6b567a5e1..f0f5bf735ae953 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -327,6 +327,36 @@ class TargetInfo : public TransferrableTargetInfo,
   static TargetInfo *CreateTargetInfo(DiagnosticsEngine &Diags,
                                       TargetOptions &Opts);
 
+  /// When a device target takes its pointer related types (the pointer width
+  /// and alignment, size_t, ptrdiff_t, and intptr_t) from a host target.
+  enum class HostAdaptation {
+    /// It keeps its own pointer related types.
+    None,
+    /// It adapts in its constructor, from TargetOptions::HostTriple.
+    Constructor,
+    SetAuxTarget,
+  };
+
+  /// Returns when the device target takes its pointer related types from the
+  /// host target, mirroring the conditions under which the TargetInfo
+  /// subclasses adapt. A device that declines a host keeps its own types, 
which
+  /// the driver's triple level check must not report as a mismatch.
+  static HostAdaptation getHostAdaptation(const llvm::Triple &DeviceTriple,
+                                          const llvm::Triple &HostTriple);
+
+  static bool adaptsToHostTarget(const llvm::Triple &DeviceTriple,
+                                 const llvm::Triple &HostTriple) {
+    return getHostAdaptation(DeviceTriple, HostTriple) != HostAdaptation::None;
+  }
+
+  /// Reports an error if this target adapts to the given host target at the
+  /// given stage and ended up with pointer related types that disagree with 
its
+  /// own data layout. Does nothing if it does not adapt at that stage. Returns
+  /// true if no error was reported.
+  bool checkHostPointerRelatedTypes(DiagnosticsEngine &Diags,
+                                    const llvm::Triple &HostTriple,
+                                    HostAdaptation Stage) const;
+
   virtual ~TargetInfo();
 
   /// Retrieve the target options.
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index a939eb9b944707..ed48400a947f96 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -836,12 +836,59 @@ std::unique_ptr<TargetInfo> AllocateTarget(const 
llvm::Triple &Triple,
 
 using namespace clang::targets;
 
-/// Returns true if Triple names a target that takes its pointer related types
-/// from a host target. Logical SPIR-V is excluded; it uses fixed values for
-/// those types regardless of the host.
-static bool adaptsToHostTarget(const llvm::Triple &Triple) {
-  return (Triple.isSPIROrSPIRV() && Triple.getArch() != llvm::Triple::spirv) ||
-         Triple.isNVPTX();
+TargetInfo::HostAdaptation
+TargetInfo::getHostAdaptation(const llvm::Triple &DeviceTriple,
+                              const llvm::Triple &HostTriple) {
+  // No recognizable host triple, so nothing to adapt to.
+  if (HostTriple.getArch() == llvm::Triple::UnknownArch)
+    return HostAdaptation::None;
+
+  // setAuxTarget() overwrites these, so constructor values are not yet final.
+  if (DeviceTriple.isAMDGPU() ||
+      (DeviceTriple.getArch() == llvm::Triple::spirv64 &&
+       DeviceTriple.getOS() == llvm::Triple::AMDHSA))
+    return HostAdaptation::SetAuxTarget;
+
+  // Logical SPIR-V sets these itself, with a 32-bit size_t by design.
+  if (DeviceTriple.isSPIRVLogical())
+    return HostAdaptation::None;
+
+  if (DeviceTriple.isSPIROrSPIRV())
+    return HostTriple.isSPIROrSPIRV() ? HostAdaptation::None
+                                      : HostAdaptation::Constructor;
+  if (DeviceTriple.isNVPTX())
+    return HostTriple.isNVPTX() ? HostAdaptation::None
+                                : HostAdaptation::Constructor;
+
+  return HostAdaptation::None;
+}
+
+bool TargetInfo::checkHostPointerRelatedTypes(DiagnosticsEngine &Diags,
+                                              const llvm::Triple &HostTriple,
+                                              HostAdaptation Stage) const {
+  assert(Stage != HostAdaptation::None && "Nothing to check");
+  if (getHostAdaptation(getTriple(), HostTriple) != Stage)
+    return true;
+
+  // The device data layout fixes the width of every one of these types.
+  unsigned Required = getTriple().getArchPointerBitWidth();
+  // The order matches the %select in the diagnostic below.
+  unsigned Widths[] = {getPointerWidth(LangAS::Default),
+                       getPointerAlign(LangAS::Default),
+                       getTypeWidth(getSizeType()),
+                       getTypeWidth(getPtrDiffType(LangAS::Default)),
+                       getTypeWidth(getIntPtrType())};
+
+  for (auto [Which, Width] : llvm::enumerate(Widths)) {
+    if (Width != Required) {
+      Diags.Report(diag::err_target_unsupported_host_pointer_related_type)
+          << getTriple().str() << HostTriple.str()
+          << static_cast<unsigned>(Which) << Width << Required;
+      return false;
+    }
+  }
+
+  return true;
 }
 
 /// CreateTargetInfo - Return the target info object for the specified target
@@ -852,21 +899,6 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine 
&Diags,
 
   llvm::Triple Triple(llvm::Triple::normalize(Opts->Triple));
 
-  // Host and device pointer related type widths must match. Reject a mismatch
-  // before constructing the device target, which asserts on this.
-  if (adaptsToHostTarget(Triple) && !Opts->HostTriple.empty()) {
-    llvm::Triple HostTriple(llvm::Triple::normalize(Opts->HostTriple));
-    if (!adaptsToHostTarget(HostTriple) &&
-        HostTriple.getArch() != llvm::Triple::UnknownArch &&
-        Triple.getArchPointerBitWidth() !=
-            HostTriple.getArchPointerBitWidth()) {
-      Diags.Report(diag::err_target_unsupported_host_device_pointer_width)
-          << Triple.str() << Triple.getArchPointerBitWidth() << 
HostTriple.str()
-          << HostTriple.getArchPointerBitWidth();
-      return nullptr;
-    }
-  }
-
   // Construct the target
   std::unique_ptr<TargetInfo> Target = AllocateTarget(Triple, *Opts);
   if (!Target) {
@@ -875,6 +907,11 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine 
&Diags,
   }
   Target->TargetOpts = Opts;
 
+  // Targets that adapt in their constructor have done so by now.
+  if (!Target->checkHostPointerRelatedTypes(
+          Diags, llvm::Triple(Opts->HostTriple), HostAdaptation::Constructor))
+    return nullptr;
+
   // Set the target CPU if specified.
   if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) {
     Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU;
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 17f90e80dc5fdd..b5400cddf575c6 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -254,18 +254,12 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public 
SPIRTargetInfo {
       : SPIRTargetInfo(Triple, Opts) {
     assert(Triple.getArch() == llvm::Triple::spir &&
            "Invalid architecture for 32-bit SPIR.");
-    PointerWidth = PointerAlign = 32;
     if (!getHostTarget()) {
+      PointerWidth = PointerAlign = 32;
       SizeType = TargetInfo::UnsignedInt;
       PtrDiffType = IntPtrType = TargetInfo::SignedInt;
     }
 
-    // Host and device pointer related type widths must match.
-    assert(PointerWidth == 32 && PointerAlign == 32 &&
-           getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 &&
-           getTypeWidth(IntPtrType) == 32 &&
-           "Invalid pointer related types for SPIR32");
-
     // SPIR32 has support for atomic ops if atomic extension is enabled.
     // Take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
@@ -283,18 +277,12 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public 
SPIRTargetInfo {
       : SPIRTargetInfo(Triple, Opts) {
     assert(Triple.getArch() == llvm::Triple::spir64 &&
            "Invalid architecture for 64-bit SPIR.");
-    PointerWidth = PointerAlign = 64;
     if (!getHostTarget()) {
+      PointerWidth = PointerAlign = 64;
       SizeType = TargetInfo::UnsignedLong;
       PtrDiffType = IntPtrType = TargetInfo::SignedLong;
     }
 
-    // Host and device pointer related type widths must match.
-    assert(PointerWidth == 64 && PointerAlign == 64 &&
-           getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 &&
-           getTypeWidth(IntPtrType) == 64 &&
-           "Invalid pointer related types for SPIR64");
-
     // SPIR64 has support for atomic ops if atomic extension is enabled.
     // Take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
@@ -383,18 +371,12 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public 
BaseSPIRVTargetInfo {
            "32-bit SPIR-V target must use unknown, chipstar, or vulkan OS");
     assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
            "32-bit SPIR-V target must use unknown environment type");
-    PointerWidth = PointerAlign = 32;
     if (!getHostTarget()) {
+      PointerWidth = PointerAlign = 32;
       SizeType = TargetInfo::UnsignedInt;
       PtrDiffType = IntPtrType = TargetInfo::SignedInt;
     }
 
-    // Host and device pointer related type widths must match.
-    assert(PointerWidth == 32 && PointerAlign == 32 &&
-           getTypeWidth(SizeType) == 32 && getTypeWidth(PtrDiffType) == 32 &&
-           getTypeWidth(IntPtrType) == 32 &&
-           "Invalid pointer related types for SPIR-V 32");
-
     // SPIR-V has core support for atomic ops, and Int32 is always available;
     // we take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
@@ -417,18 +399,12 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public 
BaseSPIRVTargetInfo {
            "64-bit SPIR-V target must use unknown, chipstar, or vulkan OS");
     assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
            "64-bit SPIR-V target must use unknown environment type");
-    PointerWidth = PointerAlign = 64;
     if (!getHostTarget()) {
+      PointerWidth = PointerAlign = 64;
       SizeType = TargetInfo::UnsignedLong;
       PtrDiffType = IntPtrType = TargetInfo::SignedLong;
     }
 
-    // Host and device pointer related type widths must match.
-    assert(PointerWidth == 64 && PointerAlign == 64 &&
-           getTypeWidth(SizeType) == 64 && getTypeWidth(PtrDiffType) == 64 &&
-           getTypeWidth(IntPtrType) == 64 &&
-           "Invalid pointer related types for SPIR-V 64");
-
     // SPIR-V has core support for atomic ops, and Int64 is always available;
     // we take the maximum because it's possible the Host supports wider types.
     MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index cf7e49932a1a25..f90c2804b805c4 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -55,6 +55,7 @@
 #include "ToolChains/ZOS.h"
 #include "clang/Basic/DiagnosticDriver.h"
 #include "clang/Basic/TargetID.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Version.h"
 #include "clang/Config/config.h"
 #include "clang/Driver/Action.h"
@@ -1129,19 +1130,16 @@ void 
Driver::CreateOffloadingDeviceToolChains(Compilation &C,
         continue;
       }
 
+      // A triple level approximation that catches the common cases early; the
+      // types are checked once the device adapts.
       const llvm::Triple &HostTriple = C.getDefaultToolChain().getTriple();
-      // Logical SPIR-V is excluded; it overrides those types with fixed 
values.
-      auto AdaptsToHostTarget = [](const llvm::Triple &T) {
-        return (T.isSPIROrSPIRV() && T.getArch() != llvm::Triple::spirv) ||
-               T.isNVPTX();
-      };
-      // Target and host pointer related type widths must match.
-      if (AdaptsToHostTarget(Target) && !AdaptsToHostTarget(HostTriple) &&
+      if (TargetInfo::adaptsToHostTarget(Target, HostTriple) &&
           Target.getArchPointerBitWidth() !=
               HostTriple.getArchPointerBitWidth()) {
-        Diag(diag::err_target_unsupported_host_device_pointer_width)
-            << Target.str() << Target.getArchPointerBitWidth()
-            << HostTriple.str() << HostTriple.getArchPointerBitWidth();
+        Diag(diag::err_target_unsupported_host_pointer_related_type)
+            << Target.str() << HostTriple.str() << /*pointer width*/ 0
+            << HostTriple.getArchPointerBitWidth()
+            << Target.getArchPointerBitWidth();
         continue;
       }
 
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 66662a786e6fca..7a7373b82ebb9a 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -167,9 +167,15 @@ bool CompilerInstance::createTarget() {
   // created. This complexity should be lifted elsewhere.
   getTarget().adjust(getDiagnostics(), getLangOpts(), getAuxTarget());
 
-  if (auto *Aux = getAuxTarget())
+  if (auto *Aux = getAuxTarget()) {
     getTarget().setAuxTarget(Aux);
 
+    if (!getTarget().checkHostPointerRelatedTypes(
+            getDiagnostics(), Aux->getTriple(),
+            TargetInfo::HostAdaptation::SetAuxTarget))
+      return false;
+  }
+
   return true;
 }
 
diff --git a/clang/test/Driver/hip-autolink.hip 
b/clang/test/Driver/hip-autolink.hip
index cce3977375d2e0..e37c6e5d7e5029 100644
--- a/clang/test/Driver/hip-autolink.hip
+++ b/clang/test/Driver/hip-autolink.hip
@@ -1,10 +1,10 @@
-// RUN: %clang --target=i386-pc-windows-msvc --cuda-gpu-arch=gfx906 -nogpulib 
-nogpuinc \
+// RUN: %clang --target=x86_64-pc-windows-msvc --cuda-gpu-arch=gfx906 
-nogpulib -nogpuinc \
 // RUN:   --cuda-device-only %s -### 2>&1 | FileCheck --check-prefix=DEV %s
-// RUN: %clang --target=i386-pc-windows-msvc --cuda-gpu-arch=gfx906 -nogpulib 
-nogpuinc \
+// RUN: %clang --target=x86_64-pc-windows-msvc --cuda-gpu-arch=gfx906 
-nogpulib -nogpuinc \
 // RUN:   --cuda-host-only %s -### 2>&1 | FileCheck --check-prefix=HOST %s
 
 // DEV: "-cc1" "-triple" "amdgcn-amd-amdhsa"
 // DEV-SAME: "-fno-autolink"
 
-// HOST: "-cc1" "-triple" "i386-pc-windows-msvc{{.*}}"
+// HOST: "-cc1" "-triple" "x86_64-pc-windows-msvc{{.*}}"
 // HOST-NOT: "-fno-autolink"
diff --git a/clang/test/SemaCUDA/amdgpu-bf16.cu 
b/clang/test/SemaCUDA/amdgpu-bf16.cu
index 0b5ce1a4f64cf5..b14a3dd608aeb2 100644
--- a/clang/test/SemaCUDA/amdgpu-bf16.cu
+++ b/clang/test/SemaCUDA/amdgpu-bf16.cu
@@ -1,8 +1,8 @@
 // REQUIRES: amdgpu-registered-target
 // REQUIRES: x86-registered-target
 
-// RUN: %clang_cc1 "-aux-triple" "x86_64-unknown-linux-gnu" "-triple" 
"r600-unknown-unknown"\
-// RUN:    -fcuda-is-device "-aux-target-cpu" "x86-64" -fsyntax-only 
-verify=r600 %s
+// RUN: %clang_cc1 "-aux-triple" "i386-unknown-linux-gnu" "-triple" 
"r600-unknown-unknown"\
+// RUN:    -fcuda-is-device "-aux-target-cpu" "i686" -fsyntax-only 
-verify=r600 %s
 
 // AMDGCN has storage-only support for bf16. R600 does not support it should 
error out when
 // it's the main target.

>From 8aa1d9a9082399bb2350654cc708b16a61884fe3 Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Fri, 28 Aug 2026 12:43:03 -0700
Subject: [PATCH 3/8] Static cast to unsigned.

---
 clang/lib/Basic/Targets.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index ed48400a947f96..a328f175b5afc4 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -873,8 +873,8 @@ bool 
TargetInfo::checkHostPointerRelatedTypes(DiagnosticsEngine &Diags,
   // The device data layout fixes the width of every one of these types.
   unsigned Required = getTriple().getArchPointerBitWidth();
   // The order matches the %select in the diagnostic below.
-  unsigned Widths[] = {getPointerWidth(LangAS::Default),
-                       getPointerAlign(LangAS::Default),
+  unsigned Widths[] = {static_cast<unsigned>(getPointerWidth(LangAS::Default)),
+                       static_cast<unsigned>(getPointerAlign(LangAS::Default)),
                        getTypeWidth(getSizeType()),
                        getTypeWidth(getPtrDiffType(LangAS::Default)),
                        getTypeWidth(getIntPtrType())};

>From 67dfe736a64ab5cb021b69a45b85b831b9924cc1 Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Mon, 31 Aug 2026 19:35:26 -0700
Subject: [PATCH 4/8] [clang] Add tests for the host/device pointer related
 type diagnostic

Add the driver and frontend tests for the diagnostic, and adapt two
existing tests that pair a 64-bit device target with a 32-bit host:
Preprocessor/init-amdgpu.c and
SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip
---
 .../Driver/offload-pointer-width-mismatch.c   | 31 +++++++
 .../offload-pointer-width-mismatch.cpp        | 93 +++++++++++++++++++
 clang/test/Preprocessor/init-amdgpu.c         |  2 +-
 ...mdgcnspirv-host-cconv-in-abstract-type.hip |  1 -
 4 files changed, 125 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Driver/offload-pointer-width-mismatch.c
 create mode 100644 clang/test/Frontend/offload-pointer-width-mismatch.cpp

diff --git a/clang/test/Driver/offload-pointer-width-mismatch.c 
b/clang/test/Driver/offload-pointer-width-mismatch.c
new file mode 100644
index 00000000000000..98fd079d5edae8
--- /dev/null
+++ b/clang/test/Driver/offload-pointer-width-mismatch.c
@@ -0,0 +1,31 @@
+// Offload targets that take their pointer related types from the host target
+// are rejected early, before any compilation job is built.
+
+// RUN: not %clang -### --target=i386-unknown-linux-gnu -x hip 
--offload-arch=gfx906 \
+// RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s
+// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda 
--offload=nvptx64-nvidia-cuda \
+// RUN:   --offload-arch=sm_60 -nogpulib -nogpuinc -c %s 2>&1 | FileCheck 
--check-prefix=NVPTX %s
+// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -x cuda 
--cuda-device-only \
+// RUN:   -nogpulib -nogpuinc --offload=spirv32-unknown-unknown -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=SPIRV32 %s
+// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda \
+// RUN:   --offload-targets=nvptx64-nvidia-cuda --offload-arch=sm_60 -nogpulib 
-nogpuinc \
+// RUN:   -c %s 2>&1 | FileCheck --check-prefix=NVPTX %s
+
+// OpenMP offloading reaches the same check.
+
+// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp \
+// RUN:   -fopenmp-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=NVPTX %s
+// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp 
--offload-arch=gfx906 \
+// RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s
+
+// AMDGPU: error: device target 'amdgpu-amd-amdhsa' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
+// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
+// SPIRV32: error: device target 'spirv32-unknown-unknown' takes a pointer 
width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 
bits
+
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -x hip 
--offload-arch=gfx906 \
+// RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=OK %s
+
+// OK-NOT: error:
+// OK: "-cc1" "-triple" "amdgpu9.06-amd-amdhsa" "-aux-triple" 
"x86_64-unknown-linux-gnu"
diff --git a/clang/test/Frontend/offload-pointer-width-mismatch.cpp 
b/clang/test/Frontend/offload-pointer-width-mismatch.cpp
new file mode 100644
index 00000000000000..4d1107079253cf
--- /dev/null
+++ b/clang/test/Frontend/offload-pointer-width-mismatch.cpp
@@ -0,0 +1,93 @@
+// REQUIRES: amdgpu-registered-target, nvptx-registered-target
+// REQUIRES: spirv-registered-target, x86-registered-target
+
+// RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple 
i386-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck 
--check-prefix=AMDGCN %s
+// RUN: not %clang_cc1 -triple r600-unknown-unknown -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck 
--check-prefix=R600 %s
+// RUN: not %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple 
i386-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x cuda %s 2>&1 | FileCheck 
--check-prefix=NVPTX %s
+// RUN: not %clang_cc1 -triple spir-unknown-unknown -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=SPIR %s
+// RUN: not %clang_cc1 -triple spirv64-unknown-unknown -aux-triple 
i386-unknown-linux-gnu \
+// RUN:   -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=SPIRV %s
+
+// AMDGCN: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
+// R600: error: device target 'r600-unknown-unknown' takes a pointer width of 
64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits
+// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
+// SPIR: error: device target 'spir-unknown-unknown' takes a pointer width of 
64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits
+// SPIRV: error: device target 'spirv64-unknown-unknown' takes a pointer width 
of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
+
+// OpenMP device compilation adapts at both stages too.
+
+// RUN: not %clang_cc1 -fopenmp -fopenmp-is-target-device -triple 
amdgcn-amd-amdhsa \
+// RUN:   -aux-triple i386-unknown-linux-gnu -fsyntax-only %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=AMDGCN %s
+// RUN: not %clang_cc1 -fopenmp -fopenmp-is-target-device -triple 
nvptx64-nvidia-cuda \
+// RUN:   -aux-triple i386-unknown-linux-gnu -fsyntax-only %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=NVPTX %s
+
+// A host target that is itself a device target is no exception.
+
+// RUN: not %clang_cc1 -triple spirv64-unknown-unknown -aux-triple 
nvptx-nvidia-cuda \
+// RUN:   -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=SPIRV-NVPTX %s
+// RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple 
r600-unknown-unknown \
+// RUN:   -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck 
--check-prefix=AMDGCN-R600 %s
+// RUN: not %clang_cc1 -triple spirv64-amd-amdhsa -aux-triple 
spir-unknown-unknown \
+// RUN:   -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=AMDHSA-SPIR %s
+
+// SPIRV-NVPTX: error: device target 'spirv64-unknown-unknown' takes a pointer 
width of 32 bits from host target 'nvptx-nvidia-cuda', but requires 64 bits
+// AMDGCN-R600: error: device target 'amdgcn-amd-amdhsa' takes a pointer width 
of 32 bits from host target 'r600-unknown-unknown', but requires 64 bits
+// AMDHSA-SPIR: error: device target 'spirv64-amd-amdhsa' takes a pointer 
width of 32 bits from host target 'spir-unknown-unknown', but requires 64 bits
+
+// The host pointer width is taken from the host target rather than from its
+// triple, so an ABI that narrows pointers is caught too.
+
+// RUN: not %clang_cc1 -triple spir64-unknown-unknown -aux-triple 
x86_64-unknown-linux-gnux32 \
+// RUN:   -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=SPIR64-X32 %s
+// RUN: not %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple 
x86_64-unknown-linux-gnux32 \
+// RUN:   -fcuda-is-device -fsyntax-only -x cuda %s 2>&1 | FileCheck 
--check-prefix=NVPTX64-X32 %s
+// RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple 
x86_64-unknown-linux-gnux32 \
+// RUN:   -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck 
--check-prefix=AMDGCN-X32 %s
+
+// SPIR64-X32: error: device target 'spir64-unknown-unknown' takes a pointer 
width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 
64 bits
+// NVPTX64-X32: error: device target 'nvptx64-nvidia-cuda' takes a pointer 
width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 
64 bits
+// AMDGCN-X32: error: device target 'amdgcn-amd-amdhsa' takes a pointer width 
of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits
+
+// NVPTX and AMDGPU take the pointer alignment from the host too, so a host 
that
+// under aligns pointers is a mismatch even where the widths agree.
+
+// RUN: not %clang_cc1 -triple nvptx-nvidia-cuda -aux-triple 
m68k-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x cuda %s 2>&1 | FileCheck 
--check-prefix=NVPTX-M68K %s
+// RUN: not %clang_cc1 -triple r600-unknown-unknown -aux-triple 
m68k-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck 
--check-prefix=R600-M68K %s
+
+// NVPTX-M68K: error: device target 'nvptx-nvidia-cuda' takes a pointer 
alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 
bits
+// R600-M68K: error: device target 'r600-unknown-unknown' takes a pointer 
alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 
bits
+
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x hip %s
+// RUN: %clang_cc1 -triple r600-unknown-unknown -aux-triple 
i386-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x hip %s
+// RUN: %clang_cc1 -triple nvptx-nvidia-cuda -aux-triple 
i386-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -fsyntax-only -x cuda %s
+// RUN: %clang_cc1 -triple spir64-unknown-unknown -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fsycl-is-device -fsyntax-only %s
+// RUN: %clang_cc1 -triple spir64-unknown-unknown -aux-triple 
x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -fsyntax-only %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-is-target-device -triple 
amdgcn-amd-amdhsa \
+// RUN:   -aux-triple x86_64-unknown-linux-gnu -fsyntax-only %s
+
+// SPIR and SPIR-V align pointers to their own width rather than to the host
+// alignment, so an under aligning host is not a mismatch there.
+
+// RUN: %clang_cc1 -triple spir-unknown-unknown -aux-triple 
m68k-unknown-linux-gnu \
+// RUN:   -fsycl-is-device -fsyntax-only %s
+
+// SPIR, SPIR-V, and NVPTX keep their own pointer related types when the host 
is
+// of their own family, so a differing width is not a mismatch there.
+
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple 
spir-unknown-unknown \
+// RUN:   -fsycl-is-device -fsyntax-only %s
+// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple nvptx-nvidia-cuda \
+// RUN:   -fcuda-is-device -fsyntax-only -x cuda %s
diff --git a/clang/test/Preprocessor/init-amdgpu.c 
b/clang/test/Preprocessor/init-amdgpu.c
index 9e938ab4502a51..5a88de5b9a71f5 100644
--- a/clang/test/Preprocessor/init-amdgpu.c
+++ b/clang/test/Preprocessor/init-amdgpu.c
@@ -32,7 +32,7 @@
 // RUN:   -aux-triple x86_64-pc-windows-msvc < /dev/null \
 // RUN:   | FileCheck -match-full-lines -check-prefix=LLP64 %s
 // RUN: %clang_cc1 -x hip -fcuda-is-device -E -dM 
-triple=amdgpu12.50-amd-amdhsa \
-// RUN:   -aux-triple i386-unknown-linux-gnu < /dev/null \
+// RUN:   -aux-triple x86_64-pc-windows-msvc < /dev/null \
 // RUN:   | FileCheck -match-full-lines -check-prefix=LLP64 %s
 // RUN: %clang_cc1 -fopenmp -fopenmp-is-target-device -E -dM \
 // RUN:   -triple=amdgpu9.0a-amd-amdhsa -aux-triple x86_64-pc-windows-msvc < 
/dev/null \
diff --git a/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip 
b/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip
index f6b4ed3d6c33e0..95c1154a68f5fe 100644
--- a/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip
+++ b/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip
@@ -1,4 +1,3 @@
-// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -aux-triple 
x86_64-pc-windows-msvc -fms-extensions -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -aux-triple 
x86_64-pc-windows-msvc -fms-extensions -verify
 // RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa 
-aux-triple x86_64-pc-windows-msvc -fms-extensions -verify
 

>From 06b60e4757e11fb6f91c0f5622122e63967c895b Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Tue, 1 Sep 2026 09:18:15 -0700
Subject: [PATCH 5/8] [clang] Report host/device target incompatibility with
 notes per type

---
 .../clang/Basic/DiagnosticCommonKinds.td      |  9 +--
 clang/include/clang/Basic/TargetInfo.h        | 14 ++---
 clang/lib/Basic/Targets.cpp                   | 59 ++++++++++++-------
 clang/lib/Driver/Driver.cpp                   |  9 +--
 clang/lib/Frontend/CompilerInstance.cpp       |  2 +-
 .../Driver/offload-pointer-width-mismatch.c   | 11 +++-
 .../offload-pointer-width-mismatch.cpp        | 50 ++++++++++++----
 7 files changed, 100 insertions(+), 54 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index bbf9882ffda069..7415a2768050c2 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -338,10 +338,11 @@ def err_target_unknown_cpu : Error<"unknown target CPU 
'%0'">;
 def note_valid_options : Note<"valid target CPU values are: %0">;
 def err_target_unsupported_cpu_for_micromips : Error<
   "micromips is not supported for target CPU '%0'">;
-def err_target_unsupported_host_pointer_related_type : Error<
-  "device target '%0' takes %select{a pointer width|a pointer alignment|"
-  "a 'size_t' width|a 'ptrdiff_t' width|an 'intptr_t' width}2 of %3 bits from "
-  "host target '%1', but requires %4 bits">;
+def err_incompatible_host_and_device_targets : Error<
+  "device target '%0' is not compatible with host target '%1'">;
+def note_incompatible_host_and_device_type : Note<
+  "%select{alignment|size}0 of type '%1' for the host target (%2 bytes) does "
+  "not match the %select{alignment|size}0 for the device target (%3 bytes)">;
 def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
 def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU 
'%1'">;
 def err_target_unsupported_abi_for_triple : Error<
diff --git a/clang/include/clang/Basic/TargetInfo.h 
b/clang/include/clang/Basic/TargetInfo.h
index 52c2f40b85aed2..741b0cc3852c08 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -348,13 +348,13 @@ class TargetInfo : public TransferrableTargetInfo,
     return getHostAdaptation(DeviceTriple, HostTriple) != HostAdaptation::None;
   }
 
-  /// Reports an error if this target adapts to the given host target at the
-  /// given stage and ended up with pointer related types that disagree with 
its
-  /// own data layout. Does nothing if it does not adapt at that stage. Returns
-  /// true if no error was reported.
-  bool checkHostPointerRelatedTypes(DiagnosticsEngine &Diags,
-                                    const llvm::Triple &HostTriple,
-                                    HostAdaptation Stage) const;
+  /// Reports an error, and a note per offending type, if this target adapts to
+  /// the given host target at the given stage and ended up with pointer 
related
+  /// types that disagree with its own data layout. Does nothing if it does not
+  /// adapt at that stage. Returns true if no error was reported.
+  bool checkHostCompatibility(DiagnosticsEngine &Diags,
+                              const llvm::Triple &HostTriple,
+                              HostAdaptation Stage) const;
 
   virtual ~TargetInfo();
 
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index a328f175b5afc4..81608ef3d06263 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -863,32 +863,47 @@ TargetInfo::getHostAdaptation(const llvm::Triple 
&DeviceTriple,
   return HostAdaptation::None;
 }
 
-bool TargetInfo::checkHostPointerRelatedTypes(DiagnosticsEngine &Diags,
-                                              const llvm::Triple &HostTriple,
-                                              HostAdaptation Stage) const {
+bool TargetInfo::checkHostCompatibility(DiagnosticsEngine &Diags,
+                                        const llvm::Triple &HostTriple,
+                                        HostAdaptation Stage) const {
   assert(Stage != HostAdaptation::None && "Nothing to check");
   if (getHostAdaptation(getTriple(), HostTriple) != Stage)
     return true;
 
-  // The device data layout fixes the width of every one of these types.
+  // The device data layout fixes the size and the alignment of a pointer, and
+  // with them the width of every integer type that has to hold one.
   unsigned Required = getTriple().getArchPointerBitWidth();
-  // The order matches the %select in the diagnostic below.
-  unsigned Widths[] = {static_cast<unsigned>(getPointerWidth(LangAS::Default)),
-                       static_cast<unsigned>(getPointerAlign(LangAS::Default)),
-                       getTypeWidth(getSizeType()),
-                       getTypeWidth(getPtrDiffType(LangAS::Default)),
-                       getTypeWidth(getIntPtrType())};
-
-  for (auto [Which, Width] : llvm::enumerate(Widths)) {
-    if (Width != Required) {
-      Diags.Report(diag::err_target_unsupported_host_pointer_related_type)
-          << getTriple().str() << HostTriple.str()
-          << static_cast<unsigned>(Which) << Width << Required;
-      return false;
-    }
-  }
+  struct Mismatch {
+    unsigned Which;
+    const char *TypeName;
+    unsigned HostBits;
+  };
+  // The order matches the %select in note_incompatible_host_and_device_type.
+  enum { Alignment, Size };
+
+  SmallVector<Mismatch, 5> Mismatches;
+  auto Check = [&](unsigned Which, const char *TypeName, uint64_t HostBits) {
+    if (HostBits != Required)
+      Mismatches.push_back({Which, TypeName, static_cast<unsigned>(HostBits)});
+  };
+
+  Check(Size, "void *", getPointerWidth(LangAS::Default));
+  Check(Alignment, "void *", getPointerAlign(LangAS::Default));
+  Check(Size, "size_t", getTypeWidth(getSizeType()));
+  Check(Size, "ptrdiff_t", getTypeWidth(getPtrDiffType(LangAS::Default)));
+  Check(Size, "intptr_t", getTypeWidth(getIntPtrType()));
+
+  if (Mismatches.empty())
+    return true;
+
+  Diags.Report(diag::err_incompatible_host_and_device_targets)
+      << getTriple().str() << HostTriple.str();
+  for (const Mismatch &M : Mismatches)
+    Diags.Report(diag::note_incompatible_host_and_device_type)
+        << M.Which << M.TypeName << M.HostBits / getCharWidth()
+        << Required / getCharWidth();
 
-  return true;
+  return false;
 }
 
 /// CreateTargetInfo - Return the target info object for the specified target
@@ -908,8 +923,8 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine 
&Diags,
   Target->TargetOpts = Opts;
 
   // Targets that adapt in their constructor have done so by now.
-  if (!Target->checkHostPointerRelatedTypes(
-          Diags, llvm::Triple(Opts->HostTriple), HostAdaptation::Constructor))
+  if (!Target->checkHostCompatibility(Diags, llvm::Triple(Opts->HostTriple),
+                                      HostAdaptation::Constructor))
     return nullptr;
 
   // Set the target CPU if specified.
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 54ca09f1b793a6..ac075e9de5f96f 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1168,10 +1168,11 @@ void 
Driver::CreateOffloadingDeviceToolChains(Compilation &C,
       if (TargetInfo::adaptsToHostTarget(Target, HostTriple) &&
           Target.getArchPointerBitWidth() !=
               HostTriple.getArchPointerBitWidth()) {
-        Diag(diag::err_target_unsupported_host_pointer_related_type)
-            << Target.str() << HostTriple.str() << /*pointer width*/ 0
-            << HostTriple.getArchPointerBitWidth()
-            << Target.getArchPointerBitWidth();
+        Diag(diag::err_incompatible_host_and_device_targets)
+            << Target.str() << HostTriple.str();
+        Diag(diag::note_incompatible_host_and_device_type)
+            << /*size*/ 1 << "void *" << HostTriple.getArchPointerBitWidth() / 
8
+            << Target.getArchPointerBitWidth() / 8;
         continue;
       }
 
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 6ed32d91f4f247..cad0215ae32340 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -170,7 +170,7 @@ bool CompilerInstance::createTarget() {
   if (auto *Aux = getAuxTarget()) {
     getTarget().setAuxTarget(Aux);
 
-    if (!getTarget().checkHostPointerRelatedTypes(
+    if (!getTarget().checkHostCompatibility(
             getDiagnostics(), Aux->getTriple(),
             TargetInfo::HostAdaptation::SetAuxTarget))
       return false;
diff --git a/clang/test/Driver/offload-pointer-width-mismatch.c 
b/clang/test/Driver/offload-pointer-width-mismatch.c
index 98fd079d5edae8..9fefa4df9f17b1 100644
--- a/clang/test/Driver/offload-pointer-width-mismatch.c
+++ b/clang/test/Driver/offload-pointer-width-mismatch.c
@@ -20,9 +20,14 @@
 // RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp 
--offload-arch=gfx906 \
 // RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s
 
-// AMDGPU: error: device target 'amdgpu-amd-amdhsa' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
-// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
-// SPIRV32: error: device target 'spirv32-unknown-unknown' takes a pointer 
width of 64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 
bits
+// The driver only knows the triples, so it notes the pointer size alone.
+
+// AMDGPU: error: device target 'amdgpu-amd-amdhsa' is not compatible with 
host target 'i386-unknown-linux-gnu'
+// AMDGPU-NEXT: note: size of type 'void *' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
+// NVPTX: error: device target 'nvptx64-nvidia-cuda' is not compatible with 
host target 'i386-unknown-linux-gnu'
+// NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
+// SPIRV32: error: device target 'spirv32-unknown-unknown' is not compatible 
with host target 'x86_64-unknown-linux-gnu'
+// SPIRV32-NEXT: note: size of type 'void *' for the host target (8 bytes) 
does not match the size for the device target (4 bytes)
 
 // RUN: %clang -### --target=x86_64-unknown-linux-gnu -x hip 
--offload-arch=gfx906 \
 // RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=OK %s
diff --git a/clang/test/Frontend/offload-pointer-width-mismatch.cpp 
b/clang/test/Frontend/offload-pointer-width-mismatch.cpp
index 4d1107079253cf..9ad94417a115f9 100644
--- a/clang/test/Frontend/offload-pointer-width-mismatch.cpp
+++ b/clang/test/Frontend/offload-pointer-width-mismatch.cpp
@@ -12,11 +12,23 @@
 // RUN: not %clang_cc1 -triple spirv64-unknown-unknown -aux-triple 
i386-unknown-linux-gnu \
 // RUN:   -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=SPIRV %s
 
-// AMDGCN: error: device target 'amdgcn-amd-amdhsa' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
-// R600: error: device target 'r600-unknown-unknown' takes a pointer width of 
64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits
-// NVPTX: error: device target 'nvptx64-nvidia-cuda' takes a pointer width of 
32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
-// SPIR: error: device target 'spir-unknown-unknown' takes a pointer width of 
64 bits from host target 'x86_64-unknown-linux-gnu', but requires 32 bits
-// SPIRV: error: device target 'spirv64-unknown-unknown' takes a pointer width 
of 32 bits from host target 'i386-unknown-linux-gnu', but requires 64 bits
+// Every type that disagrees with the device data layout is noted.
+
+// AMDGCN: error: device target 'amdgcn-amd-amdhsa' is not compatible with 
host target 'i386-unknown-linux-gnu'
+// AMDGCN-NEXT: note: size of type 'void *' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
+// AMDGCN-NEXT: note: alignment of type 'void *' for the host target (4 bytes) 
does not match the alignment for the device target (8 bytes)
+// AMDGCN-NEXT: note: size of type 'size_t' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
+// AMDGCN-NEXT: note: size of type 'ptrdiff_t' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
+// AMDGCN-NEXT: note: size of type 'intptr_t' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
+
+// R600: error: device target 'r600-unknown-unknown' is not compatible with 
host target 'x86_64-unknown-linux-gnu'
+// R600-NEXT: note: size of type 'void *' for the host target (8 bytes) does 
not match the size for the device target (4 bytes)
+// NVPTX: error: device target 'nvptx64-nvidia-cuda' is not compatible with 
host target 'i386-unknown-linux-gnu'
+// NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
+// SPIR: error: device target 'spir-unknown-unknown' is not compatible with 
host target 'x86_64-unknown-linux-gnu'
+// SPIR-NEXT: note: size of type 'void *' for the host target (8 bytes) does 
not match the size for the device target (4 bytes)
+// SPIRV: error: device target 'spirv64-unknown-unknown' is not compatible 
with host target 'i386-unknown-linux-gnu'
+// SPIRV-NEXT: note: size of type 'void *' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
 
 // OpenMP device compilation adapts at both stages too.
 
@@ -36,9 +48,12 @@
 // RUN: not %clang_cc1 -triple spirv64-amd-amdhsa -aux-triple 
spir-unknown-unknown \
 // RUN:   -fsycl-is-device -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=AMDHSA-SPIR %s
 
-// SPIRV-NVPTX: error: device target 'spirv64-unknown-unknown' takes a pointer 
width of 32 bits from host target 'nvptx-nvidia-cuda', but requires 64 bits
-// AMDGCN-R600: error: device target 'amdgcn-amd-amdhsa' takes a pointer width 
of 32 bits from host target 'r600-unknown-unknown', but requires 64 bits
-// AMDHSA-SPIR: error: device target 'spirv64-amd-amdhsa' takes a pointer 
width of 32 bits from host target 'spir-unknown-unknown', but requires 64 bits
+// SPIRV-NVPTX: error: device target 'spirv64-unknown-unknown' is not 
compatible with host target 'nvptx-nvidia-cuda'
+// SPIRV-NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
+// AMDGCN-R600: error: device target 'amdgcn-amd-amdhsa' is not compatible 
with host target 'r600-unknown-unknown'
+// AMDGCN-R600-NEXT: note: size of type 'void *' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
+// AMDHSA-SPIR: error: device target 'spirv64-amd-amdhsa' is not compatible 
with host target 'spir-unknown-unknown'
+// AMDHSA-SPIR-NEXT: note: size of type 'void *' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
 
 // The host pointer width is taken from the host target rather than from its
 // triple, so an ABI that narrows pointers is caught too.
@@ -50,9 +65,12 @@
 // RUN: not %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple 
x86_64-unknown-linux-gnux32 \
 // RUN:   -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck 
--check-prefix=AMDGCN-X32 %s
 
-// SPIR64-X32: error: device target 'spir64-unknown-unknown' takes a pointer 
width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 
64 bits
-// NVPTX64-X32: error: device target 'nvptx64-nvidia-cuda' takes a pointer 
width of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 
64 bits
-// AMDGCN-X32: error: device target 'amdgcn-amd-amdhsa' takes a pointer width 
of 32 bits from host target 'x86_64-unknown-linux-gnux32', but requires 64 bits
+// SPIR64-X32: error: device target 'spir64-unknown-unknown' is not compatible 
with host target 'x86_64-unknown-linux-gnux32'
+// SPIR64-X32-NEXT: note: size of type 'void *' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
+// NVPTX64-X32: error: device target 'nvptx64-nvidia-cuda' is not compatible 
with host target 'x86_64-unknown-linux-gnux32'
+// NVPTX64-X32-NEXT: note: size of type 'void *' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
+// AMDGCN-X32: error: device target 'amdgcn-amd-amdhsa' is not compatible with 
host target 'x86_64-unknown-linux-gnux32'
+// AMDGCN-X32-NEXT: note: size of type 'void *' for the host target (4 bytes) 
does not match the size for the device target (8 bytes)
 
 // NVPTX and AMDGPU take the pointer alignment from the host too, so a host 
that
 // under aligns pointers is a mismatch even where the widths agree.
@@ -62,8 +80,14 @@
 // RUN: not %clang_cc1 -triple r600-unknown-unknown -aux-triple 
m68k-unknown-linux-gnu \
 // RUN:   -fcuda-is-device -fsyntax-only -x hip %s 2>&1 | FileCheck 
--check-prefix=R600-M68K %s
 
-// NVPTX-M68K: error: device target 'nvptx-nvidia-cuda' takes a pointer 
alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 
bits
-// R600-M68K: error: device target 'r600-unknown-unknown' takes a pointer 
alignment of 16 bits from host target 'm68k-unknown-linux-gnu', but requires 32 
bits
+// The alignment is then the only type detail noted.
+
+// NVPTX-M68K: error: device target 'nvptx-nvidia-cuda' is not compatible with 
host target 'm68k-unknown-linux-gnu'
+// NVPTX-M68K-NEXT: note: alignment of type 'void *' for the host target (2 
bytes) does not match the alignment for the device target (4 bytes)
+// NVPTX-M68K-NOT: note:
+// R600-M68K: error: device target 'r600-unknown-unknown' is not compatible 
with host target 'm68k-unknown-linux-gnu'
+// R600-M68K-NEXT: note: alignment of type 'void *' for the host target (2 
bytes) does not match the alignment for the device target (4 bytes)
+// R600-M68K-NOT: note:
 
 // RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple 
x86_64-unknown-linux-gnu \
 // RUN:   -fcuda-is-device -fsyntax-only -x hip %s

>From d3cd49ebde2cadbb69777622e3c7d69f63dedf0f Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Tue, 1 Sep 2026 10:40:29 -0700
Subject: [PATCH 6/8] [clang] Check the built device target instead of tracking
 adaptation

---
 clang/include/clang/Basic/TargetInfo.h        | 35 +++------------
 clang/lib/Basic/Targets.cpp                   | 44 +++----------------
 clang/lib/Driver/Driver.cpp                   | 15 -------
 clang/lib/Frontend/CompilerInstance.cpp       |  6 +--
 .../Driver/offload-pointer-width-mismatch.c   | 44 +++++++------------
 5 files changed, 33 insertions(+), 111 deletions(-)

diff --git a/clang/include/clang/Basic/TargetInfo.h 
b/clang/include/clang/Basic/TargetInfo.h
index 741b0cc3852c08..d3a98eb1018bde 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -326,35 +326,14 @@ class TargetInfo : public TransferrableTargetInfo,
   static TargetInfo *CreateTargetInfo(DiagnosticsEngine &Diags,
                                       TargetOptions &Opts);
 
-  /// When a device target takes its pointer related types (the pointer width
-  /// and alignment, size_t, ptrdiff_t, and intptr_t) from a host target.
-  enum class HostAdaptation {
-    /// It keeps its own pointer related types.
-    None,
-    /// It adapts in its constructor, from TargetOptions::HostTriple.
-    Constructor,
-    SetAuxTarget,
-  };
-
-  /// Returns when the device target takes its pointer related types from the
-  /// host target, mirroring the conditions under which the TargetInfo
-  /// subclasses adapt. A device that declines a host keeps its own types, 
which
-  /// the driver's triple level check must not report as a mismatch.
-  static HostAdaptation getHostAdaptation(const llvm::Triple &DeviceTriple,
-                                          const llvm::Triple &HostTriple);
-
-  static bool adaptsToHostTarget(const llvm::Triple &DeviceTriple,
-                                 const llvm::Triple &HostTriple) {
-    return getHostAdaptation(DeviceTriple, HostTriple) != HostAdaptation::None;
-  }
-
-  /// Reports an error, and a note per offending type, if this target adapts to
-  /// the given host target at the given stage and ended up with pointer 
related
-  /// types that disagree with its own data layout. Does nothing if it does not
-  /// adapt at that stage. Returns true if no error was reported.
+  /// Reports an error, and a note per offending type, if a pointer related 
type
+  /// (the pointer size and alignment, size_t, ptrdiff_t, and intptr_t) that
+  /// this device target took from the given host target disagrees with its own
+  /// data layout. Returns true if no error was reported. Call this once the
+  /// target has taken whatever it takes from the host target, that is, after
+  /// setAuxTarget().
   bool checkHostCompatibility(DiagnosticsEngine &Diags,
-                              const llvm::Triple &HostTriple,
-                              HostAdaptation Stage) const;
+                              const llvm::Triple &HostTriple) const;
 
   virtual ~TargetInfo();
 
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 81608ef3d06263..eccd91d14778bf 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -836,42 +836,15 @@ std::unique_ptr<TargetInfo> AllocateTarget(const 
llvm::Triple &Triple,
 
 using namespace clang::targets;
 
-TargetInfo::HostAdaptation
-TargetInfo::getHostAdaptation(const llvm::Triple &DeviceTriple,
-                              const llvm::Triple &HostTriple) {
-  // No recognizable host triple, so nothing to adapt to.
-  if (HostTriple.getArch() == llvm::Triple::UnknownArch)
-    return HostAdaptation::None;
-
-  // setAuxTarget() overwrites these, so constructor values are not yet final.
-  if (DeviceTriple.isAMDGPU() ||
-      (DeviceTriple.getArch() == llvm::Triple::spirv64 &&
-       DeviceTriple.getOS() == llvm::Triple::AMDHSA))
-    return HostAdaptation::SetAuxTarget;
-
-  // Logical SPIR-V sets these itself, with a 32-bit size_t by design.
-  if (DeviceTriple.isSPIRVLogical())
-    return HostAdaptation::None;
-
-  if (DeviceTriple.isSPIROrSPIRV())
-    return HostTriple.isSPIROrSPIRV() ? HostAdaptation::None
-                                      : HostAdaptation::Constructor;
-  if (DeviceTriple.isNVPTX())
-    return HostTriple.isNVPTX() ? HostAdaptation::None
-                                : HostAdaptation::Constructor;
-
-  return HostAdaptation::None;
-}
-
 bool TargetInfo::checkHostCompatibility(DiagnosticsEngine &Diags,
-                                        const llvm::Triple &HostTriple,
-                                        HostAdaptation Stage) const {
-  assert(Stage != HostAdaptation::None && "Nothing to check");
-  if (getHostAdaptation(getTriple(), HostTriple) != Stage)
+                                        const llvm::Triple &HostTriple) const {
+  // Logical SPIR-V has no pointer size to require.
+  if (getTriple().isSPIRVLogical())
     return true;
 
-  // The device data layout fixes the size and the alignment of a pointer, and
-  // with them the width of every integer type that has to hold one.
+  // Whatever this target took from the host target, it has to hold a pointer,
+  // whose size and alignment its own data layout fixes. A target that took
+  // nothing agrees with itself and is reported here in no case.
   unsigned Required = getTriple().getArchPointerBitWidth();
   struct Mismatch {
     unsigned Which;
@@ -922,11 +895,6 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine 
&Diags,
   }
   Target->TargetOpts = Opts;
 
-  // Targets that adapt in their constructor have done so by now.
-  if (!Target->checkHostCompatibility(Diags, llvm::Triple(Opts->HostTriple),
-                                      HostAdaptation::Constructor))
-    return nullptr;
-
   // Set the target CPU if specified.
   if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) {
     Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ac075e9de5f96f..f06f1c5a75ff81 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -55,7 +55,6 @@
 #include "ToolChains/ZOS.h"
 #include "clang/Basic/DiagnosticDriver.h"
 #include "clang/Basic/TargetID.h"
-#include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Version.h"
 #include "clang/Config/config.h"
 #include "clang/Driver/Action.h"
@@ -1162,20 +1161,6 @@ void 
Driver::CreateOffloadingDeviceToolChains(Compilation &C,
         continue;
       }
 
-      // A triple level approximation that catches the common cases early; the
-      // types are checked once the device adapts.
-      const llvm::Triple &HostTriple = C.getDefaultToolChain().getTriple();
-      if (TargetInfo::adaptsToHostTarget(Target, HostTriple) &&
-          Target.getArchPointerBitWidth() !=
-              HostTriple.getArchPointerBitWidth()) {
-        Diag(diag::err_incompatible_host_and_device_targets)
-            << Target.str() << HostTriple.str();
-        Diag(diag::note_incompatible_host_and_device_type)
-            << /*size*/ 1 << "void *" << HostTriple.getArchPointerBitWidth() / 
8
-            << Target.getArchPointerBitWidth() / 8;
-        continue;
-      }
-
       std::string NormalizedName = Target.normalize();
       auto [TripleIt, Inserted] =
           FoundNormalizedTriples.try_emplace(NormalizedName, Target.str());
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index cad0215ae32340..b3eef5301e41af 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -170,9 +170,9 @@ bool CompilerInstance::createTarget() {
   if (auto *Aux = getAuxTarget()) {
     getTarget().setAuxTarget(Aux);
 
-    if (!getTarget().checkHostCompatibility(
-            getDiagnostics(), Aux->getTriple(),
-            TargetInfo::HostAdaptation::SetAuxTarget))
+    // The target has taken everything it takes from the host target by now.
+    if (getLangOpts().isTargetDevice() &&
+        !getTarget().checkHostCompatibility(getDiagnostics(), 
Aux->getTriple()))
       return false;
   }
 
diff --git a/clang/test/Driver/offload-pointer-width-mismatch.c 
b/clang/test/Driver/offload-pointer-width-mismatch.c
index 9fefa4df9f17b1..d443c80613efe7 100644
--- a/clang/test/Driver/offload-pointer-width-mismatch.c
+++ b/clang/test/Driver/offload-pointer-width-mismatch.c
@@ -1,36 +1,26 @@
-// Offload targets that take their pointer related types from the host target
-// are rejected early, before any compilation job is built.
+// An offload compilation whose device target takes its pointer related types
+// from an incompatible host target fails when the device compilation runs.
 
-// RUN: not %clang -### --target=i386-unknown-linux-gnu -x hip 
--offload-arch=gfx906 \
-// RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s
-// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda 
--offload=nvptx64-nvidia-cuda \
-// RUN:   --offload-arch=sm_60 -nogpulib -nogpuinc -c %s 2>&1 | FileCheck 
--check-prefix=NVPTX %s
-// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -x cuda 
--cuda-device-only \
-// RUN:   -nogpulib -nogpuinc --offload=spirv32-unknown-unknown -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=SPIRV32 %s
-// RUN: not %clang -### --target=i386-unknown-linux-gnu -x cuda \
-// RUN:   --offload-targets=nvptx64-nvidia-cuda --offload-arch=sm_60 -nogpulib 
-nogpuinc \
-// RUN:   -c %s 2>&1 | FileCheck --check-prefix=NVPTX %s
+// REQUIRES: amdgpu-registered-target, nvptx-registered-target
 
-// OpenMP offloading reaches the same check.
-
-// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp \
-// RUN:   -fopenmp-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc -c %s 2>&1 \
+// RUN: not %clang --target=i386-unknown-linux-gnu -x hip 
--offload-arch=gfx906 \
+// RUN:   -nogpulib -nogpuinc -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=AMDGPU %s
+// RUN: not %clang --target=i386-unknown-linux-gnu -x cuda 
--offload=nvptx64-nvidia-cuda \
+// RUN:   --offload-arch=sm_60 -nogpulib -nogpuinc -fsyntax-only %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=NVPTX %s
-// RUN: not %clang -### --target=i386-unknown-linux-gnu -fopenmp 
--offload-arch=gfx906 \
-// RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=AMDGPU %s
-
-// The driver only knows the triples, so it notes the pointer size alone.
+// RUN: not %clang --target=i386-unknown-linux-gnu -fopenmp \
+// RUN:   -fopenmp-targets=nvptx64-nvidia-cuda --offload-arch=sm_60 -nogpulib 
-nogpuinc \
+// RUN:   -fsyntax-only %s 2>&1 | FileCheck --check-prefix=NVPTX %s
 
-// AMDGPU: error: device target 'amdgpu-amd-amdhsa' is not compatible with 
host target 'i386-unknown-linux-gnu'
+// AMDGPU: error: device target 'amdgpu9.06-amd-amdhsa' is not compatible with 
host target 'i386-unknown-linux-gnu'
 // AMDGPU-NEXT: note: size of type 'void *' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
 // NVPTX: error: device target 'nvptx64-nvidia-cuda' is not compatible with 
host target 'i386-unknown-linux-gnu'
 // NVPTX-NEXT: note: size of type 'void *' for the host target (4 bytes) does 
not match the size for the device target (8 bytes)
-// SPIRV32: error: device target 'spirv32-unknown-unknown' is not compatible 
with host target 'x86_64-unknown-linux-gnu'
-// SPIRV32-NEXT: note: size of type 'void *' for the host target (8 bytes) 
does not match the size for the device target (4 bytes)
 
-// RUN: %clang -### --target=x86_64-unknown-linux-gnu -x hip 
--offload-arch=gfx906 \
-// RUN:   -nogpulib -nogpuinc -c %s 2>&1 | FileCheck --check-prefix=OK %s
+// A host target of a matching pointer width is accepted, and so is the 32-bit
+// device target that a 32-bit host selects by default.
 
-// OK-NOT: error:
-// OK: "-cc1" "-triple" "amdgpu9.06-amd-amdhsa" "-aux-triple" 
"x86_64-unknown-linux-gnu"
+// RUN: %clang --target=x86_64-unknown-linux-gnu -x hip --offload-arch=gfx906 \
+// RUN:   -nogpulib -nogpuinc -fsyntax-only %s
+// RUN: %clang --target=i386-unknown-linux-gnu -x cuda --offload-arch=sm_60 \
+// RUN:   -nogpulib -nogpuinc -fsyntax-only %s

>From 1ceb1fb76a28c00b7c02b120e940a9fd712c723b Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Tue, 1 Sep 2026 12:12:47 -0700
Subject: [PATCH 7/8] [clang] Take the auxiliary target compatibility check to
 its own interface

---
 clang/include/clang/Basic/TargetInfo.h  | 12 ++++--------
 clang/lib/Basic/Targets.cpp             | 17 +++++++++++------
 clang/lib/Frontend/CompilerInstance.cpp |  6 +++---
 3 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/clang/include/clang/Basic/TargetInfo.h 
b/clang/include/clang/Basic/TargetInfo.h
index d3a98eb1018bde..b2c0d870324a22 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -326,14 +326,10 @@ class TargetInfo : public TransferrableTargetInfo,
   static TargetInfo *CreateTargetInfo(DiagnosticsEngine &Diags,
                                       TargetOptions &Opts);
 
-  /// Reports an error, and a note per offending type, if a pointer related 
type
-  /// (the pointer size and alignment, size_t, ptrdiff_t, and intptr_t) that
-  /// this device target took from the given host target disagrees with its own
-  /// data layout. Returns true if no error was reported. Call this once the
-  /// target has taken whatever it takes from the host target, that is, after
-  /// setAuxTarget().
-  bool checkHostCompatibility(DiagnosticsEngine &Diags,
-                              const llvm::Triple &HostTriple) const;
+  /// Diagnoses the pointer related types that this target took from its
+  /// auxiliary target if they disagree with its own data layout. Returns true
+  /// if no error was reported. Call after setAuxTarget().
+  bool checkAuxTargetCompatibility(DiagnosticsEngine &Diags) const;
 
   virtual ~TargetInfo();
 
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index eccd91d14778bf..fe46d979152aad 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -836,15 +836,20 @@ std::unique_ptr<TargetInfo> AllocateTarget(const 
llvm::Triple &Triple,
 
 using namespace clang::targets;
 
-bool TargetInfo::checkHostCompatibility(DiagnosticsEngine &Diags,
-                                        const llvm::Triple &HostTriple) const {
+bool TargetInfo::checkAuxTargetCompatibility(DiagnosticsEngine &Diags) const {
+  // Only a device target takes its pointer related types from another target,
+  // and only such a target is given the triple of the target it takes them
+  // from.
+  StringRef HostTriple = getTargetOpts().HostTriple;
+  if (HostTriple.empty())
+    return true;
+
   // Logical SPIR-V has no pointer size to require.
   if (getTriple().isSPIRVLogical())
     return true;
 
-  // Whatever this target took from the host target, it has to hold a pointer,
-  // whose size and alignment its own data layout fixes. A target that took
-  // nothing agrees with itself and is reported here in no case.
+  // These getters return what the target took from the host, so a disagreement
+  // with the width its own data layout fixes is a host/device mismatch.
   unsigned Required = getTriple().getArchPointerBitWidth();
   struct Mismatch {
     unsigned Which;
@@ -870,7 +875,7 @@ bool TargetInfo::checkHostCompatibility(DiagnosticsEngine 
&Diags,
     return true;
 
   Diags.Report(diag::err_incompatible_host_and_device_targets)
-      << getTriple().str() << HostTriple.str();
+      << getTriple().str() << HostTriple;
   for (const Mismatch &M : Mismatches)
     Diags.Report(diag::note_incompatible_host_and_device_type)
         << M.Which << M.TypeName << M.HostBits / getCharWidth()
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index b3eef5301e41af..a1784bdd1cd937 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -170,9 +170,9 @@ bool CompilerInstance::createTarget() {
   if (auto *Aux = getAuxTarget()) {
     getTarget().setAuxTarget(Aux);
 
-    // The target has taken everything it takes from the host target by now.
-    if (getLangOpts().isTargetDevice() &&
-        !getTarget().checkHostCompatibility(getDiagnostics(), 
Aux->getTriple()))
+    // The target has taken everything it takes from the auxiliary target by
+    // now, which TargetInfo::adjust() above is too early for.
+    if (!getTarget().checkAuxTargetCompatibility(getDiagnostics()))
       return false;
   }
 

>From 747dccfa0e2efdac53446430697781ada012e0a4 Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <[email protected]>
Date: Wed, 2 Sep 2026 07:24:14 -0700
Subject: [PATCH 8/8] [clang] Add asserts on SPIR and SPIR-V target pointer
 types/sizes

---
 clang/lib/Basic/Targets/SPIR.h | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 7c36ac5e0ef36d..73ff5030320782 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -253,6 +253,12 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public 
SPIRTargetInfo {
       PointerWidth = PointerAlign = 32;
       SizeType = TargetInfo::UnsignedInt;
       PtrDiffType = IntPtrType = TargetInfo::SignedInt;
+
+      assert(PointerWidth == 32);
+      assert(PointerAlign == 32);
+      assert(getTypeWidth(SizeType) == 32);
+      assert(getTypeWidth(PtrDiffType) == 32);
+      assert(getTypeWidth(IntPtrType) == 32);
     }
 
     // SPIR32 has support for atomic ops if atomic extension is enabled.
@@ -276,6 +282,11 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public 
SPIRTargetInfo {
       PointerWidth = PointerAlign = 64;
       SizeType = TargetInfo::UnsignedLong;
       PtrDiffType = IntPtrType = TargetInfo::SignedLong;
+      assert(PointerWidth == 64);
+      assert(PointerAlign == 64);
+      assert(getTypeWidth(SizeType) == 64);
+      assert(getTypeWidth(PtrDiffType) == 64);
+      assert(getTypeWidth(IntPtrType) == 64);
     }
 
     // SPIR64 has support for atomic ops if atomic extension is enabled.
@@ -370,6 +381,11 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public 
BaseSPIRVTargetInfo {
       PointerWidth = PointerAlign = 32;
       SizeType = TargetInfo::UnsignedInt;
       PtrDiffType = IntPtrType = TargetInfo::SignedInt;
+      assert(PointerWidth == 32);
+      assert(PointerAlign == 32);
+      assert(getTypeWidth(SizeType) == 32);
+      assert(getTypeWidth(PtrDiffType) == 32);
+      assert(getTypeWidth(IntPtrType) == 32);
     }
 
     // SPIR-V has core support for atomic ops, and Int32 is always available;
@@ -398,6 +414,11 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public 
BaseSPIRVTargetInfo {
       PointerWidth = PointerAlign = 64;
       SizeType = TargetInfo::UnsignedLong;
       PtrDiffType = IntPtrType = TargetInfo::SignedLong;
+      assert(PointerWidth == 64);
+      assert(PointerAlign == 64);
+      assert(getTypeWidth(SizeType) == 64);
+      assert(getTypeWidth(PtrDiffType) == 64);
+      assert(getTypeWidth(IntPtrType) == 64);
     }
 
     // SPIR-V has core support for atomic ops, and Int64 is always available;
@@ -445,6 +466,17 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final
     PointerWidth = PointerAlign = 64;
     SizeType = TargetInfo::UnsignedLong;
     PtrDiffType = IntPtrType = TargetInfo::SignedLong;
+
+    // With a host target the widths above are the host's until setAuxTarget()
+    // replaces them, so only what this target sets itself is asserted.
+    if (!getHostTarget()) {
+      assert(PointerWidth == 64);
+      assert(PointerAlign == 64);
+      assert(getTypeWidth(SizeType) == 64);
+      assert(getTypeWidth(PtrDiffType) == 64);
+      assert(getTypeWidth(IntPtrType) == 64);
+    }
+
     AddrSpaceMap = &SPIRDefIsGenMap;
 
     resetDataLayout();

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

Reply via email to