1#ifndef BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
2#define BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
3
4// Copyright (c) 2015 Robert Ramey
5//
6// Distributed under the Boost Software License, Version 1.0. (See
7// accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9
10#include <boost/mp11.hpp>
11#include <boost/config.hpp> // BOOST_NO_EXCEPTIONS
12#include "exception.hpp"
13
14namespace boost {
15namespace safe_numerics {
16
17template<
18 typename AE,
19 typename IDB,
20 typename UB,
21 typename UV
22>
23struct exception_policy {
24 constexpr static void on_arithmetic_error(
25 const safe_numerics_error & e,
26 const char * msg
27 ){
28 AE()(e, msg);
29 }
30 constexpr static void on_implementation_defined_behavior(
31 const safe_numerics_error & e,
32 const char * msg
33 ){
34 IDB()(e, msg);
35 }
36 constexpr static void on_undefined_behavior(
37 const safe_numerics_error & e,
38 const char * msg
39 ){
40 UB()(e, msg);
41 }
42 constexpr static void on_uninitialized_value(
43 const safe_numerics_error & e,
44 const char * msg
45 ){
46 UV()(e, msg);
47 }
48};
49
50////////////////////////////////////////////////////////////////////////////////
51// pre-made error action handers
52
53// ignore any error and just return.
54struct ignore_exception {
55 constexpr ignore_exception() = default;
56 constexpr void operator () (
57 const boost::safe_numerics::safe_numerics_error &,
58 const char *
59 ){}
60};
61
62// emit compile time error if this is invoked.
63struct trap_exception {
64 constexpr trap_exception() = default;
65 // error will occur on operator call.
66 // hopefully this will display arguments
67};
68
69// If an exceptional condition is detected at runtime throw the exception.
70struct throw_exception {
71 constexpr throw_exception() = default;
72 #ifndef BOOST_NO_EXCEPTIONS
73 void operator()(
74 const safe_numerics_error & e,
75 const char * message
76 ){
77 throw std::system_error(std::error_code(e), message);
78 }
79 #else
80 constexpr trap_exception()(const safe_numerics_error & e, const char * message);
81 #endif
82};
83
84// given an error code - return the action code which it corresponds to.
85constexpr inline safe_numerics_actions
86make_safe_numerics_action(const safe_numerics_error & e){
87 // we can't use standard algorithms since we want this to be constexpr
88 // this brute force solution is simple and pretty fast anyway
89 switch(e){
90 case safe_numerics_error::negative_overflow_error:
91 case safe_numerics_error::underflow_error:
92 case safe_numerics_error::range_error:
93 case safe_numerics_error::domain_error:
94 case safe_numerics_error::positive_overflow_error:
95 case safe_numerics_error::precision_overflow_error:
96 return safe_numerics_actions::arithmetic_error;
97
98 case safe_numerics_error::negative_value_shift:
99 case safe_numerics_error::negative_shift:
100 case safe_numerics_error::shift_too_large:
101 return safe_numerics_actions::implementation_defined_behavior;
102
103 case safe_numerics_error::uninitialized_value:
104 return safe_numerics_actions::uninitialized_value;
105
106 case safe_numerics_error::success:
107 return safe_numerics_actions::no_action;
108 default:
109 assert(false);
110 }
111 // should never arrive here
112 //include to suppress bogus warning
113 return safe_numerics_actions::no_action;
114}
115
116////////////////////////////////////////////////////////////////////////////////
117// pre-made error policy classes
118
119// loose exception
120// - throw on arithmetic errors
121// - ignore other errors.
122// Some applications ignore these issues and still work and we don't
123// want to update them.
124using loose_exception_policy = exception_policy<
125 throw_exception, // arithmetic error
126 ignore_exception, // implementation defined behavior
127 ignore_exception, // undefined behavior
128 ignore_exception // uninitialized value
129>;
130
131// loose trap
132// same as above in that it doesn't check for various undefined behaviors
133// but traps at compile time for hard arithmetic errors. This policy
134// would be suitable for older embedded systems which depend on
135// bit manipulation operations to work.
136using loose_trap_policy = exception_policy<
137 trap_exception, // arithmetic error
138 ignore_exception, // implementation defined behavior
139 ignore_exception, // undefined behavior
140 ignore_exception // uninitialized value
141>;
142
143// strict exception
144// - throw at runtime on any kind of error
145// recommended for new code. Check everything at compile time
146// if possible and runtime if necessary. Trap or Throw as
147// appropriate. Should guarantee code to be portable across
148// architectures.
149using strict_exception_policy = exception_policy<
150 throw_exception,
151 throw_exception,
152 throw_exception,
153 ignore_exception
154>;
155
156// strict trap
157// Same as above but requires code to be written in such a way as to
158// make it impossible for errors to occur. This naturally will require
159// extra coding effort but might be justified for embedded and/or
160// safety critical systems.
161using strict_trap_policy = exception_policy<
162 trap_exception,
163 trap_exception,
164 trap_exception,
165 trap_exception
166>;
167
168// default policy
169// One would use this first. After experimentation, one might
170// replace some actions with ignore_exception
171using default_exception_policy = strict_exception_policy;
172
173} // namespace safe_numerics
174} // namespace boost
175
176#endif // BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
177

source code of boost/libs/safe_numerics/include/boost/safe_numerics/exception_policies.hpp