// // Bugcheck.h // // Library: Foundation // Package: Core // Module: Bugcheck // // Definition of the Bugcheck class and the self-testing macros. // // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // and Contributors. // // SPDX-License-Identifier: BSL-1.0 // #ifndef Foundation_Bugcheck_INCLUDED #define Foundation_Bugcheck_INCLUDED #include "Poco/Foundation.h" #include #include #if defined(_DEBUG) # include #endif namespace Poco { class Foundation_API Bugcheck /// This class provides some static methods that are /// used by the /// poco_assert_dbg(), poco_assert(), poco_check_ptr(), /// poco_bugcheck() and poco_unexpected() macros. /// You should not invoke these methods /// directly. Use the macros instead, as they /// automatically provide useful context information. { public: static void assertion(const char* cond, const char* file, int line, const char* text = 0); /// An assertion failed. Break into the debugger, if /// possible, then throw an AssertionViolationException. static void nullPointer(const char* ptr, const char* file, int line); /// An null pointer was encountered. Break into the debugger, if /// possible, then throw an NullPointerException. static void bugcheck(const char* file, int line); /// An internal error was encountered. Break into the debugger, if /// possible, then throw an BugcheckException. static void bugcheck(const char* msg, const char* file, int line); /// An internal error was encountered. Break into the debugger, if /// possible, then throw an BugcheckException. static void unexpected(const char* file, int line); /// An exception was caught in a destructor. Break into debugger, /// if possible and report exception. Must only be called from /// within a catch () block as it rethrows the exception to /// determine its class. static void debugger(const char* file, int line); /// An internal error was encountered. Break into the debugger, if /// possible. static void debugger(const char* msg, const char* file, int line); /// An internal error was encountered. Break into the debugger, if /// possible. protected: static std::string what(const char* msg, const char* file, int line, const char* text = 0); }; } // namespace Poco // // useful macros (these automatically supply line number and file name) // #if defined(__KLOCWORK__) || defined(__clang_analyzer__) // Short-circuit these macros when under static analysis. // Ideally, static analysis tools should understand and reason correctly about // noreturn methods such as Bugcheck::bugcheck(). In practice, they don't. // Help them by turning these macros into std::abort() as described here: // https://developer.klocwork.com/documentation/en/insight/10-1/tuning-cc-analysis#Usingthe__KLOCWORK__macro #include // for abort #define poco_assert_dbg(cond) do { if (!(cond)) std::abort(); } while (0) #define poco_assert_msg_dbg(cond, text) do { if (!(cond)) std::abort(); } while (0) #define poco_assert(cond) do { if (!(cond)) std::abort(); } while (0) #define poco_assert_msg(cond, text) do { if (!(cond)) std::abort(); } while (0) #define poco_check_ptr(ptr) do { if (!(ptr)) std::abort(); } while (0) #define poco_bugcheck() do { std::abort(); } while (0) #define poco_bugcheck_msg(msg) do { std::abort(); } while (0) #else // defined(__KLOCWORK__) || defined(__clang_analyzer__) #if defined(_DEBUG) #define poco_assert_dbg(cond) \ if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0 #define poco_assert_msg_dbg(cond, text) \ if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__, text); else (void) 0 #else #define poco_assert_msg_dbg(cond, text) #define poco_assert_dbg(cond) #endif #define poco_assert(cond) \ if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0 #define poco_assert_msg(cond, text) \ if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__, text); else (void) 0 #define poco_check_ptr(ptr) \ if (!(ptr)) Poco::Bugcheck::nullPointer(#ptr, __FILE__, __LINE__); else (void) 0 #define poco_bugcheck() \ Poco::Bugcheck::bugcheck(__FILE__, __LINE__) #define poco_bugcheck_msg(msg) \ Poco::Bugcheck::bugcheck(msg, __FILE__, __LINE__) #endif // defined(__KLOCWORK__) || defined(__clang_analyzer__) #define poco_unexpected() \ Poco::Bugcheck::unexpected(__FILE__, __LINE__); #define poco_debugger() \ Poco::Bugcheck::debugger(__FILE__, __LINE__) #define poco_debugger_msg(msg) \ Poco::Bugcheck::debugger(msg, __FILE__, __LINE__) #if defined(_DEBUG) # define poco_stdout_dbg(outstr) \ std::cout << __FILE__ << '(' << std::dec << __LINE__ << "):" << outstr << std::endl; #else # define poco_stdout_dbg(outstr) #endif #if defined(_DEBUG) # define poco_stderr_dbg(outstr) \ std::cerr << __FILE__ << '(' << std::dec << __LINE__ << "):" << outstr << std::endl; #else # define poco_stderr_dbg(outstr) #endif // // poco_static_assert // // The following was ported from // template struct POCO_STATIC_ASSERTION_FAILURE; template <> struct POCO_STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; template struct poco_static_assert_test { }; #if defined(__GNUC__) && (__GNUC__ == 3) && ((__GNUC_MINOR__ == 3) || (__GNUC_MINOR__ == 4)) #define poco_static_assert(B) \ typedef char POCO_JOIN(poco_static_assert_typedef_, __LINE__) \ [POCO_STATIC_ASSERTION_FAILURE<(bool) (B)>::value] #else #define poco_static_assert(B) \ typedef poco_static_assert_test)> \ POCO_JOIN(poco_static_assert_typedef_, __LINE__) POCO_UNUSED #endif #endif // Foundation_Bugcheck_INCLUDED