[clang] [HLSL] Add bounds checks for the hlsl vector arguments and return types (PR #130724)

Farzon Lotfi via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 10 23:34:48 PDT 2025


https://github.com/farzonl created https://github.com/llvm/llvm-project/pull/130724

fixes #129003
- fix up sema tests
- fix up templates for scalar and vector HLSL intrinsic overloads

>From 80f6687b461c6256aa5bacb3bbd080a58e37573b Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Mon, 10 Mar 2025 21:03:49 -0400
Subject: [PATCH] [HLSL] Add bounds checks for the hlsl vector arguments and
 return types

fixes #129003
- fix up sema tests
- fix up templates for scalar and vector HLSL intrinsic overloads
---
 clang/lib/Headers/hlsl/hlsl_detail.h          |  4 ++
 .../lib/Headers/hlsl/hlsl_intrinsic_helpers.h | 14 +----
 clang/lib/Headers/hlsl/hlsl_intrinsics.h      | 54 +++++++++++++----
 .../SemaHLSL/BuiltIns/distance-errors.hlsl    | 44 ++++++++++----
 .../test/SemaHLSL/BuiltIns/length-errors.hlsl | 60 ++++++++++++++-----
 .../SemaHLSL/BuiltIns/reflect-errors.hlsl     | 44 ++++++++++----
 6 files changed, 161 insertions(+), 59 deletions(-)

diff --git a/clang/lib/Headers/hlsl/hlsl_detail.h b/clang/lib/Headers/hlsl/hlsl_detail.h
index c691d85283de4..80c4900121dfb 100644
--- a/clang/lib/Headers/hlsl/hlsl_detail.h
+++ b/clang/lib/Headers/hlsl/hlsl_detail.h
@@ -45,6 +45,10 @@ template <typename T> struct is_arithmetic {
   static const bool Value = __is_arithmetic(T);
 };
 
+template <typename T, int N>
+using HLSL_FIXED_VECTOR =
+    vector<__detail::enable_if_t<(N > 1 && N <= 4), T>, N>;
+
 } // namespace __detail
 } // namespace hlsl
 #endif //_HLSL_HLSL_DETAILS_H_
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index 6783e23f6346d..87b52792447f6 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -23,11 +23,7 @@ constexpr vector<uint, 4> d3d_color_to_ubyte4_impl(vector<float, 4> V) {
   return V.zyxw * 255.001953f;
 }
 
-template <typename T>
-constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
-length_impl(T X) {
-  return abs(X);
-}
+template <typename T> constexpr T length_impl(T X) { return abs(X); }
 
 template <typename T, int N>
 constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
@@ -39,9 +35,7 @@ length_vec_impl(vector<T, N> X) {
 #endif
 }
 
-template <typename T>
-constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
-distance_impl(T X, T Y) {
+template <typename T> constexpr T distance_impl(T X, T Y) {
   return length_impl(X - Y);
 }
 
@@ -51,9 +45,7 @@ distance_vec_impl(vector<T, N> X, vector<T, N> Y) {
   return length_vec_impl(X - Y);
 }
 
-template <typename T>
-constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
-reflect_impl(T I, T N) {
+template <typename T> constexpr T reflect_impl(T I, T N) {
   return I - 2 * N * I * N;
 }
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index cd6d836578787..3fadd45ecabb7 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -89,23 +89,31 @@ void asuint(double4, out uint4, out uint4);
 /// \param X The X input value.
 /// \param Y The Y input value.
 
+template <typename T>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline half distance(half X, half Y) {
+const inline __detail::enable_if_t<
+    __detail::is_arithmetic<T>::Value &&
+    __detail::is_same<half, T>::value> distance(T X, T Y) {
   return __detail::distance_impl(X, Y);
 }
 
-const inline float distance(float X, float Y) {
+template <typename T>
+const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
+                                   __detail::is_same<float, T>::value>
+distance(T X, T Y) {
   return __detail::distance_impl(X, Y);
 }
 
 template <int N>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline half distance(vector<half, N> X, vector<half, N> Y) {
+const inline half distance(__detail::HLSL_FIXED_VECTOR<half, N> X,
+                           __detail::HLSL_FIXED_VECTOR<half, N> Y) {
   return __detail::distance_vec_impl(X, Y);
 }
 
 template <int N>
-const inline float distance(vector<float, N> X, vector<float, N> Y) {
+const inline float distance(__detail::HLSL_FIXED_VECTOR<float, N> X,
+                            __detail::HLSL_FIXED_VECTOR<float, N> Y) {
   return __detail::distance_vec_impl(X, Y);
 }
 
@@ -119,17 +127,29 @@ const inline float distance(vector<float, N> X, vector<float, N> Y) {
 ///
 /// Length is based on the following formula: sqrt(x[0]^2 + x[1]^2 + ...).
 
+template <typename T>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline half length(half X) { return __detail::length_impl(X); }
-const inline float length(float X) { return __detail::length_impl(X); }
+const inline __detail::enable_if_t<
+    __detail::is_arithmetic<T>::Value &&
+    __detail::is_same<half, T>::value> length(T X) {
+  return __detail::length_impl(X);
+}
+
+template <typename T>
+const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
+                                   __detail::is_same<float, T>::value>
+length(T X) {
+  return __detail::length_impl(X);
+}
 
 template <int N>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline half length(vector<half, N> X) {
+const inline half length(__detail::HLSL_FIXED_VECTOR<half, N> X) {
   return __detail::length_vec_impl(X);
 }
 
-template <int N> const inline float length(vector<float, N> X) {
+template <int N>
+const inline float length(__detail::HLSL_FIXED_VECTOR<float, N> X) {
   return __detail::length_vec_impl(X);
 }
 
@@ -173,23 +193,33 @@ constexpr vector<uint, 4> D3DCOLORtoUBYTE4(vector<float, 4> V) {
 ///
 /// Result type and the type of all operands must be the same type.
 
+template <typename T>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline half reflect(half I, half N) {
+const inline __detail::enable_if_t<
+    __detail::is_arithmetic<T>::Value &&
+    __detail::is_same<half, T>::value> reflect(T I, T N) {
   return __detail::reflect_impl(I, N);
 }
 
-const inline float reflect(float I, float N) {
+template <typename T>
+const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
+                                   __detail::is_same<float, T>::value>
+reflect(T I, T N) {
   return __detail::reflect_impl(I, N);
 }
 
 template <int L>
 _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-const inline vector<half, L> reflect(vector<half, L> I, vector<half, L> N) {
+const inline __detail::HLSL_FIXED_VECTOR<half, L> reflect(
+    __detail::HLSL_FIXED_VECTOR<half, L> I,
+    __detail::HLSL_FIXED_VECTOR<half, L> N) {
   return __detail::reflect_vec_impl(I, N);
 }
 
 template <int L>
-const inline vector<float, L> reflect(vector<float, L> I, vector<float, L> N) {
+const inline __detail::HLSL_FIXED_VECTOR<float, L>
+reflect(__detail::HLSL_FIXED_VECTOR<float, L> I,
+        __detail::HLSL_FIXED_VECTOR<float, L> N) {
   return __detail::reflect_vec_impl(I, N);
 }
 } // namespace hlsl
diff --git a/clang/test/SemaHLSL/BuiltIns/distance-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/distance-errors.hlsl
index e996bf5d2cb7c..0ddde79c5ef10 100644
--- a/clang/test/SemaHLSL/BuiltIns/distance-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/distance-errors.hlsl
@@ -3,8 +3,8 @@
 float test_no_second_arg(float2 p0) {
   return distance(p0);
   // expected-error at -1 {{no matching function for call to 'distance'}}
-  // 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 distance(p0, p0, p0);
   // expected-error at -1 {{no matching function for call to 'distance'}}
-  // 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 distance(p0, p1);
-  // expected-error at -1  {{call to 'distance' 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 'distance'}}
+  // 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 distance(p0, p1);
-  // expected-error at -1  {{call to 'distance' 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 'distance'}}
+  // 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 distance(p0, p1);
+  // expected-error at -1  {{no matching function for call to 'distance'}}
+  // 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, void>'}}
+  // 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, void>'}}
+  // 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 distance(p0, p1);
+  // expected-error at -1  {{no matching function for call to 'distance'}}
+  // 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, void>'}}
+  // 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, void>'}}
+  // 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>'}}
 }
diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
index a191f0419fbba..4ec3c7f3fee44 100644
--- a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
@@ -4,8 +4,8 @@ void test_too_few_arg()
 {
   return length();
   // expected-error at -1 {{no matching function for call to 'length'}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but no arguments were provided}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but no arguments were provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
 }
@@ -14,40 +14,68 @@ void test_too_many_arg(float2 p0)
 {
   return length(p0, p0);
   // expected-error at -1 {{no matching function for call to 'length'}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but 2 arguments were provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
-  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but 2 arguments were provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
   // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
 }
 
 float double_to_float_type(double p0) {
   return length(p0);
-  // expected-error at -1  {{call to 'length' 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 'length'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = double]: no type named 'Type' in 'hlsl::__detail::enable_if<false, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = double]: no type named 'Type' in 'hlsl::__detail::enable_if<false, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match '__detail::HLSL_FIXED_VECTOR<half, N>' (aka 'vector<__detail::enable_if_t<(N > 1 && N <= 4), half>, N>') against 'double'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match '__detail::HLSL_FIXED_VECTOR<float, N>' (aka 'vector<__detail::enable_if_t<(N > 1 && N <= 4), float>, N>') against 'double'}}
 }
 
 
 float bool_to_float_type_promotion(bool p1)
 {
   return length(p1);
-  // expected-error at -1  {{call to 'length' 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 'length'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = bool]: no type named 'Type' in 'hlsl::__detail::enable_if<false, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = bool]: no type named 'Type' in 'hlsl::__detail::enable_if<false, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match '__detail::HLSL_FIXED_VECTOR<half, N>' (aka 'vector<__detail::enable_if_t<(N > 1 && N <= 4), half>, N>') against 'bool'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match '__detail::HLSL_FIXED_VECTOR<float, N>' (aka 'vector<__detail::enable_if_t<(N > 1 && N <= 4), float>, N>') against 'bool'}}
 }
 
 float length_int_to_float_promotion(int p1)
 {
   return length(p1);
-  // expected-error at -1  {{call to 'length' 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 'length'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int]: no type named 'Type' in 'hlsl::__detail::enable_if<false, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int]: no type named 'Type' in 'hlsl::__detail::enable_if<false, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match '__detail::HLSL_FIXED_VECTOR<half, N>' (aka 'vector<__detail::enable_if_t<(N > 1 && N <= 4), half>, N>') against 'int'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: could not match '__detail::HLSL_FIXED_VECTOR<float, N>' (aka 'vector<__detail::enable_if_t<(N > 1 && N <= 4), float>, N>') against 'int'}}
 }
 
 float2 length_int2_to_float2_promotion(int2 p1)
 {
   return length(p1);
-  // expected-error at -1  {{call to 'length' 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 'length'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int2]}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int2]}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{1st parameter does not match adjusted type 'vector<int, [...]>' of argument [with N = 2]}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{1st parameter does not match adjusted type 'vector<int, [...]>' of argument [with N = 2]}}
+}
+
+float1 test_vec1_inputs(float1 p0) {
+  return length(p0);
+  // expected-error at -1  {{no matching function for call to 'length'}}
+  // 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, void>'}}
+  // 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, void>'}}
+  // 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) {
+  return length(p0);
+  // expected-error at -1  {{no matching function for call to 'length'}}
+  // 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, void>'}}
+  // 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, void>'}}
+  // 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>'}}
 }
diff --git a/clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl
index 28cf992ed602b..4535991a859aa 100644
--- a/clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/reflect-errors.hlsl
@@ -3,8 +3,8 @@
 float test_no_second_arg(float2 p0) {
   return reflect(p0);
   // expected-error at -1 {{no matching function for call to 'reflect'}}
-  // 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 reflect(p0, p0, p0);
   // expected-error at -1 {{no matching function for call to 'reflect'}}
-  // 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 reflect(p0, p1);
-  // expected-error at -1  {{call to 'reflect' 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 'reflect'}}
+  // 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 reflect(p0, p1);
-  // expected-error at -1  {{call to 'reflect' 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 'reflect'}}
+  // 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 reflect(p0, p1);
+  // expected-error at -1  {{no matching function for call to 'reflect'}}
+  // 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, void>'}}
+  // 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, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 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 L = 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 reflect(p0, p1);
+  // expected-error at -1  {{no matching function for call to 'reflect'}}
+  // 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, void>'}}
+  // 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, void>'}}
+  // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 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 L = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
 }



More information about the cfe-commits mailing list