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>
This commit is contained in:
parent
ec7a1d2a1b
commit
775dfbf7a8
|
@ -779,24 +779,22 @@ utils::Result<NumberT> ConstEval::Div(const Source& source, NumberT a, NumberT b
|
|||
}
|
||||
} 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;
|
||||
}
|
||||
|
|
|
@ -419,36 +419,31 @@ INSTANTIATE_TEST_SUITE_P(Mul,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue