Skip to content

Commit 1cb1407

Browse files
authored
[HLSL] Add bounds checks for the hlsl vector arguments and return types (#130724)
fixes #129003 - fix up sema tests - fix up templates for scalar and vector HLSL intrinsic overloads
1 parent 456fa47 commit 1cb1407

File tree

6 files changed

+161
-59
lines changed

6 files changed

+161
-59
lines changed

clang/lib/Headers/hlsl/hlsl_detail.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ template <typename T> struct is_arithmetic {
4545
static const bool Value = __is_arithmetic(T);
4646
};
4747

48+
template <typename T, int N>
49+
using HLSL_FIXED_VECTOR =
50+
vector<__detail::enable_if_t<(N > 1 && N <= 4), T>, N>;
51+
4852
} // namespace __detail
4953
} // namespace hlsl
5054
#endif //_HLSL_HLSL_DETAILS_H_

clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ constexpr vector<uint, 4> d3d_color_to_ubyte4_impl(vector<float, 4> V) {
2323
return V.zyxw * 255.001953f;
2424
}
2525

26-
template <typename T>
27-
constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
28-
length_impl(T X) {
29-
return abs(X);
30-
}
26+
template <typename T> constexpr T length_impl(T X) { return abs(X); }
3127

3228
template <typename T, int N>
3329
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) {
3935
#endif
4036
}
4137

42-
template <typename T>
43-
constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
44-
distance_impl(T X, T Y) {
38+
template <typename T> constexpr T distance_impl(T X, T Y) {
4539
return length_impl(X - Y);
4640
}
4741

@@ -51,9 +45,7 @@ distance_vec_impl(vector<T, N> X, vector<T, N> Y) {
5145
return length_vec_impl(X - Y);
5246
}
5347

54-
template <typename T>
55-
constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
56-
reflect_impl(T I, T N) {
48+
template <typename T> constexpr T reflect_impl(T I, T N) {
5749
return I - 2 * N * I * N;
5850
}
5951

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,31 @@ void asuint(double4, out uint4, out uint4);
8989
/// \param X The X input value.
9090
/// \param Y The Y input value.
9191

92+
template <typename T>
9293
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
93-
const inline half distance(half X, half Y) {
94+
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
95+
__detail::is_same<half, T>::value,
96+
T> distance(T X, T Y) {
9497
return __detail::distance_impl(X, Y);
9598
}
9699

97-
const inline float distance(float X, float Y) {
100+
template <typename T>
101+
const inline __detail::enable_if_t<
102+
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
103+
distance(T X, T Y) {
98104
return __detail::distance_impl(X, Y);
99105
}
100106

101107
template <int N>
102108
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
103-
const inline half distance(vector<half, N> X, vector<half, N> Y) {
109+
const inline half distance(__detail::HLSL_FIXED_VECTOR<half, N> X,
110+
__detail::HLSL_FIXED_VECTOR<half, N> Y) {
104111
return __detail::distance_vec_impl(X, Y);
105112
}
106113

107114
template <int N>
108-
const inline float distance(vector<float, N> X, vector<float, N> Y) {
115+
const inline float distance(__detail::HLSL_FIXED_VECTOR<float, N> X,
116+
__detail::HLSL_FIXED_VECTOR<float, N> Y) {
109117
return __detail::distance_vec_impl(X, Y);
110118
}
111119

@@ -119,17 +127,29 @@ const inline float distance(vector<float, N> X, vector<float, N> Y) {
119127
///
120128
/// Length is based on the following formula: sqrt(x[0]^2 + x[1]^2 + ...).
121129

130+
template <typename T>
122131
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
123-
const inline half length(half X) { return __detail::length_impl(X); }
124-
const inline float length(float X) { return __detail::length_impl(X); }
132+
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
133+
__detail::is_same<half, T>::value,
134+
T> length(T X) {
135+
return __detail::length_impl(X);
136+
}
137+
138+
template <typename T>
139+
const inline __detail::enable_if_t<
140+
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
141+
length(T X) {
142+
return __detail::length_impl(X);
143+
}
125144

126145
template <int N>
127146
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
128-
const inline half length(vector<half, N> X) {
147+
const inline half length(__detail::HLSL_FIXED_VECTOR<half, N> X) {
129148
return __detail::length_vec_impl(X);
130149
}
131150

132-
template <int N> const inline float length(vector<float, N> X) {
151+
template <int N>
152+
const inline float length(__detail::HLSL_FIXED_VECTOR<float, N> X) {
133153
return __detail::length_vec_impl(X);
134154
}
135155

@@ -173,23 +193,33 @@ constexpr vector<uint, 4> D3DCOLORtoUBYTE4(vector<float, 4> V) {
173193
///
174194
/// Result type and the type of all operands must be the same type.
175195

196+
template <typename T>
176197
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
177-
const inline half reflect(half I, half N) {
198+
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
199+
__detail::is_same<half, T>::value,
200+
T> reflect(T I, T N) {
178201
return __detail::reflect_impl(I, N);
179202
}
180203

181-
const inline float reflect(float I, float N) {
204+
template <typename T>
205+
const inline __detail::enable_if_t<
206+
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
207+
reflect(T I, T N) {
182208
return __detail::reflect_impl(I, N);
183209
}
184210

185211
template <int L>
186212
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
187-
const inline vector<half, L> reflect(vector<half, L> I, vector<half, L> N) {
213+
const inline __detail::HLSL_FIXED_VECTOR<half, L> reflect(
214+
__detail::HLSL_FIXED_VECTOR<half, L> I,
215+
__detail::HLSL_FIXED_VECTOR<half, L> N) {
188216
return __detail::reflect_vec_impl(I, N);
189217
}
190218

191219
template <int L>
192-
const inline vector<float, L> reflect(vector<float, L> I, vector<float, L> N) {
220+
const inline __detail::HLSL_FIXED_VECTOR<float, L>
221+
reflect(__detail::HLSL_FIXED_VECTOR<float, L> I,
222+
__detail::HLSL_FIXED_VECTOR<float, L> N) {
193223
return __detail::reflect_vec_impl(I, N);
194224
}
195225
} // namespace hlsl

clang/test/SemaHLSL/BuiltIns/distance-errors.hlsl

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,55 @@
33
float test_no_second_arg(float2 p0) {
44
return distance(p0);
55
// expected-error@-1 {{no matching function for call to 'distance'}}
6-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 1 was provided}}
7-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 1 was provided}}
6+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
7+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
88
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
99
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 1 was provided}}
1010
}
1111

1212
float test_too_many_arg(float2 p0) {
1313
return distance(p0, p0, p0);
1414
// expected-error@-1 {{no matching function for call to 'distance'}}
15-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
16-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
15+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
16+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
1717
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
1818
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 2 arguments, but 3 were provided}}
1919
}
2020

2121
float test_double_inputs(double p0, double p1) {
2222
return distance(p0, p1);
23-
// expected-error@-1 {{call to 'distance' is ambiguous}}
24-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
25-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
23+
// expected-error@-1 {{no matching function for call to 'distance'}}
24+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
25+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
26+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
27+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
2628
}
2729

2830
float test_int_inputs(int p0, int p1) {
2931
return distance(p0, p1);
30-
// expected-error@-1 {{call to 'distance' is ambiguous}}
31-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
32-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
32+
// expected-error@-1 {{no matching function for call to 'distance'}}
33+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
34+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
35+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
36+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
37+
}
38+
39+
float1 test_vec1_inputs(float1 p0, float1 p1) {
40+
return distance(p0, p1);
41+
// expected-error@-1 {{no matching function for call to 'distance'}}
42+
// expected-note@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>>'}}
43+
// expected-note@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>>'}}
44+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
45+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
46+
}
47+
48+
typedef float float5 __attribute__((ext_vector_type(5)));
49+
50+
float5 test_vec5_inputs(float5 p0, float5 p1) {
51+
return distance(p0, p1);
52+
// expected-error@-1 {{no matching function for call to 'distance'}}
53+
// expected-note@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>>'}}
54+
// expected-note@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>>'}}
55+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
56+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
3357
}

clang/test/SemaHLSL/BuiltIns/length-errors.hlsl

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ void test_too_few_arg()
44
{
55
return length();
66
// expected-error@-1 {{no matching function for call to 'length'}}
7-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but no arguments were provided}}
8-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but no arguments were provided}}
7+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
8+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
99
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
1010
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but no arguments were provided}}
1111
}
@@ -14,40 +14,68 @@ void test_too_many_arg(float2 p0)
1414
{
1515
return length(p0, p0);
1616
// expected-error@-1 {{no matching function for call to 'length'}}
17-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but 2 arguments were provided}}
1817
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
19-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires single argument 'X', but 2 arguments were provided}}
18+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
19+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
2020
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires single argument 'X', but 2 arguments were provided}}
2121
}
2222

2323
float double_to_float_type(double p0) {
2424
return length(p0);
25-
// expected-error@-1 {{call to 'length' is ambiguous}}
26-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
27-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
25+
// expected-error@-1 {{no matching function for call to 'length'}}
26+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = double]: no type named 'Type' in 'hlsl::__detail::enable_if<false, double>'}}
27+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = double]: no type named 'Type' in 'hlsl::__detail::enable_if<false, double>'}}
28+
// expected-note@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'}}
29+
// expected-note@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'}}
2830
}
2931

3032

3133
float bool_to_float_type_promotion(bool p1)
3234
{
3335
return length(p1);
34-
// expected-error@-1 {{call to 'length' is ambiguous}}
35-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
36-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
36+
// expected-error@-1 {{no matching function for call to 'length'}}
37+
// expected-note@hlsl/hlsl_intrinsics.h:* {{andidate template ignored: substitution failure [with T = bool]: no type named 'Type' in 'hlsl::__detail::enable_if<false, bool>'}}
38+
// expected-note@hlsl/hlsl_intrinsics.h:* {{andidate template ignored: substitution failure [with T = bool]: no type named 'Type' in 'hlsl::__detail::enable_if<false, bool>'}}
39+
// expected-note@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'}}
40+
// expected-note@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'}}
3741
}
3842

3943
float length_int_to_float_promotion(int p1)
4044
{
4145
return length(p1);
42-
// expected-error@-1 {{call to 'length' is ambiguous}}
43-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
44-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
46+
// expected-error@-1 {{no matching function for call to 'length'}}
47+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int]: no type named 'Type' in 'hlsl::__detail::enable_if<false, int>'}}
48+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int]: no type named 'Type' in 'hlsl::__detail::enable_if<false, int>'}}
49+
// expected-note@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'}}
50+
// expected-note@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'}}
4551
}
4652

4753
float2 length_int2_to_float2_promotion(int2 p1)
4854
{
4955
return length(p1);
50-
// expected-error@-1 {{call to 'length' is ambiguous}}
51-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
52-
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function}}
56+
// expected-error@-1 {{no matching function for call to 'length'}}
57+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int2]}}
58+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = int2]}}
59+
// expected-note@hlsl/hlsl_intrinsics.h:* {{1st parameter does not match adjusted type 'vector<int, [...]>' of argument [with N = 2]}}
60+
// expected-note@hlsl/hlsl_intrinsics.h:* {{1st parameter does not match adjusted type 'vector<int, [...]>' of argument [with N = 2]}}
61+
}
62+
63+
float1 test_vec1_inputs(float1 p0) {
64+
return length(p0);
65+
// expected-error@-1 {{no matching function for call to 'length'}}
66+
// expected-note@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>>'}}
67+
// expected-note@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>>'}}
68+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
69+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
70+
}
71+
72+
typedef float float5 __attribute__((ext_vector_type(5)));
73+
74+
float5 test_vec5_inputs(float5 p0) {
75+
return length(p0);
76+
// expected-error@-1 {{no matching function for call to 'length'}}
77+
// expected-note@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>>'}}
78+
// expected-note@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>>'}}
79+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
80+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with N = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
5381
}

0 commit comments

Comments
 (0)