Adjustments to pass all tests with gcc 4.8.1 -std=c++03

This commit is contained in:
Robert Ramey
2015-01-12 19:06:11 -08:00
parent 14608927a4
commit b1d4d43aba
4 changed files with 101 additions and 47 deletions

View File

@@ -1,6 +1,6 @@
# CMake build control file for Serialization Library tests
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.0)
project("SafeIntegers")
@@ -12,9 +12,10 @@ message(STATUS "compiler is ${CMAKE_CXX_COMPILER_ID}" )
if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
add_definitions( -ftemplate-depth=300 )
set (CMAKE_CXX_FLAGS "-std=c++11" )
elseif( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
add_definitions( /wd4996 )
elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
elseif( CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" )
add_definitions( -ftemplate-depth=300 )
# include the following if and only if you want to use c++11 features
set (CMAKE_CXX_FLAGS "-std=c++11" )
@@ -138,8 +139,8 @@ set(CTEST_DROP_SITE_CDASH TRUE)
endif()
# the include above includes enable_testing() so the following line isn't
# necessary
# the "include (CTest)" above includes enable_testing()
# so the following line isn't necessary
# enable_testing()
message(STATUS "test_cast")
@@ -182,10 +183,10 @@ add_executable( test_conversion ../test/test_conversion.cpp)
target_link_libraries( test_conversion ${Boost_LIBRARIES} )
add_test(NAME test_conversion COMMAND test_conversion)
message(STATUS "test")
add_executable( test ../test/test.cpp)
target_link_libraries( test ${Boost_LIBRARIES} )
add_test(NAME test COMMAND test)
message(STATUS "test0")
add_executable( test0 ../test/test.cpp)
target_link_libraries( test0 ${Boost_LIBRARIES} )
add_test(NAME test0 COMMAND test)
# examples
message(STATUS "example1")

View File

@@ -9,6 +9,5 @@ set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
# set(CTEST_DROP_LOCATION "/cdash/submit.php?project=MyProject")
set(CTEST_DROP_LOCATION "/index.php?project=Safe+Numerics")
set(CTEST_DROP_LOCATION "/submit.php?project=Safe+Numerics")
set(CTEST_DROP_SITE_CDASH TRUE)

View File

@@ -28,13 +28,30 @@
which behave exactly like the original ones EXCEPT that the results of
these operations are checked to be sure any possible errors resulting from
undefined arithmetic behavior are trapped at compile time (if possible) or
at runtime.</para>
at runtime. This will permit one to write arithmetic expressions without
resulting in an erroneous result. Instead, one and only one of the
following is guarenteed to occur.</para>
<para>In addition to eliminating undefined behavior from primitive integer
types, we define new data types <code>safe_signed_range&lt;MIN,
MAX&gt;</code> and <code>safe_unsigned_range&lt;MIN, MAX&gt;</code> which
will throw an exception if an attempt is made to store a result which is
outside the closed range [MIN, MAX].</para>
<para><itemizedlist>
<listitem>
<para>the expression will emit a compilation error.</para>
</listitem>
<listitem>
<para>the expression will invoke a runtime exception.</para>
</listitem>
<listitem>
<para>the expression will yield the correct mathematical
result</para>
</listitem>
</itemizedlist>In addition to eliminating undefined behavior from
primitive integer types, we define new data types
<code>safe_signed_range&lt;MIN, MAX&gt;</code> and
<code>safe_unsigned_range&lt;MIN, MAX&gt;</code> which will throw an
exception if an attempt is made to store a result which is outside the
closed range [MIN, MAX]. By using these types, on can guarentee correct
runtime behavior without the need for exception handling.</para>
</section>
<section>
@@ -76,4 +93,15 @@
</listitem>
</itemizedlist></para>
</section>
<section>
<title>Scope</title>
<para>This library currently applies only to built-in integer types.
Analogous issues arise for floating point types but they are not currently
addressed by this version of the library. User or Library defined types
such as arbitrary precision integers can also have this problem. Extension
of this library to these other types is not currently under
development</para>
</section>
</section>

View File

@@ -62,11 +62,16 @@ namespace detail {
template<bool TS, bool US>
struct check_addition_overflow{};
template<typename T, typename U>
struct check_addition_result{
typedef BOOST_TYPEOF_TPL(T() + U()) type;
};
// both arguments unsigned
template<>
struct check_addition_overflow<false, false> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_addition_result<T, U>::type
add(const T & t, const U & u) {
BOOST_AUTO_TPL(tmp, t + u);
if(boost::numeric::safe_compare::less_than(tmp, t)
@@ -79,9 +84,9 @@ namespace detail {
template<>
struct check_addition_overflow<false, true> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_addition_result<T, U>::type
add(const T & t, const U & u){
typedef BOOST_TYPEOF_TPL(T() + U()) result_type;
typedef typename check_addition_result<T, U>::type result_type;
if(boost::numeric::is_unsigned<result_type>::value){
if(u < 0)
overflow("safe range right operand value altered");
@@ -105,9 +110,9 @@ namespace detail {
template<>
struct check_addition_overflow<true, false> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_addition_result<T, U>::type
add(const T & t, const U & u){
typedef BOOST_TYPEOF_TPL(T() + U()) result_type;
typedef typename check_addition_result<T, U>::type result_type;
if(boost::numeric::is_unsigned<result_type>::value){
if(t < 0)
overflow("safe range left operand value altered");
@@ -132,9 +137,9 @@ namespace detail {
template<>
struct check_addition_overflow<true, true> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_addition_result<T, U>::type
add(const T & t, const U & u){
typedef BOOST_TYPEOF_TPL(T() + U()) result_type;
typedef typename check_addition_result<T, U>::type result_type;
if(t > 0 && u > 0){
result_type tmp = t + u;
if(tmp < 0)
@@ -156,11 +161,16 @@ namespace detail {
template<bool TS, bool US>
struct check_subtraction_overflow{};
template<typename T, typename U>
struct check_subtraction_result{
typedef BOOST_TYPEOF_TPL(T() - U()) type;
};
// both arguments signed
template<>
struct check_subtraction_overflow<true, true> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_subtraction_result<T, U>::type
subtract(const T & t, const U & u){
auto tmp = t - u;
if(t > 0 && u < 0){
@@ -178,7 +188,7 @@ namespace detail {
template<>
struct check_subtraction_overflow<false, false> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_subtraction_result<T, U>::type
subtract(const T & t, const U & u) {
if(safe_compare::less_than(t, u))
overflow("safe range subtraction unsigned difference less than zero");
@@ -189,7 +199,7 @@ namespace detail {
template<>
struct check_subtraction_overflow<false, true> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_subtraction_result<T, U>::type
subtract(const T & t, const U & u){
typedef BOOST_TYPEOF_TPL(T() + U()) result_type;
if(boost::numeric::is_unsigned<result_type>::value){
@@ -207,9 +217,9 @@ namespace detail {
template<>
struct check_subtraction_overflow<true, false> {
template<class T, class U>
static BOOST_TYPEOF_TPL(T() + U())
static typename check_subtraction_result<T, U>::type
subtract(const T & t, const U & u){
typedef BOOST_TYPEOF_TPL(T() + U()) result_type;
typedef typename check_subtraction_result<T, U>::type result_type;
if(boost::numeric::is_unsigned<result_type>::value){
return check_subtraction_overflow<false, false>::subtract(
safe_cast<result_type>(t),
@@ -227,10 +237,15 @@ namespace detail {
////////////////////////////////
// multiplication implementation
template<typename T, typename U>
struct check_multiplication_result{
typedef BOOST_TYPEOF_TPL(T() * U()) type;
};
template<class T, class U>
BOOST_TYPEOF_TPL(T() * U())
typename check_multiplication_result<T, U>::type
check_multiplication_overflow(const T & t, const U & u){
typedef BOOST_TYPEOF_TPL(T() * U()) result_type;
typedef typename check_multiplication_result<T, U>::type result_type;
char const * const msg = "safe range multiplication overflow";
// presume that size of uintmax_t and intmax_t are the same
typedef bits<boost::uintmax_t> available_bits;
@@ -325,8 +340,14 @@ namespace detail {
return t * u;
}
template<typename T, typename U>
struct check_division_result{
typedef BOOST_TYPEOF_TPL(T() / U()) type;
};
template<class T, class U>
BOOST_TYPEOF_TPL(T() / U())
typename check_division_result<T, U>::type
check_division_overflow(const T & t, const U & u){
if(0 == u)
overflow("divide by zero");
@@ -350,7 +371,7 @@ namespace detail {
return t / u;
}
template<class T, class U>
BOOST_TYPEOF_TPL(T() / U())
typename check_division_result<T, U>::type
check_modulus_overflow(const T & t, const U & u){
if(0 == u)
overflow("modulus divide by zero");
@@ -547,7 +568,7 @@ public:
template<class U>
typename boost::enable_if<
no_addition_overflow_possible<Stored, U>,
BOOST_TYPEOF_TPL(Stored() - U())
typename detail::check_addition_result<Stored, U>::type
>::type
inline operator+(const U & rhs) const {
return m_t + rhs;
@@ -557,7 +578,7 @@ public:
template<class U>
typename boost::disable_if<
no_addition_overflow_possible<Stored, U>,
BOOST_TYPEOF_TPL(Stored() - U())
typename detail::check_addition_result<Stored, U>::type
>::type
inline operator+(const U & rhs) const {
return detail::check_addition_overflow<
@@ -587,7 +608,7 @@ public:
template<class U>
typename boost::enable_if<
no_subtraction_overflow_possible<Stored, U>,
BOOST_TYPEOF_TPL(Stored() - U())
typename detail::check_subtraction_result<Stored, U>::type
>::type
inline operator-(const U & rhs) const {
return m_t - rhs;
@@ -596,7 +617,7 @@ public:
template<class U>
typename boost::disable_if<
no_subtraction_overflow_possible<Stored, U>,
BOOST_TYPEOF_TPL(Stored() - U())
typename detail::check_subtraction_result<Stored, U>::type
>::type
inline operator-(const U & rhs) const {
return detail::check_subtraction_overflow<
@@ -608,7 +629,7 @@ public:
// multiplication
template<class U>
BOOST_TYPEOF_TPL(U() * Stored())
typename detail::check_multiplication_result<U, Stored>::type
inline operator*(const U & rhs) const {
return detail::check_multiplication_overflow(m_t, rhs);
}
@@ -616,7 +637,7 @@ public:
/////////////////////////////////////////////////////////////////
// division
template<class U>
BOOST_TYPEOF_TPL(U() / Stored())
typename detail::check_division_result<U, Stored>::type
inline operator/(const U & rhs) const {
return detail::check_division_overflow(m_t, rhs);
}
@@ -624,7 +645,7 @@ public:
/////////////////////////////////////////////////////////////////
// modulus
template<class U>
BOOST_TYPEOF_TPL(Stored() % U())
typename detail::check_division_result<Stored, U>::type
inline operator%(const U & rhs) const {
if(0 == rhs)
throw std::domain_error("Divide by zero");
@@ -633,8 +654,13 @@ public:
/////////////////////////////////////////////////////////////////
// logical operators
template<typename T, typename U>
struct check_logical_result{
typedef BOOST_TYPEOF_TPL(T() & U()) type;
};
template<class U>
BOOST_TYPEOF_TPL(Stored() | U())
typename check_logical_result<Stored, U>::type
inline operator|(const U & rhs) const {
// verify that U is an integer type
BOOST_STATIC_ASSERT_MSG(
@@ -644,7 +670,7 @@ public:
return m_t | rhs;
}
template<class U>
BOOST_TYPEOF_TPL(Stored() & U())
typename check_logical_result<Stored, U>::type
inline operator&(const U & rhs) const {
// verify that U is an integer type
BOOST_STATIC_ASSERT_MSG(
@@ -654,7 +680,7 @@ public:
return m_t & rhs;
}
template<class U>
BOOST_TYPEOF_TPL(Stored() ^ U())
typename check_logical_result<Stored, U>::type
inline operator^(const U & rhs) const {
// verify that U is an integer type
BOOST_STATIC_ASSERT_MSG(
@@ -781,7 +807,7 @@ inline operator<=(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
template<class T, class Stored, class Derived>
typename boost::enable_if<
boost::is_integral<T>,
BOOST_TYPEOF_TPL(T() + Stored())
typename detail::check_addition_result<T, Stored>::type
>::type
inline operator+(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
return rhs + lhs;
@@ -791,7 +817,7 @@ inline operator+(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
template<class T, class Stored, class Derived>
typename boost::enable_if<
boost::is_integral<T>,
BOOST_TYPEOF_TPL(T() - Stored())
typename detail::check_subtraction_result<T, Stored>::type
>::type
inline operator-(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
BOOST_TYPEOF_TPL(T() - Stored()) tmp = rhs - lhs;
@@ -802,7 +828,7 @@ inline operator-(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
template<class T, class Stored, class Derived>
typename boost::enable_if<
boost::is_integral<T>,
BOOST_TYPEOF_TPL(T() * Stored())
typename detail::check_multiplication_result<T, Stored>::type
>::type
inline operator*(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
return rhs * lhs;
@@ -813,7 +839,7 @@ inline operator*(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
template<class T, class Stored, class Derived>
typename boost::enable_if<
boost::is_integral<T>,
BOOST_TYPEOF_TPL(T() / Stored())
typename detail::check_division_result<T, Stored>::type
>::type
inline operator/(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
if(safe_compare::equal(0, rhs))
@@ -827,7 +853,7 @@ inline operator/(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
template<class T, class Stored, class Derived>
typename boost::enable_if<
boost::is_integral<T>,
BOOST_TYPEOF_TPL(T() % Stored())
typename detail::check_division_result<T, Stored>::type
>::type
inline operator%(const T & lhs, const safe_range_base<Stored, Derived> & rhs) {
if(safe_compare::equal(0, rhs))