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
