File tree Expand file tree Collapse file tree 2 files changed +8
-18
lines changed Expand file tree Collapse file tree 2 files changed +8
-18
lines changed Original file line number Diff line number Diff line change 9
9
#include < quick-lint-js/util/narrow-cast.h>
10
10
11
11
namespace quick_lint_js {
12
- // Only permit tested specializations, and disallow implicit conversions (e.g.
13
- // long -> int).
14
12
template <class T >
15
- std::optional<T> checked_add (T x, T y) noexcept = delete;
16
-
17
- template <>
18
- inline std::optional<int > checked_add (int x, int y) noexcept {
19
- using out = int ;
20
- using wider_int = long long ;
21
- constexpr out out_max = (std::numeric_limits<out>::max)();
22
- constexpr out out_min = std::numeric_limits<out>::lowest ();
23
- static_assert (std::numeric_limits<wider_int>::lowest () / 2 <= out_min);
24
- static_assert (out_max <= (std::numeric_limits<wider_int>::max)() / 2 );
25
-
26
- wider_int sum = static_cast <wider_int>(x) + static_cast <wider_int>(y);
27
- if (in_range<out>(sum)) {
28
- return static_cast <out>(sum);
29
- } else {
13
+ std::enable_if_t <std::is_signed_v<T> && std::is_integral_v<T>, std::optional<T>>
14
+ checked_add (T x, T y) noexcept {
15
+ // https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
16
+ constexpr T t_max = (std::numeric_limits<T>::max)();
17
+ constexpr T t_min = std::numeric_limits<T>::lowest ();
18
+ if (((y > 0 ) && (x > (t_max - y))) || ((y < 0 ) && (x < (t_min - y)))) {
30
19
return std::nullopt;
31
20
}
21
+ return x + y;
32
22
}
33
23
}
34
24
Original file line number Diff line number Diff line change @@ -11,7 +11,7 @@ namespace quick_lint_js {
11
11
namespace {
12
12
template <class BoolVector16 >
13
13
class test_math_checked_add_signed : public ::testing::Test {};
14
- using signed_types = ::testing::Types<int >;
14
+ using signed_types = ::testing::Types<int , long , long long >;
15
15
TYPED_TEST_SUITE (test_math_checked_add_signed, signed_types,
16
16
::testing::internal::DefaultNameGenerator);
17
17
You can’t perform that action at this time.
0 commit comments