Bugcheck.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //
  2. // Bugcheck.h
  3. //
  4. // Library: Foundation
  5. // Package: Core
  6. // Module: Bugcheck
  7. //
  8. // Definition of the Bugcheck class and the self-testing macros.
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Foundation_Bugcheck_INCLUDED
  16. #define Foundation_Bugcheck_INCLUDED
  17. #include "Poco/Foundation.h"
  18. #include <string>
  19. #include <cstdlib>
  20. #if defined(_DEBUG)
  21. # include <iostream>
  22. #endif
  23. namespace Poco {
  24. class Foundation_API Bugcheck
  25. /// This class provides some static methods that are
  26. /// used by the
  27. /// poco_assert_dbg(), poco_assert(), poco_check_ptr(),
  28. /// poco_bugcheck() and poco_unexpected() macros.
  29. /// You should not invoke these methods
  30. /// directly. Use the macros instead, as they
  31. /// automatically provide useful context information.
  32. {
  33. public:
  34. static void assertion(const char* cond, const char* file, int line, const char* text = 0);
  35. /// An assertion failed. Break into the debugger, if
  36. /// possible, then throw an AssertionViolationException.
  37. static void nullPointer(const char* ptr, const char* file, int line);
  38. /// An null pointer was encountered. Break into the debugger, if
  39. /// possible, then throw an NullPointerException.
  40. static void bugcheck(const char* file, int line);
  41. /// An internal error was encountered. Break into the debugger, if
  42. /// possible, then throw an BugcheckException.
  43. static void bugcheck(const char* msg, const char* file, int line);
  44. /// An internal error was encountered. Break into the debugger, if
  45. /// possible, then throw an BugcheckException.
  46. static void unexpected(const char* file, int line);
  47. /// An exception was caught in a destructor. Break into debugger,
  48. /// if possible and report exception. Must only be called from
  49. /// within a catch () block as it rethrows the exception to
  50. /// determine its class.
  51. static void debugger(const char* file, int line);
  52. /// An internal error was encountered. Break into the debugger, if
  53. /// possible.
  54. static void debugger(const char* msg, const char* file, int line);
  55. /// An internal error was encountered. Break into the debugger, if
  56. /// possible.
  57. protected:
  58. static std::string what(const char* msg, const char* file, int line, const char* text = 0);
  59. };
  60. } // namespace Poco
  61. //
  62. // useful macros (these automatically supply line number and file name)
  63. //
  64. #if defined(__KLOCWORK__) || defined(__clang_analyzer__)
  65. // Short-circuit these macros when under static analysis.
  66. // Ideally, static analysis tools should understand and reason correctly about
  67. // noreturn methods such as Bugcheck::bugcheck(). In practice, they don't.
  68. // Help them by turning these macros into std::abort() as described here:
  69. // https://developer.klocwork.com/documentation/en/insight/10-1/tuning-cc-analysis#Usingthe__KLOCWORK__macro
  70. #include <cstdlib> // for abort
  71. #define poco_assert_dbg(cond) do { if (!(cond)) std::abort(); } while (0)
  72. #define poco_assert_msg_dbg(cond, text) do { if (!(cond)) std::abort(); } while (0)
  73. #define poco_assert(cond) do { if (!(cond)) std::abort(); } while (0)
  74. #define poco_assert_msg(cond, text) do { if (!(cond)) std::abort(); } while (0)
  75. #define poco_check_ptr(ptr) do { if (!(ptr)) std::abort(); } while (0)
  76. #define poco_bugcheck() do { std::abort(); } while (0)
  77. #define poco_bugcheck_msg(msg) do { std::abort(); } while (0)
  78. #else // defined(__KLOCWORK__) || defined(__clang_analyzer__)
  79. #if defined(_DEBUG)
  80. #define poco_assert_dbg(cond) \
  81. if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0
  82. #define poco_assert_msg_dbg(cond, text) \
  83. if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__, text); else (void) 0
  84. #else
  85. #define poco_assert_msg_dbg(cond, text)
  86. #define poco_assert_dbg(cond)
  87. #endif
  88. #define poco_assert(cond) \
  89. if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0
  90. #define poco_assert_msg(cond, text) \
  91. if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__, text); else (void) 0
  92. #define poco_check_ptr(ptr) \
  93. if (!(ptr)) Poco::Bugcheck::nullPointer(#ptr, __FILE__, __LINE__); else (void) 0
  94. #define poco_bugcheck() \
  95. Poco::Bugcheck::bugcheck(__FILE__, __LINE__)
  96. #define poco_bugcheck_msg(msg) \
  97. Poco::Bugcheck::bugcheck(msg, __FILE__, __LINE__)
  98. #endif // defined(__KLOCWORK__) || defined(__clang_analyzer__)
  99. #define poco_unexpected() \
  100. Poco::Bugcheck::unexpected(__FILE__, __LINE__);
  101. #define poco_debugger() \
  102. Poco::Bugcheck::debugger(__FILE__, __LINE__)
  103. #define poco_debugger_msg(msg) \
  104. Poco::Bugcheck::debugger(msg, __FILE__, __LINE__)
  105. #if defined(_DEBUG)
  106. # define poco_stdout_dbg(outstr) \
  107. std::cout << __FILE__ << '(' << std::dec << __LINE__ << "):" << outstr << std::endl;
  108. #else
  109. # define poco_stdout_dbg(outstr)
  110. #endif
  111. #if defined(_DEBUG)
  112. # define poco_stderr_dbg(outstr) \
  113. std::cerr << __FILE__ << '(' << std::dec << __LINE__ << "):" << outstr << std::endl;
  114. #else
  115. # define poco_stderr_dbg(outstr)
  116. #endif
  117. //
  118. // poco_static_assert
  119. //
  120. // The following was ported from <boost/static_assert.hpp>
  121. //
  122. template <bool x>
  123. struct POCO_STATIC_ASSERTION_FAILURE;
  124. template <>
  125. struct POCO_STATIC_ASSERTION_FAILURE<true>
  126. {
  127. enum
  128. {
  129. value = 1
  130. };
  131. };
  132. template <int x>
  133. struct poco_static_assert_test
  134. {
  135. };
  136. #if defined(__GNUC__) && (__GNUC__ == 3) && ((__GNUC_MINOR__ == 3) || (__GNUC_MINOR__ == 4))
  137. #define poco_static_assert(B) \
  138. typedef char POCO_JOIN(poco_static_assert_typedef_, __LINE__) \
  139. [POCO_STATIC_ASSERTION_FAILURE<(bool) (B)>::value]
  140. #else
  141. #define poco_static_assert(B) \
  142. typedef poco_static_assert_test<sizeof(POCO_STATIC_ASSERTION_FAILURE<(bool) (B)>)> \
  143. POCO_JOIN(poco_static_assert_typedef_, __LINE__) POCO_UNUSED
  144. #endif
  145. #endif // Foundation_Bugcheck_INCLUDED