[clang] [HLSL] Add bounds checks for the HLSL `fmod` vector arguments and return types (PR #131035)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 12 14:34:57 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-hlsl

Author: Kaitlin Peng (kmpeng)

<details>
<summary>Changes</summary>

Fixes #<!-- -->131024.
- Fixes template for scalar and vector `fmod` intrinsic overloads
- Fixes `fmod` Sema test

---
Full diff: https://github.com/llvm/llvm-project/pull/131035.diff


3 Files Affected:

- (modified) clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h (+1-3) 
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+18-4) 
- (modified) clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl (+34-10) 


``````````diff
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index 5f7c047dbf340..89ab664e90ba9 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -58,9 +58,7 @@ constexpr vector<T, L> reflect_vec_impl(vector<T, L> I, vector<T, L> N) {
 #endif
 }
 
-template <typename T>
-constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
-fmod_impl(T X, T Y) {
+template <typename T> constexpr T fmod_impl(T X, T Y) {
 #if !defined(__DIRECTX__)
   return __builtin_elementwise_fmod(X, Y);
 #else
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 5459cbeb34fd0..a48a8e998a015 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -129,19 +129,33 @@ const inline float distance(__detail::HLSL_FIXED_VECTOR<float, N> X,
 /// Return the floating-point remainder of the x parameter divided by the y
 /// parameter.
 
+template <typename T>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline half fmod(half X, half Y) { return __detail::fmod_impl(X, Y); }
+const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
+                                       __detail::is_same<half, T>::value,
+                                   T> fmod(T X, T Y) {
+  return __detail::fmod_impl(X, Y);
+}
 
-const inline float fmod(float X, float Y) { return __detail::fmod_impl(X, Y); }
+template <typename T>
+const inline __detail::enable_if_t<
+    __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
+fmod(T X, T Y) {
+  return __detail::fmod_impl(X, Y);
+}
 
 template <int N>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline vector<half, N> fmod(vector<half, N> X, vector<half, N> Y) {
+const inline __detail::HLSL_FIXED_VECTOR<half, N> fmod(
+    __detail::HLSL_FIXED_VECTOR<half, N> X,
+    __detail::HLSL_FIXED_VECTOR<half, N> Y) {
   return __detail::fmod_vec_impl(X, Y);
 }
 
 template <int N>
-const inline vector<float, N> fmod(vector<float, N> X, vector<float, N> Y) {
+const inline __detail::HLSL_FIXED_VECTOR<float, N>
+fmod(__detail::HLSL_FIXED_VECTOR<float, N> X,
+     __detail::HLSL_FIXED_VECTOR<float, N> Y) {
   return __detail::fmod_vec_impl(X, Y);
 }
 
diff --git a/clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl
index 86f5a6f7bea9c..fc931139e523d 100644
--- a/clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl
@@ -3,8 +3,8 @@
 float test_no_second_arg(float2 p0) {
   return fmod(p0);
   // expected-error at -1 {{no matching function for call to 'fmod'}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 1 was provided}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
 }
@@ -12,22 +12,46 @@ float test_no_second_arg(float2 p0) {
 float test_too_many_arg(float2 p0) {
   return fmod(p0, p0, p0);
   // expected-error at -1 {{no matching function for call to 'fmod'}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
 }
 
 float test_double_inputs(double p0, double p1) {
   return fmod(p0, p1);
-  // expected-error at -1  {{call to 'fmod' is ambiguous}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function}}
+  // expected-error at -1  {{no matching function for call to 'fmod'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
 }
 
 float test_int_inputs(int p0, int p1) {
   return fmod(p0, p1);
-  // expected-error at -1  {{call to 'fmod' is ambiguous}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function}}
+  // expected-error at -1  {{no matching function for call to 'fmod'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+}
+
+float1 test_vec1_inputs(float1 p0, float1 p1) {
+  return fmod(p0, p1);
+  // expected-error at -1  {{no matching function for call to 'fmod'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
+}
+
+typedef float float5 __attribute__((ext_vector_type(5)));
+
+float5 test_vec5_inputs(float5 p0, float5 p1) {
+  return fmod(p0, p1);
+  // expected-error at -1  {{no matching function for call to 'fmod'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 5>>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 5>>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/131035


More information about the cfe-commits mailing list