execution_monitor.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. // (C) Copyright Gennadiy Rozental 2001.
  2. // (C) Copyright Beman Dawes 2001.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org/libs/test for the library home page.
  7. //
  8. //!@file
  9. //!@brief Defines public interface of the Execution Monitor and related classes
  10. // ***************************************************************************
  11. #ifndef BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
  12. #define BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
  13. // Boost.Test
  14. #include <boost/test/detail/global_typedef.hpp>
  15. #include <boost/test/detail/fwd_decl.hpp>
  16. #include <boost/test/detail/throw_exception.hpp>
  17. #include <boost/test/utils/class_properties.hpp>
  18. // Boost
  19. #include <boost/shared_ptr.hpp>
  20. #include <boost/scoped_array.hpp>
  21. #include <boost/type.hpp>
  22. #include <boost/cstdlib.hpp>
  23. #include <boost/function/function0.hpp>
  24. #include <boost/test/detail/suppress_warnings.hpp>
  25. #ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
  26. // for the FP constants and control routines
  27. #include <float.h>
  28. #ifndef EM_INVALID
  29. #define EM_INVALID _EM_INVALID
  30. #endif
  31. #ifndef EM_DENORMAL
  32. #define EM_DENORMAL _EM_DENORMAL
  33. #endif
  34. #ifndef EM_ZERODIVIDE
  35. #define EM_ZERODIVIDE _EM_ZERODIVIDE
  36. #endif
  37. #ifndef EM_OVERFLOW
  38. #define EM_OVERFLOW _EM_OVERFLOW
  39. #endif
  40. #ifndef EM_UNDERFLOW
  41. #define EM_UNDERFLOW _EM_UNDERFLOW
  42. #endif
  43. #ifndef MCW_EM
  44. #define MCW_EM _MCW_EM
  45. #endif
  46. #else // based on ISO C standard
  47. #if !defined(BOOST_NO_FENV_H)
  48. #include <boost/detail/fenv.hpp>
  49. #endif
  50. #endif
  51. #if defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE)
  52. //! Indicates tha the floating point exception handling is supported
  53. //! through SEH
  54. #define BOOST_TEST_FPE_SUPPORT_WITH_SEH__
  55. #elif !defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE)
  56. #if !defined(BOOST_NO_FENV_H) && !defined(BOOST_CLANG) && \
  57. defined(__GLIBC__) && defined(__USE_GNU) && \
  58. !(defined(__UCLIBC__) || defined(__nios2__) || defined(__microblaze__))
  59. //! Indicates that floating point exception handling is supported for the
  60. //! non SEH version of it, for the GLIBC extensions only
  61. // see dicussions on the related topic: https://svn.boost.org/trac/boost/ticket/11756
  62. #define BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
  63. #endif
  64. #endif
  65. // Additional macro documentations not being generated without this hack
  66. #ifdef BOOST_TEST_DOXYGEN_DOC__
  67. //! Disables the support of the alternative stack
  68. //! during the compilation of the Boost.test framework. This is especially useful
  69. //! in case it is not possible to detect the lack of alternative stack support for
  70. //! your compiler (for instance, ESXi).
  71. #define BOOST_TEST_DISABLE_ALT_STACK
  72. #endif
  73. //____________________________________________________________________________//
  74. namespace boost {
  75. /// @defgroup ExecutionMonitor Function Execution Monitor
  76. /// @{
  77. /// @section Intro Introduction
  78. /// Sometimes we need to call a function and make sure that no user or system originated exceptions are being thrown by it. Uniform exception reporting
  79. /// is also may be convenient. That's the purpose of the Boost.Test's Execution Monitor.
  80. ///
  81. /// The Execution Monitor is a lower-level component of the Boost Test Library. It is the base for implementing all other Boost.Test components, but also
  82. /// can be used standalone to get controlled execution of error-prone functions with a uniform error notification. The Execution Monitor calls a user-supplied
  83. /// function in a controlled environment, relieving users from messy error detection.
  84. ///
  85. /// The Execution Monitor usage is demonstrated in the example exec_mon_example.
  86. ///
  87. /// @section DesignRationale Design Rationale
  88. ///
  89. /// The Execution Monitor design assumes that it can be used when no (or almost no) memory available. Also the Execution Monitor is intended to be portable to as many platforms as possible.
  90. ///
  91. /// @section UserGuide User's guide
  92. /// The Execution Monitor is designed to solve the problem of executing potentially dangerous function that may result in any number of error conditions,
  93. /// in monitored environment that should prevent any undesirable exceptions to propagate out of function call and produce consistent result report for all outcomes.
  94. /// The Execution Monitor is able to produce informative report for all standard C++ exceptions and intrinsic types. All other exceptions are reported as unknown.
  95. /// If you prefer different message for your exception type or need to perform any action, the Execution Monitor supports custom exception translators.
  96. /// There are several other parameters of the monitored environment can be configured by setting appropriate properties of the Execution Monitor.
  97. ///
  98. /// All symbols in the Execution Monitor implementation are located in the namespace boost. To use the Execution Monitor you need to:
  99. /// -# include @c boost/test/execution_monitor.hpp
  100. /// -# Make an instance of execution_monitor.
  101. /// -# Optionally register custom exception translators for exception classes which require special processing.
  102. ///
  103. /// @subsection FuncExec Monitored function execution
  104. ///
  105. /// The class execution_monitor can monitor functions with the following signatures:
  106. /// - int ()
  107. /// - void ()
  108. ///
  109. /// This function is expected to be self sufficient part of your application. You can't pass any arguments to this function directly. Instead you
  110. /// should bind them into executable nullary function using bind function (either standard or boost variant). Neither you can return any other value,
  111. /// but an integer result code. If necessary you can bind output parameters by reference or use some other more complicated nullary functor, which
  112. /// maintains state. This includes class methods, static class methods etc.
  113. ///
  114. /// To start the monitored function, invoke the method execution_monitor::execute and pass the monitored function as an argument. If the call succeeds,
  115. /// the method returns the result code produced by the monitored function. If any of the following conditions occur:
  116. /// - Uncaught C++ exception
  117. /// - Hardware or software signal, trap, or other exception
  118. /// - Timeout reached
  119. /// - Debug assert event occurred (under Microsoft Visual C++ or compatible compiler)
  120. ///
  121. /// then the method throws the execution_exception. The exception contains unique error_code value identifying the error condition and the detailed message
  122. /// that can be used to report the error.
  123. ///
  124. /// @subsection Reporting Errors reporting and translation
  125. ///
  126. /// If you need to report an error inside monitored function execution you have to throw an exception. Do not use the execution_exception - it's not intended
  127. /// to be used for this purpose. The simplest choice is to use one of the following C++ types as an exception:
  128. /// - C string
  129. /// - std:string
  130. /// - any exception class in std::exception hierarchy
  131. /// - boost::exception
  132. ///
  133. /// execution_monitor will catch and report these types of exceptions. If exception is thrown which is unknown to execution_monitor, it can only
  134. /// report the fact of the exception. So in case if you prefer to use your own exception types or can't govern what exceptions are generated by monitored
  135. /// function and would like to see proper error message in a report, execution_monitor can be configured with custom "translator" routine, which will have
  136. /// a chance to either record the fact of the exception itself or translate it into one of standard exceptions and rethrow (or both). The translator routine
  137. /// is registered per exception type and is invoked when exception of this class (or one inherited from it) is thrown inside monitored routine. You can
  138. /// register as many independent translators as you like. See execution_monitor::register_exception_translator specification for requirements on translator
  139. /// function.
  140. ///
  141. /// Finally, if you need to abort the monitored function execution without reporting any errors, you can throw an exception execution_aborted. As a result
  142. /// the execution is aborted and zero result code is produced by the method execution_monitor::execute.
  143. ///
  144. /// @subsection Parameters Supported parameters
  145. ///
  146. /// The Execution Monitor behavior is configurable through the set of parameters (properties) associated with the instance of the monitor. See execution_monitor
  147. /// specification for a list of supported parameters and their semantic.
  148. // ************************************************************************** //
  149. // ************** detail::translator_holder_base ************** //
  150. // ************************************************************************** //
  151. namespace detail {
  152. class translator_holder_base;
  153. typedef boost::shared_ptr<translator_holder_base> translator_holder_base_ptr;
  154. class BOOST_TEST_DECL translator_holder_base {
  155. protected:
  156. typedef boost::unit_test::const_string const_string;
  157. public:
  158. // Constructor
  159. translator_holder_base( translator_holder_base_ptr next, const_string tag )
  160. : m_next( next )
  161. , m_tag( std::string() + tag )
  162. {
  163. }
  164. // Destructor
  165. virtual ~translator_holder_base() {}
  166. // translator holder interface
  167. // invokes the function F inside the try/catch guarding against specific exception
  168. virtual int operator()( boost::function<int ()> const& F ) = 0;
  169. // erases specific translator holder from the chain
  170. translator_holder_base_ptr erase( translator_holder_base_ptr this_, const_string tag )
  171. {
  172. if( m_next )
  173. m_next = m_next->erase( m_next, tag );
  174. return m_tag == tag ? m_next : this_;
  175. }
  176. #ifndef BOOST_NO_RTTI
  177. virtual translator_holder_base_ptr erase( translator_holder_base_ptr this_, std::type_info const& ) = 0;
  178. template<typename ExceptionType>
  179. translator_holder_base_ptr erase( translator_holder_base_ptr this_, boost::type<ExceptionType>* = 0 )
  180. {
  181. if( m_next )
  182. m_next = m_next->erase<ExceptionType>( m_next );
  183. return erase( this_, typeid(ExceptionType) );
  184. }
  185. #endif
  186. protected:
  187. // Data members
  188. translator_holder_base_ptr m_next;
  189. std::string m_tag;
  190. };
  191. } // namespace detail
  192. // ************************************************************************** //
  193. /// @class execution_exception
  194. /// @brief This class is used to report any kind of an failure during execution of a monitored function inside of execution_monitor
  195. ///
  196. /// The instance of this class is thrown out of execution_monitor::execute invocation when failure is detected. Regardless of a kind of failure occurred
  197. /// the instance will provide a uniform way to catch and report it.
  198. ///
  199. /// One important design rationale for this class is that we should be ready to work after fatal memory corruptions or out of memory conditions. To facilitate
  200. /// this class never allocates any memory and assumes that strings it refers to are either some constants or live in a some kind of persistent (preallocated) memory.
  201. // ************************************************************************** //
  202. class BOOST_TEST_DECL execution_exception {
  203. typedef boost::unit_test::const_string const_string;
  204. public:
  205. /// These values are sometimes used as program return codes.
  206. /// The particular values have been chosen to avoid conflicts with
  207. /// commonly used program return codes: values < 100 are often user
  208. /// assigned, values > 255 are sometimes used to report system errors.
  209. /// Gaps in values allow for orderly expansion.
  210. ///
  211. /// @note(1) Only uncaught C++ exceptions are treated as errors.
  212. /// If a function catches a C++ exception, it never reaches
  213. /// the execution_monitor.
  214. ///
  215. /// The implementation decides what is a system_fatal_error and what is
  216. /// just a system_exception. Fatal errors are so likely to have corrupted
  217. /// machine state (like a stack overflow or addressing exception) that it
  218. /// is unreasonable to continue execution.
  219. ///
  220. /// @note(2) These errors include Unix signals and Windows structured
  221. /// exceptions. They are often initiated by hardware traps.
  222. enum error_code {
  223. no_error = 0, ///< for completeness only; never returned
  224. user_error = 200, ///< user reported non-fatal error
  225. cpp_exception_error = 205, ///< see note (1) above
  226. system_error = 210, ///< see note (2) above
  227. timeout_error = 215, ///< only detectable on certain platforms
  228. user_fatal_error = 220, ///< user reported fatal error
  229. system_fatal_error = 225 ///< see note (2) above
  230. };
  231. /// Simple model for the location of failure in a source code
  232. struct BOOST_TEST_DECL location {
  233. explicit location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 );
  234. explicit location( const_string file_name, size_t line_num = 0, char const* func = 0 );
  235. const_string m_file_name; ///< File name
  236. size_t m_line_num; ///< Line number
  237. const_string m_function; ///< Function name
  238. };
  239. /// @name Constructors
  240. /// Constructs instance based on message, location and error code
  241. /// @param[in] ec error code
  242. /// @param[in] what_msg error message
  243. /// @param[in] location error location
  244. execution_exception( error_code ec, const_string what_msg, location const& location );
  245. /// @name Access methods
  246. /// Exception error code
  247. error_code code() const { return m_error_code; }
  248. /// Exception message
  249. const_string what() const { return m_what; }
  250. /// Exception location
  251. location const& where() const { return m_location; }
  252. ///@}
  253. private:
  254. // Data members
  255. error_code m_error_code;
  256. const_string m_what;
  257. location m_location;
  258. }; // execution_exception
  259. // ************************************************************************** //
  260. /// @brief Function execution monitor
  261. /// This class is used to uniformly detect and report an occurrence of several types of signals and exceptions, reducing various
  262. /// errors to a uniform execution_exception that is returned to a caller.
  263. ///
  264. /// The executiom_monitor behavior can be customized through a set of public parameters (properties) associated with the execution_monitor instance.
  265. /// All parameters are implemented as public unit_test::readwrite_property data members of the class execution_monitor.
  266. // ************************************************************************** //
  267. class BOOST_TEST_DECL execution_monitor {
  268. typedef boost::unit_test::const_string const_string;
  269. public:
  270. /// Default constructor initializes all execution monitor properties
  271. execution_monitor();
  272. /// Should monitor catch system errors.
  273. ///
  274. /// The @em p_catch_system_errors property is a boolean flag (default value is true) specifying whether or not execution_monitor should trap system
  275. /// errors/system level exceptions/signals, which would cause program to crash in a regular case (without execution_monitor).
  276. /// Set this property to false, for example, if you wish to force coredump file creation. The Unit Test Framework provides a
  277. /// runtime parameter @c \-\-catch_system_errors=yes to alter the behavior in monitored test cases.
  278. unit_test::readwrite_property<bool> p_catch_system_errors;
  279. /// Should monitor try to attach debugger in case of caught system error.
  280. ///
  281. /// The @em p_auto_start_dbg property is a boolean flag (default value is false) specifying whether or not execution_monitor should try to attach debugger
  282. /// in case system error is caught.
  283. unit_test::readwrite_property<bool> p_auto_start_dbg;
  284. /// Specifies the seconds that elapse before a timer_error occurs.
  285. ///
  286. /// The @em p_timeout property is an integer timeout (in seconds) for monitored function execution. Use this parameter to monitor code with possible deadlocks
  287. /// or indefinite loops. This feature is only available for some operating systems (not yet Microsoft Windows).
  288. unit_test::readwrite_property<unsigned> p_timeout;
  289. /// Should monitor use alternative stack for the signal catching.
  290. ///
  291. /// The @em p_use_alt_stack property is a boolean flag (default value is false) specifying whether or not execution_monitor should use an alternative stack
  292. /// for the sigaction based signal catching. When enabled the signals are delivered to the execution_monitor on a stack different from current execution
  293. /// stack, which is safer in case if it is corrupted by monitored function. For more details on alternative stack handling see appropriate manuals.
  294. unit_test::readwrite_property<bool> p_use_alt_stack;
  295. /// Should monitor try to detect hardware floating point exceptions (!= 0), and which specific exception to catch.
  296. ///
  297. /// The @em p_detect_fp_exceptions property is a boolean flag (default value is false) specifying whether or not execution_monitor should install hardware
  298. /// traps for the floating point exception on platforms where it's supported.
  299. unit_test::readwrite_property<unsigned> p_detect_fp_exceptions;
  300. // @name Monitoring entry points
  301. /// @brief Execution monitor entry point for functions returning integer value
  302. ///
  303. /// This method executes supplied function F inside a try/catch block and also may include other unspecified platform dependent error detection code.
  304. ///
  305. /// This method throws an execution_exception on an uncaught C++ exception, a hardware or software signal, trap, or other user exception.
  306. ///
  307. /// @note execute() doesn't consider it an error for F to return a non-zero value.
  308. /// @param[in] F Function to monitor
  309. /// @returns value returned by function call F().
  310. /// @see vexecute
  311. int execute( boost::function<int ()> const& F );
  312. /// @brief Execution monitor entry point for functions returning void
  313. ///
  314. /// This method is semantically identical to execution_monitor::execute, but des't produce any result code.
  315. /// @param[in] F Function to monitor
  316. /// @see execute
  317. void vexecute( boost::function<void ()> const& F );
  318. // @}
  319. // @name Exception translator registration
  320. /// @brief Registers custom (user supplied) exception translator
  321. /// This method template registers a translator for an exception type specified as a first template argument. For example
  322. /// @code
  323. /// void myExceptTr( MyException const& ex ) { /*do something with the exception here*/}
  324. /// em.register_exception_translator<MyException>( myExceptTr );
  325. /// @endcode
  326. /// The translator should be any unary function/functor object which accepts MyException const&. This can be free standing function
  327. /// or bound class method. The second argument is an optional string tag you can associate with this translator routine. The only reason
  328. /// to specify the tag is if you plan to erase the translator eventually. This can be useful in scenario when you reuse the same
  329. /// execution_monitor instance to monitor different routines and need to register a translator specific to the routine being monitored.
  330. /// While it is possible to erase the translator based on an exception type it was registered for, tag string provides simpler way of doing this.
  331. /// @tparam ExceptionType type of the exception we register a translator for
  332. /// @tparam ExceptionTranslator type of the translator we register for this exception
  333. /// @param[in] tr translator function object with the signature <em> void (ExceptionType const&)</em>
  334. /// @param[in] tag tag associated with this translator
  335. template<typename ExceptionType, typename ExceptionTranslator>
  336. void register_exception_translator( ExceptionTranslator const& tr, const_string tag = const_string(), boost::type<ExceptionType>* = 0 );
  337. /// @brief Erases custom exception translator based on a tag
  338. /// Use the same tag as the one used during translator registration
  339. /// @param[in] tag tag associated with translator you wants to erase
  340. void erase_exception_translator( const_string tag )
  341. {
  342. m_custom_translators = m_custom_translators->erase( m_custom_translators, tag );
  343. }
  344. #ifndef BOOST_NO_RTTI
  345. /// @brief Erases custom exception translator based on an exception type
  346. ///
  347. /// tparam ExceptionType Exception type for which you want to erase the translator
  348. template<typename ExceptionType>
  349. void erase_exception_translator( boost::type<ExceptionType>* = 0 )
  350. {
  351. m_custom_translators = m_custom_translators->erase<ExceptionType>( m_custom_translators );
  352. }
  353. //@}
  354. #endif
  355. private:
  356. // implementation helpers
  357. int catch_signals( boost::function<int ()> const& F );
  358. // Data members
  359. detail::translator_holder_base_ptr m_custom_translators;
  360. boost::scoped_array<char> m_alt_stack;
  361. }; // execution_monitor
  362. // ************************************************************************** //
  363. // ************** detail::translator_holder ************** //
  364. // ************************************************************************** //
  365. namespace detail {
  366. template<typename ExceptionType, typename ExceptionTranslator>
  367. class translator_holder : public translator_holder_base
  368. {
  369. public:
  370. explicit translator_holder( ExceptionTranslator const& tr, translator_holder_base_ptr& next, const_string tag = const_string() )
  371. : translator_holder_base( next, tag ), m_translator( tr ) {}
  372. // translator holder interface
  373. virtual int operator()( boost::function<int ()> const& F )
  374. {
  375. BOOST_TEST_I_TRY {
  376. return m_next ? (*m_next)( F ) : F();
  377. }
  378. BOOST_TEST_I_CATCH( ExceptionType, e ) {
  379. m_translator( e );
  380. return boost::exit_exception_failure;
  381. }
  382. }
  383. #ifndef BOOST_NO_RTTI
  384. virtual translator_holder_base_ptr erase( translator_holder_base_ptr this_, std::type_info const& ti )
  385. {
  386. return ti == typeid(ExceptionType) ? m_next : this_;
  387. }
  388. #endif
  389. private:
  390. // Data members
  391. ExceptionTranslator m_translator;
  392. };
  393. } // namespace detail
  394. template<typename ExceptionType, typename ExceptionTranslator>
  395. void
  396. execution_monitor::register_exception_translator( ExceptionTranslator const& tr, const_string tag, boost::type<ExceptionType>* )
  397. {
  398. m_custom_translators.reset(
  399. new detail::translator_holder<ExceptionType,ExceptionTranslator>( tr, m_custom_translators, tag ) );
  400. }
  401. // ************************************************************************** //
  402. /// @class execution_aborted
  403. /// @brief This is a trivial default constructible class. Use it to report graceful abortion of a monitored function execution.
  404. // ************************************************************************** //
  405. struct execution_aborted {};
  406. // ************************************************************************** //
  407. // ************** system_error ************** //
  408. // ************************************************************************** //
  409. class system_error {
  410. public:
  411. // Constructor
  412. explicit system_error( char const* exp );
  413. long const p_errno;
  414. char const* const p_failed_exp;
  415. };
  416. //!@internal
  417. #define BOOST_TEST_SYS_ASSERT( cond ) BOOST_TEST_I_ASSRT( cond, ::boost::system_error( BOOST_STRINGIZE( exp ) ) )
  418. // ************************************************************************** //
  419. // **************Floating point exception management interface ************** //
  420. // ************************************************************************** //
  421. namespace fpe {
  422. enum masks {
  423. BOOST_FPE_OFF = 0,
  424. #if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__) /* *** */
  425. BOOST_FPE_DIVBYZERO = EM_ZERODIVIDE,
  426. BOOST_FPE_INEXACT = EM_INEXACT,
  427. BOOST_FPE_INVALID = EM_INVALID,
  428. BOOST_FPE_OVERFLOW = EM_OVERFLOW,
  429. BOOST_FPE_UNDERFLOW = EM_UNDERFLOW|EM_DENORMAL,
  430. BOOST_FPE_ALL = MCW_EM,
  431. #elif !defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)/* *** */
  432. BOOST_FPE_DIVBYZERO = BOOST_FPE_OFF,
  433. BOOST_FPE_INEXACT = BOOST_FPE_OFF,
  434. BOOST_FPE_INVALID = BOOST_FPE_OFF,
  435. BOOST_FPE_OVERFLOW = BOOST_FPE_OFF,
  436. BOOST_FPE_UNDERFLOW = BOOST_FPE_OFF,
  437. BOOST_FPE_ALL = BOOST_FPE_OFF,
  438. #else /* *** */
  439. #if defined(FE_DIVBYZERO)
  440. BOOST_FPE_DIVBYZERO = FE_DIVBYZERO,
  441. #else
  442. BOOST_FPE_DIVBYZERO = BOOST_FPE_OFF,
  443. #endif
  444. #if defined(FE_INEXACT)
  445. BOOST_FPE_INEXACT = FE_INEXACT,
  446. #else
  447. BOOST_FPE_INEXACT = BOOST_FPE_OFF,
  448. #endif
  449. #if defined(FE_INVALID)
  450. BOOST_FPE_INVALID = FE_INVALID,
  451. #else
  452. BOOST_FPE_INVALID = BOOST_FPE_OFF,
  453. #endif
  454. #if defined(FE_OVERFLOW)
  455. BOOST_FPE_OVERFLOW = FE_OVERFLOW,
  456. #else
  457. BOOST_FPE_OVERFLOW = BOOST_FPE_OFF,
  458. #endif
  459. #if defined(FE_UNDERFLOW)
  460. BOOST_FPE_UNDERFLOW = FE_UNDERFLOW,
  461. #else
  462. BOOST_FPE_UNDERFLOW = BOOST_FPE_OFF,
  463. #endif
  464. #if defined(FE_ALL_EXCEPT)
  465. BOOST_FPE_ALL = FE_ALL_EXCEPT,
  466. #else
  467. BOOST_FPE_ALL = BOOST_FPE_OFF,
  468. #endif
  469. #endif /* *** */
  470. BOOST_FPE_INV = BOOST_FPE_ALL+1
  471. };
  472. //____________________________________________________________________________//
  473. // return the previous set of enabled exceptions when successful, and BOOST_FPE_INV otherwise
  474. unsigned BOOST_TEST_DECL enable( unsigned mask );
  475. unsigned BOOST_TEST_DECL disable( unsigned mask );
  476. //____________________________________________________________________________//
  477. } // namespace fpe
  478. ///@}
  479. } // namespace boost
  480. #include <boost/test/detail/enable_warnings.hpp>
  481. #endif