Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:36

0001 #ifndef BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
0002 #define BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
0003 
0004 //  Copyright (c) 2015 Robert Ramey
0005 //
0006 // Distributed under the Boost Software License, Version 1.0. (See
0007 // accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 #include <boost/mp11.hpp>
0011 #include <boost/config.hpp> // BOOST_NO_EXCEPTIONS
0012 #include "exception.hpp"
0013 
0014 namespace boost {
0015 namespace safe_numerics {
0016 
0017 template<
0018     typename AE,
0019     typename IDB,
0020     typename UB,
0021     typename UV
0022 >
0023 struct exception_policy {
0024     constexpr static void on_arithmetic_error(
0025         const safe_numerics_error & e,
0026         const char * msg
0027     ){
0028         AE()(e, msg);
0029     }
0030     constexpr static void on_implementation_defined_behavior(
0031         const safe_numerics_error & e,
0032         const char * msg
0033     ){
0034         IDB()(e, msg);
0035     }
0036     constexpr static void on_undefined_behavior(
0037         const safe_numerics_error & e,
0038         const char * msg
0039     ){
0040         UB()(e, msg);
0041     }
0042     constexpr static void on_uninitialized_value(
0043         const safe_numerics_error & e,
0044         const char * msg
0045     ){
0046         UV()(e, msg);
0047     }
0048 };
0049 
0050 ////////////////////////////////////////////////////////////////////////////////
0051 // pre-made error action handers
0052 
0053 // ignore any error and just return.
0054 struct ignore_exception {
0055     constexpr ignore_exception() = default;
0056     constexpr void operator () (
0057         const boost::safe_numerics::safe_numerics_error &,
0058         const char *
0059     ){}
0060 };
0061 
0062 // emit compile time error if this is invoked.
0063 struct trap_exception {
0064     constexpr trap_exception() = default;
0065     // error will occur on operator call.
0066     // hopefully this will display arguments
0067 };
0068 
0069 // If an exceptional condition is detected at runtime throw the exception.
0070 struct throw_exception {
0071     constexpr throw_exception() = default;
0072     #ifndef BOOST_NO_EXCEPTIONS
0073     void operator()(
0074         const safe_numerics_error & e,
0075         const char * message
0076     ){
0077         throw std::system_error(std::error_code(e), message);
0078     }
0079     #else
0080     constexpr trap_exception()(const safe_numerics_error & e, const char * message);
0081     #endif
0082 };
0083 
0084 // given an error code - return the action code which it corresponds to.
0085 constexpr inline safe_numerics_actions
0086 make_safe_numerics_action(const safe_numerics_error & e){
0087     // we can't use standard algorithms since we want this to be constexpr
0088     // this brute force solution is simple and pretty fast anyway
0089     switch(e){
0090     case safe_numerics_error::negative_overflow_error:
0091     case safe_numerics_error::underflow_error:
0092     case safe_numerics_error::range_error:
0093     case safe_numerics_error::domain_error:
0094     case safe_numerics_error::positive_overflow_error:
0095     case safe_numerics_error::precision_overflow_error:
0096         return safe_numerics_actions::arithmetic_error;
0097 
0098     case safe_numerics_error::negative_value_shift:
0099     case safe_numerics_error::negative_shift:
0100     case safe_numerics_error::shift_too_large:
0101         return safe_numerics_actions::implementation_defined_behavior;
0102 
0103     case safe_numerics_error::uninitialized_value:
0104         return safe_numerics_actions::uninitialized_value;
0105 
0106     case safe_numerics_error::success:
0107         return safe_numerics_actions::no_action;
0108     default:
0109         assert(false);
0110     }
0111     // should never arrive here
0112     //include to suppress bogus warning
0113     return safe_numerics_actions::no_action;
0114 }
0115 
0116 ////////////////////////////////////////////////////////////////////////////////
0117 // pre-made error policy classes
0118 
0119 // loose exception
0120 // - throw on arithmetic errors
0121 // - ignore other errors.
0122 // Some applications ignore these issues and still work and we don't
0123 // want to update them.
0124 using loose_exception_policy = exception_policy<
0125     throw_exception,    // arithmetic error
0126     ignore_exception,   // implementation defined behavior
0127     ignore_exception,   // undefined behavior
0128     ignore_exception     // uninitialized value
0129 >;
0130 
0131 // loose trap
0132 // same as above in that it doesn't check for various undefined behaviors
0133 // but traps at compile time for hard arithmetic errors.  This policy
0134 // would be suitable for older embedded systems which depend on
0135 // bit manipulation operations to work.
0136 using loose_trap_policy = exception_policy<
0137     trap_exception,    // arithmetic error
0138     ignore_exception,  // implementation defined behavior
0139     ignore_exception,  // undefined behavior
0140     ignore_exception   // uninitialized value
0141 >;
0142 
0143 // strict exception
0144 // - throw at runtime on any kind of error
0145 // recommended for new code.  Check everything at compile time
0146 // if possible and runtime if necessary.  Trap or Throw as
0147 // appropriate.  Should guarantee code to be portable across
0148 // architectures.
0149 using strict_exception_policy = exception_policy<
0150     throw_exception,
0151     throw_exception,
0152     throw_exception,
0153     ignore_exception
0154 >;
0155 
0156 // strict trap
0157 // Same as above but requires code to be written in such a way as to
0158 // make it impossible for errors to occur.  This naturally will require
0159 // extra coding effort but might be justified for embedded and/or
0160 // safety critical systems.
0161 using strict_trap_policy = exception_policy<
0162     trap_exception,
0163     trap_exception,
0164     trap_exception,
0165     trap_exception
0166 >;
0167 
0168 // default policy
0169 // One would use this first. After experimentation, one might
0170 // replace some actions with ignore_exception
0171 using default_exception_policy = strict_exception_policy;
0172 
0173 } // namespace safe_numerics
0174 } // namespace boost
0175 
0176 #endif // BOOST_NUMERIC_EXCEPTION_POLICIES_HPP