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