diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2019-08-28 18:26:07 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-08-28 18:26:07 +0000 |
commit | d6f11844f1c17a675c335ea95f7a49736eb653e9 (patch) | |
tree | c712e6d4a4a373a4aff7b249fb44072e4640cbcc /src/mongo/platform | |
parent | 0a0625f43e4fa34302c7bc4757b0f273782925b5 (diff) | |
download | mongo-d6f11844f1c17a675c335ea95f7a49736eb653e9.tar.gz |
SERVER-43032 simplify overflow_arithmetic.h
Diffstat (limited to 'src/mongo/platform')
-rw-r--r-- | src/mongo/platform/overflow_arithmetic.h | 139 | ||||
-rw-r--r-- | src/mongo/platform/overflow_arithmetic_test.cpp | 24 |
2 files changed, 45 insertions, 118 deletions
diff --git a/src/mongo/platform/overflow_arithmetic.h b/src/mongo/platform/overflow_arithmetic.h index 0306023916a..74567fe2763 100644 --- a/src/mongo/platform/overflow_arithmetic.h +++ b/src/mongo/platform/overflow_arithmetic.h @@ -35,123 +35,50 @@ #include <SafeInt.hpp> #endif -namespace mongo { +#include "mongo/stdx/type_traits.h" -/** - * Returns true if multiplying lhs by rhs would overflow. Otherwise, multiplies 64-bit signed - * or unsigned integers lhs by rhs and stores the result in *product. - */ -constexpr bool mongoSignedMultiplyOverflow64(int64_t lhs, int64_t rhs, int64_t* product); -constexpr bool mongoUnsignedMultiplyOverflow64(uint64_t lhs, uint64_t rhs, uint64_t* product); +namespace mongo::overflow { /** - * Returns true if adding lhs and rhs would overflow. Otherwise, adds 64-bit signed or unsigned - * integers lhs and rhs and stores the result in *sum. - */ -constexpr bool mongoSignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t* sum); -constexpr bool mongoUnsignedAddOverflow64(uint64_t lhs, uint64_t rhs, uint64_t* sum); - -/** - * Returns true if subtracting rhs from lhs would overflow. Otherwise, subtracts 64-bit signed or - * unsigned integers rhs from lhs and stores the result in *difference. + * Synopsis: + * + * bool mul(A a, A b, T* r); + * bool add(A a, A b, T* r); + * bool sub(A a, A b, T* r); + * + * The domain type `A` evaluates to `T`, which is deduced from the `r` parameter. + * That is, the input parameters are coerced into the type accepted by the output parameter. + * All functions return true if operation would overflow, otherwise they store result in `*r`. */ -constexpr bool mongoSignedSubtractOverflow64(int64_t lhs, int64_t rhs, int64_t* difference); -constexpr bool mongoUnsignedSubtractOverflow64(uint64_t lhs, uint64_t rhs, uint64_t* difference); +// MSVC : The SafeInt functions return false on overflow. +// GCC, Clang: The __builtin_*_overflow functions return true on overflow. +template <typename T> +constexpr bool mul(stdx::type_identity_t<T> a, stdx::type_identity_t<T> b, T* r) { #ifdef _MSC_VER - -// The SafeInt functions return true on success, false on overflow. - -constexpr bool mongoSignedMultiplyOverflow64(int64_t lhs, int64_t rhs, int64_t* product) { - return !SafeMultiply(lhs, rhs, *product); -} - -constexpr bool mongoUnsignedMultiplyOverflow64(uint64_t lhs, uint64_t rhs, uint64_t* product) { - return !SafeMultiply(lhs, rhs, *product); -} - -constexpr bool mongoSignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t* sum) { - return !SafeAdd(lhs, rhs, *sum); -} - -constexpr bool mongoUnsignedAddOverflow64(uint64_t lhs, uint64_t rhs, uint64_t* sum) { - return !SafeAdd(lhs, rhs, *sum); -} - -constexpr bool mongoSignedSubtractOverflow64(int64_t lhs, int64_t rhs, int64_t* difference) { - return !SafeSubtract(lhs, rhs, *difference); -} - -constexpr bool mongoUnsignedSubtractOverflow64(uint64_t lhs, uint64_t rhs, uint64_t* difference) { - return !SafeSubtract(lhs, rhs, *difference); -} - + return !SafeMultiply(a, b, *r); #else - -// On GCC and CLANG we can use __builtin functions to perform these calculations. These return true -// on overflow and false on success. - -constexpr bool mongoSignedMultiplyOverflow64(long lhs, long rhs, long* product) { - return __builtin_mul_overflow(lhs, rhs, product); -} - -constexpr bool mongoSignedMultiplyOverflow64(long long lhs, long long rhs, long long* product) { - return __builtin_mul_overflow(lhs, rhs, product); -} - -constexpr bool mongoUnsignedMultiplyOverflow64(unsigned long lhs, - unsigned long rhs, - unsigned long* product) { - return __builtin_mul_overflow(lhs, rhs, product); -} - -constexpr bool mongoUnsignedMultiplyOverflow64(unsigned long long lhs, - unsigned long long rhs, - unsigned long long* product) { - return __builtin_mul_overflow(lhs, rhs, product); -} - -constexpr bool mongoSignedAddOverflow64(long lhs, long rhs, long* sum) { - return __builtin_add_overflow(lhs, rhs, sum); -} - -constexpr bool mongoSignedAddOverflow64(long long lhs, long long rhs, long long* sum) { - return __builtin_add_overflow(lhs, rhs, sum); -} - -constexpr bool mongoUnsignedAddOverflow64(unsigned long lhs, - unsigned long rhs, - unsigned long* sum) { - return __builtin_add_overflow(lhs, rhs, sum); -} - -constexpr bool mongoUnsignedAddOverflow64(unsigned long long lhs, - unsigned long long rhs, - unsigned long long* sum) { - return __builtin_add_overflow(lhs, rhs, sum); -} - -constexpr bool mongoSignedSubtractOverflow64(long lhs, long rhs, long* difference) { - return __builtin_sub_overflow(lhs, rhs, difference); -} - -constexpr bool mongoSignedSubtractOverflow64(long long lhs, long long rhs, long long* difference) { - return __builtin_sub_overflow(lhs, rhs, difference); -} - -constexpr bool mongoUnsignedSubtractOverflow64(unsigned long lhs, - unsigned long rhs, - unsigned long* sum) { - return __builtin_sub_overflow(lhs, rhs, sum); + return __builtin_mul_overflow(a, b, r); +#endif } -constexpr bool mongoUnsignedSubtractOverflow64(unsigned long long lhs, - unsigned long long rhs, - unsigned long long* sum) { - return __builtin_sub_overflow(lhs, rhs, sum); +template <typename T> +constexpr bool add(stdx::type_identity_t<T> a, stdx::type_identity_t<T> b, T* r) { +#ifdef _MSC_VER + return !SafeAdd(a, b, *r); +#else + return __builtin_add_overflow(a, b, r); +#endif } +template <typename T> +constexpr bool sub(stdx::type_identity_t<T> a, stdx::type_identity_t<T> b, T* r) { +#ifdef _MSC_VER + return !SafeSubtract(a, b, *r); +#else + return __builtin_sub_overflow(a, b, r); #endif +} -} // namespace mongo +} // namespace mongo::overflow diff --git a/src/mongo/platform/overflow_arithmetic_test.cpp b/src/mongo/platform/overflow_arithmetic_test.cpp index 19571203e3c..95910832c86 100644 --- a/src/mongo/platform/overflow_arithmetic_test.cpp +++ b/src/mongo/platform/overflow_arithmetic_test.cpp @@ -49,34 +49,34 @@ namespace { } while (false) #define assertSignedMultiplyNoOverflow(LHS, RHS, EXPECTED) \ - assertArithOverflow(int64_t, mongoSignedMultiplyOverflow64, LHS, RHS, false, EXPECTED) + assertArithOverflow(int64_t, overflow::mul, LHS, RHS, false, EXPECTED) #define assertSignedMultiplyWithOverflow(LHS, RHS) \ - assertArithOverflow(int64_t, mongoSignedMultiplyOverflow64, LHS, RHS, true, 0) + assertArithOverflow(int64_t, overflow::mul, LHS, RHS, true, 0) #define assertUnsignedMultiplyNoOverflow(LHS, RHS, EXPECTED) \ - assertArithOverflow(uint64_t, mongoUnsignedMultiplyOverflow64, LHS, RHS, false, EXPECTED) + assertArithOverflow(uint64_t, overflow::mul, LHS, RHS, false, EXPECTED) #define assertUnsignedMultiplyWithOverflow(LHS, RHS) \ - assertArithOverflow(uint64_t, mongoUnsignedMultiplyOverflow64, LHS, RHS, true, 0) + assertArithOverflow(uint64_t, overflow::mul, LHS, RHS, true, 0) #define assertSignedAddNoOverflow(LHS, RHS, EXPECTED) \ - assertArithOverflow(int64_t, mongoSignedAddOverflow64, LHS, RHS, false, EXPECTED) + assertArithOverflow(int64_t, overflow::add, LHS, RHS, false, EXPECTED) #define assertSignedAddWithOverflow(LHS, RHS) \ - assertArithOverflow(int64_t, mongoSignedAddOverflow64, LHS, RHS, true, 0) + assertArithOverflow(int64_t, overflow::add, LHS, RHS, true, 0) #define assertUnsignedAddNoOverflow(LHS, RHS, EXPECTED) \ - assertArithOverflow(uint64_t, mongoUnsignedAddOverflow64, LHS, RHS, false, EXPECTED) + assertArithOverflow(uint64_t, overflow::add, LHS, RHS, false, EXPECTED) #define assertUnsignedAddWithOverflow(LHS, RHS) \ - assertArithOverflow(uint64_t, mongoUnsignedAddOverflow64, LHS, RHS, true, 0) + assertArithOverflow(uint64_t, overflow::add, LHS, RHS, true, 0) #define assertSignedSubtractNoOverflow(LHS, RHS, EXPECTED) \ - assertArithOverflow(int64_t, mongoSignedSubtractOverflow64, LHS, RHS, false, EXPECTED) + assertArithOverflow(int64_t, overflow::sub, LHS, RHS, false, EXPECTED) #define assertSignedSubtractWithOverflow(LHS, RHS) \ - assertArithOverflow(int64_t, mongoSignedSubtractOverflow64, LHS, RHS, true, 0) + assertArithOverflow(int64_t, overflow::sub, LHS, RHS, true, 0) #define assertUnsignedSubtractNoOverflow(LHS, RHS, EXPECTED) \ - assertArithOverflow(uint64_t, mongoUnsignedSubtractOverflow64, LHS, RHS, false, EXPECTED) + assertArithOverflow(uint64_t, overflow::sub, LHS, RHS, false, EXPECTED) #define assertUnsignedSubtractWithOverflow(LHS, RHS) \ - assertArithOverflow(uint64_t, mongoUnsignedSubtractOverflow64, LHS, RHS, true, 0) + assertArithOverflow(uint64_t, overflow::sub, LHS, RHS, true, 0) TEST(OverflowArithmetic, SignedMultiplicationTests) { using limits = std::numeric_limits<int64_t>; |