summaryrefslogtreecommitdiff
path: root/src/mongo/platform
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2019-08-28 18:26:07 +0000
committerevergreen <evergreen@mongodb.com>2019-08-28 18:26:07 +0000
commitd6f11844f1c17a675c335ea95f7a49736eb653e9 (patch)
treec712e6d4a4a373a4aff7b249fb44072e4640cbcc /src/mongo/platform
parent0a0625f43e4fa34302c7bc4757b0f273782925b5 (diff)
downloadmongo-d6f11844f1c17a675c335ea95f7a49736eb653e9.tar.gz
SERVER-43032 simplify overflow_arithmetic.h
Diffstat (limited to 'src/mongo/platform')
-rw-r--r--src/mongo/platform/overflow_arithmetic.h139
-rw-r--r--src/mongo/platform/overflow_arithmetic_test.cpp24
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>;