Use builtins for overflow detection in OverflowSafeInt on gcc/clang
This commit is contained in:
23
config.lib
23
config.lib
@@ -1914,6 +1914,29 @@ EOL
|
|||||||
CFLAGS="$CFLAGS -DWITH_BITMATH_BUILTINS"
|
CFLAGS="$CFLAGS -DWITH_BITMATH_BUILTINS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
log 2 "executing $cc_host $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.overflow-builtins -x c++ -"
|
||||||
|
"$cc_host" $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.overflow-builtins -x c++ - 2> /dev/null << EOL
|
||||||
|
#include <cstdint>
|
||||||
|
int main() {
|
||||||
|
int64_t a = 0;
|
||||||
|
int64_t b = 0;
|
||||||
|
int64_t c = 0;
|
||||||
|
bool res1 = __builtin_add_overflow(a, b, &c);
|
||||||
|
bool res2 = __builtin_sub_overflow(a, b, &c);
|
||||||
|
bool res3 = __builtin_mul_overflow(a, b, &c);
|
||||||
|
return (res1 || res2 || res3) ? 1 : 0;
|
||||||
|
}
|
||||||
|
EOL
|
||||||
|
ret=$?
|
||||||
|
rm -f tmp.config.overflow-builtins
|
||||||
|
log 2 " exit code $ret"
|
||||||
|
if [ $ret -ne 0 ]; then
|
||||||
|
log 1 "checking overflow builtins... no"
|
||||||
|
else
|
||||||
|
log 1 "checking overflow builtins... found"
|
||||||
|
CFLAGS="$CFLAGS -DWITH_OVERFLOW_BUILTINS"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "DOS" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ] && [ "$os" != "OS2" ]; then
|
if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "DOS" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ] && [ "$os" != "OS2" ]; then
|
||||||
log 2 "executing $cc_host $CFLAGS $CFLAGS_ENV $LDFLAGS $LDFLAGS_ENV -o tmp.config.demangle -x c++ - -lstdc++"
|
log 2 "executing $cc_host $CFLAGS $CFLAGS_ENV $LDFLAGS $LDFLAGS_ENV -o tmp.config.demangle -x c++ - -lstdc++"
|
||||||
"$cc_host" $CFLAGS $CFLAGS_ENV $LDFLAGS $LDFLAGS_ENV -o tmp.config.demangle -x c++ - -lstdc++ 2> /dev/null << EOL
|
"$cc_host" $CFLAGS $CFLAGS_ENV $LDFLAGS $LDFLAGS_ENV -o tmp.config.demangle -x c++ - -lstdc++ 2> /dev/null << EOL
|
||||||
|
@@ -46,12 +46,30 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline OverflowSafeInt& operator += (const OverflowSafeInt& other)
|
inline OverflowSafeInt& operator += (const OverflowSafeInt& other)
|
||||||
{
|
{
|
||||||
|
#ifdef WITH_OVERFLOW_BUILTINS
|
||||||
|
if (unlikely(__builtin_add_overflow(this->m_value, other.m_value, &this->m_value))) {
|
||||||
|
this->m_value = (other.m_value < 0) ? T_MIN : T_MAX;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ((T_MAX - abs(other.m_value)) < abs(this->m_value) &&
|
if ((T_MAX - abs(other.m_value)) < abs(this->m_value) &&
|
||||||
(this->m_value < 0) == (other.m_value < 0)) {
|
(this->m_value < 0) == (other.m_value < 0)) {
|
||||||
this->m_value = (this->m_value < 0) ? T_MIN : T_MAX ;
|
this->m_value = (this->m_value < 0) ? T_MIN : T_MAX ;
|
||||||
} else {
|
} else {
|
||||||
this->m_value += other.m_value;
|
this->m_value += other.m_value;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline OverflowSafeInt& operator -= (const OverflowSafeInt& other)
|
||||||
|
{
|
||||||
|
#ifdef WITH_OVERFLOW_BUILTINS
|
||||||
|
if (unlikely(__builtin_sub_overflow(this->m_value, other.m_value, &this->m_value))) {
|
||||||
|
this->m_value = (other.m_value < 0) ? T_MAX : T_MIN;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
*this += (-other);
|
||||||
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +77,6 @@ public:
|
|||||||
inline OverflowSafeInt operator + (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; }
|
inline OverflowSafeInt operator + (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; }
|
||||||
inline OverflowSafeInt operator + (const int other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
|
inline OverflowSafeInt operator + (const int other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
|
||||||
inline OverflowSafeInt operator + (const uint other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
|
inline OverflowSafeInt operator + (const uint other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
|
||||||
inline OverflowSafeInt& operator -= (const OverflowSafeInt& other) { return *this += (-other); }
|
|
||||||
inline OverflowSafeInt operator - (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; }
|
inline OverflowSafeInt operator - (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; }
|
||||||
inline OverflowSafeInt operator - (const int other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
|
inline OverflowSafeInt operator - (const int other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
|
||||||
inline OverflowSafeInt operator - (const uint other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
|
inline OverflowSafeInt operator - (const uint other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
|
||||||
@@ -77,11 +94,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline OverflowSafeInt& operator *= (const int factor)
|
inline OverflowSafeInt& operator *= (const int factor)
|
||||||
{
|
{
|
||||||
|
#ifdef WITH_OVERFLOW_BUILTINS
|
||||||
|
if (unlikely(__builtin_mul_overflow(this->m_value, factor, &this->m_value))) {
|
||||||
|
this->m_value = ((this->m_value < 0) == (factor < 0)) ? T_MAX : T_MIN;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (factor != 0 && (T_MAX / abs(factor)) < abs(this->m_value)) {
|
if (factor != 0 && (T_MAX / abs(factor)) < abs(this->m_value)) {
|
||||||
this->m_value = ((this->m_value < 0) == (factor < 0)) ? T_MAX : T_MIN ;
|
this->m_value = ((this->m_value < 0) == (factor < 0)) ? T_MAX : T_MIN ;
|
||||||
} else {
|
} else {
|
||||||
this->m_value *= factor ;
|
this->m_value *= factor ;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user