1
0

mptAssert.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * mptAssert.h
  3. * -----------
  4. * Purpose: assert and static_assert
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "mpt/base/source_location.hpp"
  12. #include "mptBaseMacros.h"
  13. OPENMPT_NAMESPACE_BEGIN
  14. // Static code checkers might need to get the knowledge of our assertions transferred to them.
  15. #define MPT_CHECKER_ASSUME_ASSERTIONS 1
  16. //#define MPT_CHECKER_ASSUME_ASSERTIONS 0
  17. #ifdef MPT_BUILD_ANALYZED
  18. #if MPT_COMPILER_MSVC
  19. #if MPT_CHECKER_ASSUME_ASSERTIONS
  20. #define MPT_CHECKER_ASSUME(x) __analysis_assume(!!(x))
  21. #endif
  22. #elif MPT_COMPILER_CLANG
  23. #if MPT_CHECKER_ASSUME_ASSERTIONS
  24. #ifdef NDEBUG
  25. #error "Builds for static analyzers depend on assert() being enabled, but the current build has #define NDEBUG. This makes no sense."
  26. #endif
  27. OPENMPT_NAMESPACE_END
  28. #include <cassert>
  29. OPENMPT_NAMESPACE_BEGIN
  30. #define MPT_CHECKER_ASSUME(x) assert(!!(x))
  31. #endif
  32. #endif // MPT_COMPILER
  33. #endif // MPT_BUILD_ANALYZED
  34. #ifndef MPT_CHECKER_ASSUME
  35. #define MPT_CHECKER_ASSUME(x) do { } while(0)
  36. #endif
  37. #if defined(MPT_WITH_MFC) && !defined(MPT_CPPCHECK_CUSTOM)
  38. #if !defined(ASSERT)
  39. #error "MFC is expected to #define ASSERT"
  40. #endif // !defined(ASERRT)
  41. #define MPT_FRAMEWORK_ASSERT_IS_DEFINED
  42. #if defined(_DEBUG)
  43. #define MPT_FRAMEWORK_ASSERT_IS_ACTIVE 1
  44. #else // !_DEBUG
  45. #define MPT_FRAMEWORK_ASSERT_IS_ACTIVE 0
  46. #endif // _DEBUG
  47. // let MFC handle our asserts
  48. #define MPT_ASSERT_USE_FRAMEWORK 1
  49. #else // !MPT_WITH_MFC
  50. #if defined(ASSERT)
  51. #define MPT_FRAMEWORK_ASSERT_IS_DEFINED
  52. #if defined(_DEBUG)
  53. #define MPT_FRAMEWORK_ASSERT_IS_ACTIVE 1
  54. #else // !_DEBUG
  55. #define MPT_FRAMEWORK_ASSERT_IS_ACTIVE 0
  56. #endif // _DEBUG
  57. #endif // !defined(ASERRT)
  58. // handle assert in our own way without relying on some platform-/framework-specific assert implementation
  59. #define MPT_ASSERT_USE_FRAMEWORK 0
  60. #endif // MPT_WITH_MFC
  61. #if defined(MPT_FRAMEWORK_ASSERT_IS_DEFINED) && (MPT_ASSERT_USE_FRAMEWORK == 1)
  62. #define MPT_ASSERT_NOTREACHED() ASSERT(0)
  63. #define MPT_ASSERT(expr) ASSERT((expr))
  64. #define MPT_ASSERT_MSG(expr, msg) ASSERT((expr) && (msg))
  65. #if (MPT_FRAMEWORK_ASSERT_IS_ACTIVE == 1)
  66. #define MPT_ASSERT_ALWAYS(expr) ASSERT((expr))
  67. #define MPT_ASSERT_ALWAYS_MSG(expr, msg) ASSERT((expr) && (msg))
  68. #else
  69. #define MPT_ASSERT_ALWAYS(expr) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } while(0)
  70. #define MPT_ASSERT_ALWAYS_MSG(expr, msg) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr, msg); } MPT_CHECKER_ASSUME(expr); } while(0)
  71. #ifndef MPT_ASSERT_HANDLER_NEEDED
  72. #define MPT_ASSERT_HANDLER_NEEDED
  73. #endif
  74. #endif
  75. #elif defined(NO_ASSERTS)
  76. #define MPT_ASSERT_NOTREACHED() MPT_CHECKER_ASSUME(0)
  77. #define MPT_ASSERT(expr) MPT_CHECKER_ASSUME(expr)
  78. #define MPT_ASSERT_MSG(expr, msg) MPT_CHECKER_ASSUME(expr)
  79. #define MPT_ASSERT_ALWAYS(expr) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } while(0)
  80. #define MPT_ASSERT_ALWAYS_MSG(expr, msg) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr, msg); } MPT_CHECKER_ASSUME(expr); } while(0)
  81. #ifndef MPT_ASSERT_HANDLER_NEEDED
  82. #define MPT_ASSERT_HANDLER_NEEDED
  83. #endif
  84. #else // !NO_ASSERTS
  85. #define MPT_ASSERT_NOTREACHED() do { if constexpr(!(0)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), "0"); } MPT_CHECKER_ASSUME(0); } while(0)
  86. #define MPT_ASSERT(expr) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } while(0)
  87. #define MPT_ASSERT_MSG(expr, msg) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr, msg); } MPT_CHECKER_ASSUME(expr); } while(0)
  88. #define MPT_ASSERT_ALWAYS(expr) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } while(0)
  89. #define MPT_ASSERT_ALWAYS_MSG(expr, msg) do { if(!(expr)) { OPENMPT_NAMESPACE::AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr, msg); } MPT_CHECKER_ASSUME(expr); } while(0)
  90. #ifndef MPT_ASSERT_HANDLER_NEEDED
  91. #define MPT_ASSERT_HANDLER_NEEDED
  92. #endif
  93. #endif // NO_ASSERTS
  94. #if defined(MPT_ASSERT_HANDLER_NEEDED)
  95. // custom assert handler needed
  96. MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *expr, const char *msg=nullptr);
  97. #endif // MPT_ASSERT_HANDLER_NEEDED
  98. OPENMPT_NAMESPACE_END