25 #ifndef XAPIAN_INCLUDED_OVERFLOW_H 26 #define XAPIAN_INCLUDED_OVERFLOW_H 29 # error config.h must be included first in each C++ source file 32 #include <type_traits> 34 #if !HAVE_DECL___BUILTIN_ADD_OVERFLOW || !HAVE_DECL___BUILTIN_SUB_OVERFLOW 35 # if HAVE_DECL__ADDCARRY_U32 || HAVE_DECL__ADDCARRY_U64 || \ 36 HAVE_DECL__SUBBORROW_U32 || HAVE_DECL__SUBBORROW_U64 54 template<
typename T1,
typename T2,
typename R>
55 typename std::enable_if<std::is_unsigned<T1>::value &&
56 std::is_unsigned<T2>::value &&
57 std::is_unsigned<R>::value,
bool>::type
59 #if HAVE_DECL___BUILTIN_ADD_OVERFLOW 60 return __builtin_add_overflow(a, b, &res);
67 res =
static_cast<R
>(r);
73 typedef decltype(r) r_type;
74 return (
sizeof(R) <=
sizeof(T1) ||
sizeof(R) <=
sizeof(T2)) &&
75 (r_type(res) != r || r < r_type(b));
79 #if !HAVE_DECL___BUILTIN_ADD_OVERFLOW 83 # if HAVE_DECL__ADDCARRY_U32 91 return _addcarry_u32(0, a, b, &res) != 0;
95 # if HAVE_DECL__ADDCARRY_U64 100 unsigned __int64>(
unsigned __int64 a,
102 unsigned __int64& res) {
103 return _addcarry_u64(0, a, b, &res) != 0;
121 template<
typename T1,
typename T2,
typename R>
122 typename std::enable_if<std::is_unsigned<T1>::value &&
123 std::is_unsigned<T2>::value &&
124 std::is_unsigned<R>::value,
bool>::type
126 #if HAVE_DECL___BUILTIN_ADD_OVERFLOW 127 return __builtin_sub_overflow(a, b, &res);
134 res =
static_cast<R
>(r);
137 typedef decltype(r) r_type;
138 return r_type(res) != r || r > r_type(a);
142 #if !HAVE_DECL___BUILTIN_SUB_OVERFLOW 146 # if HAVE_DECL__SUBBORROW_U32 151 unsigned>(
unsigned a,
154 return _subborrow_u32(0, a, b, &res) != 0;
158 # if HAVE_DECL__SUBBORROW_U64 163 unsigned __int64>(
unsigned __int64 a,
165 unsigned __int64& res) {
166 return _subborrow_u64(0, a, b, &res) != 0;
184 template<
typename T1,
typename T2,
typename R>
185 typename std::enable_if<std::is_unsigned<T1>::value &&
186 std::is_unsigned<T2>::value &&
187 std::is_unsigned<R>::value,
bool>::type
189 #if HAVE_DECL___BUILTIN_MUL_OVERFLOW 190 return __builtin_mul_overflow(a, b, &res);
197 res =
static_cast<R
>(r);
200 typedef decltype(r) r_type;
201 return r_type(res) != r || (a != 0 && r / r_type(a) != r_type(b));
205 #endif // XAPIAN_INCLUDED_OVERFLOW_H std::enable_if< std::is_unsigned< T1 >::value &&std::is_unsigned< T2 >::value &&std::is_unsigned< R >::value, bool >::type add_overflows(T1 a, T2 b, R &res)
Addition with overflow checking.
std::enable_if< std::is_unsigned< T1 >::value &&std::is_unsigned< T2 >::value &&std::is_unsigned< R >::value, bool >::type sub_overflows(T1 a, T2 b, R &res)
Subtraction with overflow checking.
std::enable_if< std::is_unsigned< T1 >::value &&std::is_unsigned< T2 >::value &&std::is_unsigned< R >::value, bool >::type mul_overflows(T1 a, T2 b, R &res)
Multiplication with overflow checking.