https://github.com/wenju-he updated 
https://github.com/llvm/llvm-project/pull/204086

>From f90642ac5da3d3da7d2cc648a88121e80520ab95 Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Tue, 16 Jun 2026 01:08:58 -0700
Subject: [PATCH 1/8] [OpenCL] Warn if filter_mode is linear in
 read_image{i|ui}

Per OpenCL spec:
The read_image{i|ui} calls support a nearest filter only. The
filter_mode specified in sampler must be set to CLK_FILTER_NEAREST;
otherwise the values returned are undefined.

Assisted-by: Claude Sonnet 4.6
---
 .../clang/Basic/DiagnosticSemaKinds.td        |  2 +
 clang/include/clang/Sema/SemaOpenCL.h         |  2 +
 clang/lib/Sema/SemaExpr.cpp                   |  7 ++
 clang/lib/Sema/SemaOpenCL.cpp                 | 49 +++++++++++++
 .../read-image-integer-linear-filter.cl       | 68 +++++++++++++++++++
 5 files changed, 128 insertions(+)
 create mode 100644 clang/test/SemaOpenCL/read-image-integer-linear-filter.cl

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f84cd8dca6d4c..57c32216a2f1e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11834,6 +11834,8 @@ def err_sampler_initializer_not_integer : Error<
   "sampler_t initialization requires 32-bit integer, not %0">;
 def warn_sampler_initializer_invalid_bits : Warning<
   "sampler initializer has invalid %0 bits">, InGroup<SpirCompat>, 
DefaultIgnore;
+def warn_sampler_argument_invalid_filter : Warning<
+  "'%0' sampler must use CLK_FILTER_NEAREST">, InGroup<SpirCompat>;
 def err_sampler_argument_required : Error<
   "sampler_t variable required - got %0">;
 def err_wrong_sampler_addressspace: Error<
diff --git a/clang/include/clang/Sema/SemaOpenCL.h 
b/clang/include/clang/Sema/SemaOpenCL.h
index 04b2b617fb12f..51c2e1703b504 100644
--- a/clang/include/clang/Sema/SemaOpenCL.h
+++ b/clang/include/clang/Sema/SemaOpenCL.h
@@ -100,6 +100,8 @@ class SemaOpenCL : public SemaBase {
   bool checkBuiltinKernelWorkGroupSize(CallExpr *TheCall);
 
   bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall);
+
+  void checkBuiltinReadImage(FunctionDecl *FDecl, CallExpr *Call);
 };
 
 } // namespace clang
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index f2745425588f5..345d093aed88a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -59,6 +59,7 @@
 #include "clang/Sema/SemaFixItUtils.h"
 #include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaObjC.h"
+#include "clang/Sema/SemaOpenCL.h"
 #include "clang/Sema/SemaOpenMP.h"
 #include "clang/Sema/SemaPseudoObject.h"
 #include "clang/Sema/Template.h"
@@ -7283,6 +7284,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
     }
   }
 
+  // Check read_image{i|ui} sampler argument before ConvertArgumentsForCall
+  // replaces sampler DeclRefExprs with their integer initializers.
+  if (getLangOpts().OpenCL && FDecl) {
+    OpenCL().checkBuiltinReadImage(FDecl, TheCall);
+  }
+
   if (Proto) {
     if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc,
                                 IsExecConfig))
diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index f11a40e3964ff..d307858e1660f 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -12,7 +12,9 @@
 
 #include "clang/Sema/SemaOpenCL.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
+#include "clang/AST/Expr.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Sema.h"
@@ -576,4 +578,51 @@ bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, 
CallExpr *Call) {
   return false;
 }
 
+void SemaOpenCL::checkBuiltinReadImage(FunctionDecl *FDecl, CallExpr *Call) {
+  IdentifierInfo *II = FDecl->getIdentifier();
+  if (!II)
+    return;
+  StringRef Name = II->getName();
+  if (Name != "read_imagei" && Name != "read_imageui")
+    return;
+
+  // read_image{i|ui} take (image, sampler, coord); sampler is arg[1].
+  if (Call->getNumArgs() < 2)
+    return;
+  Expr *SamplerArg = Call->getArg(1);
+  QualType ArgTy = SamplerArg->getType().getCanonicalType();
+  if (!ArgTy->isSamplerT() && !ArgTy->isIntegerType())
+    return;
+
+  Expr *IntExpr = nullptr;
+  Expr *Inner = SamplerArg->IgnoreParenCasts();
+
+  if (auto *DRE = dyn_cast<DeclRefExpr>(Inner)) {
+    if (auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+      if (const Expr *Init = Var->getAnyInitializer()) {
+        Init = Init->IgnoreParenImpCasts();
+        if (Init->getType()->isIntegerType())
+          IntExpr = const_cast<Expr *>(Init);
+      }
+    }
+  } else if (Inner->getType()->isIntegerType()) {
+    IntExpr = Inner;
+  }
+
+  if (!IntExpr)
+    return;
+
+  Expr::EvalResult EVResult;
+  if (!IntExpr->EvaluateAsInt(EVResult, getASTContext()))
+    return;
+
+  uint64_t SamplerValue = EVResult.Val.getInt().getLimitedValue();
+  // Bit layout: |...|FilterMode[5:4]|AddressMode[3:1]|NormalizedCoords[0]|
+  // CLK_FILTER_LINEAR = 0x20 => FilterMode bits = 2
+  if (((SamplerValue & 0x30u) >> 4) == 2)
+    Diag(SamplerArg->getExprLoc(),
+         diag::warn_sampler_argument_invalid_filter)
+        << Name << SamplerArg->getSourceRange();
+}
+
 } // namespace clang
diff --git a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl 
b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
new file mode 100644
index 0000000000000..2a7acff8a8298
--- /dev/null
+++ b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 
-finclude-default-header
+
+// OpenCL spec: read_imagei and read_imageui support nearest filter only.
+// CLK_FILTER_LINEAR in the sampler results in undefined behavior; warn.
+
+// Program scope samplers.
+__constant sampler_t glb_linear =
+    CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | 
CLK_ADDRESS_MIRRORED_REPEAT;
+__constant sampler_t glb_nearest =
+    CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST | 
CLK_ADDRESS_CLAMP_TO_EDGE;
+
+kernel void test_read_imageui_global_sampler(read_only image2d_t img, global 
uint *out) {
+  int2 coord = (int2)(0, 0);
+  *out = read_imageui(img, glb_linear, coord).s0; // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
+  *out = read_imageui(img, glb_nearest, coord).s0; // no warning
+}
+
+kernel void test_read_imagei_global_sampler(read_only image2d_t img, global 
int *out) {
+  int2 coord = (int2)(0, 0);
+  *out = read_imagei(img, glb_linear, coord).s0; // 
expected-warning{{'read_imagei' sampler must use CLK_FILTER_NEAREST}}
+}
+
+kernel void test_read_imageui_local_constant(read_only image2d_t img, global 
uint *out) {
+  __constant sampler_t s_linear =
+      CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP;
+  int2 coord = (int2)(0, 0);
+  *out = read_imageui(img, s_linear, coord).s0; // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
+}
+
+kernel void test_read_imageui_nearest_constant(read_only image2d_t img, global 
uint *out) {
+  __constant sampler_t s_nearest =
+      CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_NONE;
+  int2 coord = (int2)(0, 0);
+  *out = read_imageui(img, s_nearest, coord).s0; // no warning
+}
+
+kernel void test_read_imageui_local(read_only image2d_t img, global uint *out) 
{
+  sampler_t s_linear =
+      CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP;
+  int2 coord = (int2)(0, 0);
+  *out = read_imageui(img, s_linear, coord).s0; // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
+}
+
+kernel void test_read_imageui_nearest(read_only image2d_t img, global uint 
*out) {
+  sampler_t s_nearest =
+      CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_NONE;
+  int2 coord = (int2)(0, 0);
+  *out = read_imageui(img, s_nearest, coord).s0; // no warning
+}
+
+kernel void test_read_imageui_literal(read_only image2d_t img, global uint 
*out) {
+  int2 coord = (int2)(0, 0);
+  // CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP = 0x21
+  *out = read_imageui(img, CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | 
CLK_ADDRESS_CLAMP, coord).s0; // expected-warning{{'read_imageui' sampler must 
use CLK_FILTER_NEAREST}}
+  // CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_NONE = 0x10
+  *out = read_imageui(img, CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | 
CLK_ADDRESS_NONE, coord).s0; // no warning
+}
+
+kernel void test_read_imageui_parameter(read_only image2d_t img, global uint 
*out, sampler_t smp) {
+  int2 coord = (int2)(0, 0);
+  *out = read_imageui(img, smp, coord).s0; // no warning
+}
+
+kernel void test_read_imagef_linear(read_only image2d_t img, global float 
*out) {
+  // read_imagef supports linear filtering: no warning.
+  float2 coord = (float2)(0.5f, 0.5f);
+  *out = read_imagef(img, glb_linear, coord).s0; // no warning
+}

>From be35e55a2c073b300b405297178b2f73ccab7004 Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Tue, 16 Jun 2026 01:49:29 -0700
Subject: [PATCH 2/8] clang-format

---
 clang/lib/Sema/SemaOpenCL.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index d307858e1660f..832c8fd66ba40 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -620,8 +620,7 @@ void SemaOpenCL::checkBuiltinReadImage(FunctionDecl *FDecl, 
CallExpr *Call) {
   // Bit layout: |...|FilterMode[5:4]|AddressMode[3:1]|NormalizedCoords[0]|
   // CLK_FILTER_LINEAR = 0x20 => FilterMode bits = 2
   if (((SamplerValue & 0x30u) >> 4) == 2)
-    Diag(SamplerArg->getExprLoc(),
-         diag::warn_sampler_argument_invalid_filter)
+    Diag(SamplerArg->getExprLoc(), diag::warn_sampler_argument_invalid_filter)
         << Name << SamplerArg->getSourceRange();
 }
 

>From fd22a864e8c55963f90582a1444583c6e030b809 Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Tue, 16 Jun 2026 03:10:02 -0700
Subject: [PATCH 3/8] add -fdeclare-opencl-builtins to fix test on aarch64

---
 clang/test/SemaOpenCL/read-image-integer-linear-filter.cl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl 
b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
index 2a7acff8a8298..3654908f7b925 100644
--- a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
+++ b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 
-finclude-default-header
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 
-fdeclare-opencl-builtins -finclude-default-header
 
 // OpenCL spec: read_imagei and read_imageui support nearest filter only.
 // CLK_FILTER_LINEAR in the sampler results in undefined behavior; warn.

>From 53a69ef3a46ffc1d7ccdada0f4e185b8556b5cd0 Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Thu, 18 Jun 2026 04:35:21 +0200
Subject: [PATCH 4/8] fix getNumArgs check for sampless read

---
 clang/lib/Sema/SemaOpenCL.cpp                          |  5 +++--
 .../SemaOpenCL/read-image-integer-linear-filter.cl     | 10 ++++++++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index 832c8fd66ba40..018a569b81dfd 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -586,8 +586,9 @@ void SemaOpenCL::checkBuiltinReadImage(FunctionDecl *FDecl, 
CallExpr *Call) {
   if (Name != "read_imagei" && Name != "read_imageui")
     return;
 
-  // read_image{i|ui} take (image, sampler, coord); sampler is arg[1].
-  if (Call->getNumArgs() < 2)
+  // read_image{i|ui} with a sampler take (image, sampler, coord).
+  // Bail out samplerless overloads (image, coord) — 2 args.
+  if (Call->getNumArgs() < 3)
     return;
   Expr *SamplerArg = Call->getArg(1);
   QualType ArgTy = SamplerArg->getType().getCanonicalType();
diff --git a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl 
b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
index 3654908f7b925..f606f3d55615a 100644
--- a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
+++ b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
@@ -66,3 +66,13 @@ kernel void test_read_imagef_linear(read_only image2d_t img, 
global float *out)
   float2 coord = (float2)(0.5f, 0.5f);
   *out = read_imagef(img, glb_linear, coord).s0; // no warning
 }
+
+// Samplerless 1D image reads: integer coordinate must not be mistaken for a
+// sampler value even when it looks like CLK_FILTER_LINEAR (e.g. 0x20).
+kernel void test_read_imageui_samplerless(read_only image1d_t img, global uint 
*out) {
+  *out = read_imageui(img, 0x10).s0; // no warning
+  *out = read_imageui(img, 0x20).s0; // no warning
+  *out = read_imageui(img, 0x30).s0; // no warning
+  *out = read_imagei(img, 0x10).s0;  // no warning
+  *out = read_imagei(img, 0x20).s0;  // no warning
+}

>From 5f51cbd19bb2ef8cfe2c16ecfaa0c21147b24228 Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Thu, 18 Jun 2026 04:36:00 +0200
Subject: [PATCH 5/8] use FilterModeMask and value from opencl-c-base.h; add
 comment

---
 clang/lib/Sema/SemaOpenCL.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index 018a569b81dfd..72761ca3ea211 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -618,9 +618,10 @@ void SemaOpenCL::checkBuiltinReadImage(FunctionDecl 
*FDecl, CallExpr *Call) {
     return;
 
   uint64_t SamplerValue = EVResult.Val.getInt().getLimitedValue();
-  // Bit layout: |...|FilterMode[5:4]|AddressMode[3:1]|NormalizedCoords[0]|
-  // CLK_FILTER_LINEAR = 0x20 => FilterMode bits = 2
-  if (((SamplerValue & 0x30u) >> 4) == 2)
+  // Must stay in sync with CLK_FILTER_* defines in opencl-c-base.h.
+  constexpr unsigned FilterModeMask = 0x30u;
+  constexpr unsigned FilterModeLinear = 0x20u;
+  if ((SamplerValue & FilterModeMask) == FilterModeLinear)
     Diag(SamplerArg->getExprLoc(), diag::warn_sampler_argument_invalid_filter)
         << Name << SamplerArg->getSourceRange();
 }

>From acdfc995f0d699f4e50280ecde97e01a82685500 Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Thu, 18 Jun 2026 04:43:46 +0200
Subject: [PATCH 6/8] use local temps in test

---
 .../read-image-integer-linear-filter.cl       | 52 +++++++++----------
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl 
b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
index f606f3d55615a..f1c793199838d 100644
--- a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
+++ b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
@@ -9,70 +9,70 @@ __constant sampler_t glb_linear =
 __constant sampler_t glb_nearest =
     CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST | 
CLK_ADDRESS_CLAMP_TO_EDGE;
 
-kernel void test_read_imageui_global_sampler(read_only image2d_t img, global 
uint *out) {
+kernel void test_read_imageui_global_sampler(read_only image2d_t img) {
   int2 coord = (int2)(0, 0);
-  *out = read_imageui(img, glb_linear, coord).s0; // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
-  *out = read_imageui(img, glb_nearest, coord).s0; // no warning
+  uint4 u = read_imageui(img, glb_linear, coord); // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
+  u = read_imageui(img, glb_nearest, coord); // no warning
 }
 
-kernel void test_read_imagei_global_sampler(read_only image2d_t img, global 
int *out) {
+kernel void test_read_imagei_global_sampler(read_only image2d_t img) {
   int2 coord = (int2)(0, 0);
-  *out = read_imagei(img, glb_linear, coord).s0; // 
expected-warning{{'read_imagei' sampler must use CLK_FILTER_NEAREST}}
+  int4 i = read_imagei(img, glb_linear, coord); // 
expected-warning{{'read_imagei' sampler must use CLK_FILTER_NEAREST}}
 }
 
-kernel void test_read_imageui_local_constant(read_only image2d_t img, global 
uint *out) {
+kernel void test_read_imageui_local_constant(read_only image2d_t img) {
   __constant sampler_t s_linear =
       CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP;
   int2 coord = (int2)(0, 0);
-  *out = read_imageui(img, s_linear, coord).s0; // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
+  uint4 u = read_imageui(img, s_linear, coord); // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
 }
 
-kernel void test_read_imageui_nearest_constant(read_only image2d_t img, global 
uint *out) {
+kernel void test_read_imageui_nearest_constant(read_only image2d_t img) {
   __constant sampler_t s_nearest =
       CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_NONE;
   int2 coord = (int2)(0, 0);
-  *out = read_imageui(img, s_nearest, coord).s0; // no warning
+  uint4 u = read_imageui(img, s_nearest, coord); // no warning
 }
 
-kernel void test_read_imageui_local(read_only image2d_t img, global uint *out) 
{
+kernel void test_read_imageui_local(read_only image2d_t img) {
   sampler_t s_linear =
       CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP;
   int2 coord = (int2)(0, 0);
-  *out = read_imageui(img, s_linear, coord).s0; // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
+  uint4 u = read_imageui(img, s_linear, coord); // 
expected-warning{{'read_imageui' sampler must use CLK_FILTER_NEAREST}}
 }
 
-kernel void test_read_imageui_nearest(read_only image2d_t img, global uint 
*out) {
+kernel void test_read_imageui_nearest(read_only image2d_t img) {
   sampler_t s_nearest =
       CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_NONE;
   int2 coord = (int2)(0, 0);
-  *out = read_imageui(img, s_nearest, coord).s0; // no warning
+  uint4 u = read_imageui(img, s_nearest, coord); // no warning
 }
 
-kernel void test_read_imageui_literal(read_only image2d_t img, global uint 
*out) {
+kernel void test_read_imageui_literal(read_only image2d_t img) {
   int2 coord = (int2)(0, 0);
   // CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP = 0x21
-  *out = read_imageui(img, CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | 
CLK_ADDRESS_CLAMP, coord).s0; // expected-warning{{'read_imageui' sampler must 
use CLK_FILTER_NEAREST}}
+  uint4 u = read_imageui(img, CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR | 
CLK_ADDRESS_CLAMP, coord); // expected-warning{{'read_imageui' sampler must use 
CLK_FILTER_NEAREST}}
   // CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_NONE = 0x10
-  *out = read_imageui(img, CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | 
CLK_ADDRESS_NONE, coord).s0; // no warning
+  u = read_imageui(img, CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | 
CLK_ADDRESS_NONE, coord); // no warning
 }
 
-kernel void test_read_imageui_parameter(read_only image2d_t img, global uint 
*out, sampler_t smp) {
+kernel void test_read_imageui_parameter(read_only image2d_t img, sampler_t 
smp) {
   int2 coord = (int2)(0, 0);
-  *out = read_imageui(img, smp, coord).s0; // no warning
+  uint4 u = read_imageui(img, smp, coord); // no warning
 }
 
-kernel void test_read_imagef_linear(read_only image2d_t img, global float 
*out) {
+kernel void test_read_imagef_linear(read_only image2d_t img) {
   // read_imagef supports linear filtering: no warning.
   float2 coord = (float2)(0.5f, 0.5f);
-  *out = read_imagef(img, glb_linear, coord).s0; // no warning
+  float4 f = read_imagef(img, glb_linear, coord); // no warning
 }
 
 // Samplerless 1D image reads: integer coordinate must not be mistaken for a
 // sampler value even when it looks like CLK_FILTER_LINEAR (e.g. 0x20).
-kernel void test_read_imageui_samplerless(read_only image1d_t img, global uint 
*out) {
-  *out = read_imageui(img, 0x10).s0; // no warning
-  *out = read_imageui(img, 0x20).s0; // no warning
-  *out = read_imageui(img, 0x30).s0; // no warning
-  *out = read_imagei(img, 0x10).s0;  // no warning
-  *out = read_imagei(img, 0x20).s0;  // no warning
+kernel void test_read_imageui_samplerless(read_only image1d_t img) {
+  uint4 u = read_imageui(img, 0x10); // no warning
+  u = read_imageui(img, 0x20); // no warning
+  u = read_imageui(img, 0x30); // no warning
+  int4 i = read_imagei(img, 0x10); // no warning
+  i = read_imagei(img, 0x20); // no warning
 }

>From ff6c83b8f5672d477ff1010976944c5914b001eb Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Thu, 18 Jun 2026 04:56:35 +0200
Subject: [PATCH 7/8] test -Wno-spir-compat suppresses warning

---
 clang/test/SemaOpenCL/read-image-integer-linear-filter.cl | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl 
b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
index f1c793199838d..a90f689a307d9 100644
--- a/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
+++ b/clang/test/SemaOpenCL/read-image-integer-linear-filter.cl
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 
-fdeclare-opencl-builtins -finclude-default-header
+// RUN: %clang_cc1 %s -verify=nowarn -fsyntax-only -cl-std=CL2.0 
-fdeclare-opencl-builtins -finclude-default-header -Wno-spir-compat
+// nowarn-no-diagnostics
 
 // OpenCL spec: read_imagei and read_imageui support nearest filter only.
 // CLK_FILTER_LINEAR in the sampler results in undefined behavior; warn.

>From 7b58e9dfa6095342f0e402b776e90c61e4e3523f Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Sat, 20 Jun 2026 05:06:09 +0200
Subject: [PATCH 8/8] check arg1 is sampler type

---
 clang/lib/Sema/SemaOpenCL.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index 72761ca3ea211..4151972c67473 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -586,14 +586,12 @@ void SemaOpenCL::checkBuiltinReadImage(FunctionDecl 
*FDecl, CallExpr *Call) {
   if (Name != "read_imagei" && Name != "read_imageui")
     return;
 
-  // read_image{i|ui} with a sampler take (image, sampler, coord).
-  // Bail out samplerless overloads (image, coord) — 2 args.
-  if (Call->getNumArgs() < 3)
+  if (FDecl->getNumParams() < 2)
     return;
-  Expr *SamplerArg = Call->getArg(1);
-  QualType ArgTy = SamplerArg->getType().getCanonicalType();
-  if (!ArgTy->isSamplerT() && !ArgTy->isIntegerType())
+  QualType ParamTy = FDecl->getParamDecl(1)->getType().getCanonicalType();
+  if (!ParamTy->isSamplerT())
     return;
+  Expr *SamplerArg = Call->getArg(1);
 
   Expr *IntExpr = nullptr;
   Expr *Inner = SamplerArg->IgnoreParenCasts();

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

Reply via email to