tint: fix const eval of divide to emit errors on dbz and min/-1
Bug: tint:1581
Change-Id: I0459a7feb1be17f3570b68b54f1a0e0a1723880b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112180
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index b7674dc..7195824 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -779,24 +779,22 @@
}
} else {
using T = UnwrapNumber<NumberT>;
- auto divide_values = [](T lhs, T rhs) {
- if constexpr (std::is_integral_v<T>) {
- // For integers, lhs / 0 returns lhs
- if (rhs == 0) {
- return lhs;
- }
-
- if constexpr (std::is_signed_v<T>) {
- // For signed integers, for lhs / -1, return lhs if lhs is the
- // most negative value
- if (rhs == -1 && lhs == std::numeric_limits<T>::min()) {
- return lhs;
- }
- }
+ auto lhs = a.value;
+ auto rhs = b.value;
+ if (rhs == 0) {
+ // For integers (as for floats), lhs / 0 is an error
+ AddError(OverflowErrorMessage(a, "/", b), source);
+ return utils::Failure;
+ }
+ if constexpr (std::is_signed_v<T>) {
+ // For signed integers, lhs / -1 where lhs is the
+ // most negative value is an error
+ if (rhs == -1 && lhs == std::numeric_limits<T>::min()) {
+ AddError(OverflowErrorMessage(a, "/", b), source);
+ return utils::Failure;
}
- return lhs / rhs;
- };
- result = divide_values(a.value, b.value);
+ }
+ result = lhs / rhs;
}
return result;
}
diff --git a/src/tint/resolver/const_eval_binary_op_test.cc b/src/tint/resolver/const_eval_binary_op_test.cc
index a35214a..f621c61 100644
--- a/src/tint/resolver/const_eval_binary_op_test.cc
+++ b/src/tint/resolver/const_eval_binary_op_test.cc
@@ -419,36 +419,31 @@
template <typename T>
std::vector<Case> OpDivIntCases() {
- std::vector<Case> r = {
- C(Val(T{0}), Val(T{1}), Val(T{0})),
- C(Val(T{1}), Val(T{1}), Val(T{1})),
- C(Val(T{1}), Val(T{1}), Val(T{1})),
- C(Val(T{2}), Val(T{1}), Val(T{2})),
- C(Val(T{4}), Val(T{2}), Val(T{2})),
- C(Val(T::Highest()), Val(T{1}), Val(T::Highest())),
- C(Val(T::Lowest()), Val(T{1}), Val(T::Lowest())),
- C(Val(T::Highest()), Val(T::Highest()), Val(T{1})),
- C(Val(T{0}), Val(T::Highest()), Val(T{0})),
- C(Val(T{0}), Val(T::Lowest()), Val(T{0})),
- };
- ConcatIntoIf<!IsAbstract<T> && IsIntegral<T>>( //
- r, std::vector<Case>{
- // e1, when e2 is zero.
- C(T{123}, T{0}, T{123}),
- });
- ConcatIntoIf<!IsAbstract<T> && IsSignedIntegral<T>>( //
- r, std::vector<Case>{
- // e1, when e1 is the most negative value in T, and e2 is -1.
- C(T::Smallest(), T{-1}, T::Smallest()),
- });
-
auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "/", b);
};
- ConcatIntoIf<IsAbstract<T>>( //
+
+ std::vector<Case> r = {
+ C(T{0}, T{1}, T{0}),
+ C(T{1}, T{1}, T{1}),
+ C(T{1}, T{1}, T{1}),
+ C(T{2}, T{1}, T{2}),
+ C(T{4}, T{2}, T{2}),
+ C(T::Highest(), T{1}, T::Highest()),
+ C(T::Lowest(), T{1}, T::Lowest()),
+ C(T::Highest(), T::Highest(), T{1}),
+ C(T{0}, T::Highest(), T{0}),
+
+ // Divide by zero
+ E(T{123}, T{0}, error_msg(T{123}, T{0})),
+ E(T::Highest(), T{0}, error_msg(T::Highest(), T{0})),
+ E(T::Lowest(), T{0}, error_msg(T::Lowest(), T{0})),
+ };
+
+ // Error on most negative divided by -1
+ ConcatIntoIf<IsSignedIntegral<T>>( //
r, std::vector<Case>{
- // Most negative value divided by -1
- E(AInt::Lowest(), -1_a, error_msg(AInt::Lowest(), -1_a)),
+ E(T::Lowest(), T{-1}, error_msg(T::Lowest(), T{-1})),
});
return r;
}