Branch data Line data Source code
1 : : // ***************************************************************************** 2 : : /*! 3 : : \file src/Base/Exception.hpp 4 : : \copyright 2012-2015 J. Bakosi, 5 : : 2016-2018 Los Alamos National Security, LLC., 6 : : 2019-2021 Triad National Security, LLC. 7 : : All rights reserved. See the LICENSE file for details. 8 : : \brief Exception class declaration 9 : : \details Exception class declaration. The basic functionality provided by 10 : : the Exception class is to facilitate printing out a message, together with 11 : : the location of the exception (file, line, funcion name), as well as a call 12 : : trace if available, when an exception is thrown. This file also defines 13 : : three macros, Throw, Assert, and ErrChk, that help simplifying client code 14 : : throwing exceptions. 15 : : */ 16 : : // ***************************************************************************** 17 : : #ifndef Exception_h 18 : : #define Exception_h 19 : : 20 : : #include <exception> 21 : : #include <string> 22 : : 23 : : //! Toolkit declarations and definitions for general purpose utilities 24 : : namespace tk { 25 : : 26 : : #ifdef NDEBUG // asserts disabled 27 : : static constexpr bool ndebug = true; 28 : : #else // asserts enabled 29 : : static constexpr bool ndebug = false; 30 : : #endif 31 : : 32 : : //! \brief Throw macro that always throws an exception 33 : : //! \details Throw Exception with arguments passed in. Add source filename, 34 : : //! function name, and line number where exception occurred. This macro 35 : : //! facilitates a throw of Exception that is somehwat cleaner at the point 36 : : //! of invocation than a direct throw of Exception, as it hides the 37 : : //! file:func:line arguments. Whenever is possible, it should be used via the 38 : : //! Assert and ErrChk macros defined below. 39 : : #define Throw(...) \ 40 : : throw tk::Exception(__VA_ARGS__, __FILE__, __PRETTY_FUNCTION__, __LINE__) 41 : : 42 : : //! \brief Assert macro that only throws an exception if expr fails. 43 : : //! \details If NDEBUG is defined (e.g. cmake's RELEASE or OPTIMIZED mode), do 44 : : //! nothing, expr is not evaluated. If NDEBUG is not defined, evaluate expr. 45 : : //! If expr is true, do nothing. If expr is false, throw Exception with 46 : : //! arguments passed in. The behavior is similar to libc's assert macro, but 47 : : //! throwing an Exception instead will also generate a nice call-trace and 48 : : //! will attempt to free memory. This macro should be used to detect 49 : : //! programmer errors. 50 : : #ifdef NDEBUG 51 : : # define Assert(expr, ...) (static_cast<void>(0)) 52 : : #else // NDEBUG 53 : : # define Assert(expr, ...) \ 54 : : ((expr) ? static_cast<void>(0) : Throw(__VA_ARGS__)) 55 : : #endif // NDEBUG 56 : : 57 : : //! \brief ErrChk macro that only throws an exception if expr fails. 58 : : //! \details The behavior of this macro is the same whether NDEBUG is defined or 59 : : //! not: expr is always evaluated. If expr is true, do nothing. If expr is 60 : : //! false, throw Exception with arguments passed in. This macro should be 61 : : //! used to detect user or runtime errors. 62 : : #define ErrChk(expr, ...) \ 63 : : ((expr) ? static_cast<void>(0) : Throw(__VA_ARGS__)) 64 : : 65 : : //! Error codes for the OS (or whatever calls us) 66 : : enum ErrCode { SUCCESS = EXIT_SUCCESS, //!< Everything went fine 67 : : FAILURE = EXIT_FAILURE //!< Exceptions occurred 68 : : }; 69 : : 70 : : //! \brief Basic exception class for producing file:func:line info + call trace 71 : : //! \details The basic functionality provided by the Exception class is to 72 : : //! facilitate printing out a message, together with the location of the 73 : : //! exception (file, line, funcion name), as well as a call trace if 74 : : //! available, when an exception is thrown. 75 : : class Exception : public std::exception { 76 : : 77 : : public: 78 : : //! Constructor 79 : : explicit Exception( std::string&& message, 80 : : std::string&& file = "", 81 : : std::string&& function = "", 82 : : unsigned int line = 0 ) noexcept; 83 : : 84 : : //! Destructor 85 : : virtual ~Exception() noexcept override; 86 : : 87 : : //! Force move constructor for throws 88 : : Exception(Exception&&) = default; 89 : : 90 : : //! Redefine std::exception's what() 91 : : //! \return C-style string to exception message 92 : 6 : virtual const char* what() const noexcept override { 93 : 6 : return m_message.c_str(); 94 : : } 95 : : 96 : : //! Handle Exception 97 : : virtual ErrCode handleException() noexcept; 98 : : 99 : : //! Accessor to function name 100 : : //! \return Reference to function name in which the exception occurred 101 : : const std::string& func() const noexcept { return m_func; } 102 : : 103 : : private: 104 : : // Use move constructor by default 105 : : //! Don't permit copy constructor 106 : : Exception(const Exception&) = delete; 107 : : //! Don't permit copy assignment 108 : : Exception& operator=(const Exception&) = delete; 109 : : //! Don't permit move assignment 110 : : Exception& operator=(Exception&&) = delete; 111 : : 112 : : //! Save call trace 113 : : void saveTrace() noexcept; 114 : : 115 : : //! Demangle and Echo call trace 116 : : void echoTrace() noexcept; 117 : : 118 : : const std::string m_file; //!< Source file where exception is occurred 119 : : const std::string m_func; //!< Function name where exception is occurred 120 : : const unsigned int m_line; //!< Source line where exception is occurred 121 : : 122 : : std::string m_message; //!< Error message 123 : : void* m_addrList[128]; //!< Call-stack before exception 124 : : int m_addrLength; //!< Number of stack frames 125 : : char** m_symbolList; //!< Symbol list of stack entries 126 : : }; 127 : : 128 : : } // tk:: 129 : : 130 : : #endif // Exception_h