assert.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
  2. // SPDX-FileCopyrightText: 2014 Citra Emulator Project & 2024 suyu Emulator Project
  3. // SPDX-License-Identifier: GPL-2.0-or-later
  4. #pragma once
  5. #include "common/logging/log.h"
  6. // Sometimes we want to try to continue even after hitting an assert.
  7. // However touching this file yields a global recompilation as this header is included almost
  8. // everywhere. So let's just move the handling of the failed assert to a single cpp file.
  9. void assert_fail_impl();
  10. [[noreturn]] void unreachable_impl();
  11. #ifdef _MSC_VER
  12. #define SUYU_NO_INLINE __declspec(noinline)
  13. #else
  14. #define SUYU_NO_INLINE __attribute__((noinline))
  15. #endif
  16. #define ASSERT(_a_) \
  17. ([&]() SUYU_NO_INLINE { \
  18. if (!(_a_)) [[unlikely]] { \
  19. LOG_CRITICAL(Debug, "Assertion Failed!"); \
  20. assert_fail_impl(); \
  21. } \
  22. }())
  23. #define ASSERT_MSG(_a_, ...) \
  24. ([&]() SUYU_NO_INLINE { \
  25. if (!(_a_)) [[unlikely]] { \
  26. LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \
  27. assert_fail_impl(); \
  28. } \
  29. }())
  30. #define UNREACHABLE() \
  31. do { \
  32. LOG_CRITICAL(Debug, "Unreachable code!"); \
  33. unreachable_impl(); \
  34. } while (0)
  35. #define UNREACHABLE_MSG(...) \
  36. do { \
  37. LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); \
  38. unreachable_impl(); \
  39. } while (0)
  40. #ifdef _DEBUG
  41. #define DEBUG_ASSERT(_a_) ASSERT(_a_)
  42. #define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__)
  43. #else // not debug
  44. #define DEBUG_ASSERT(_a_) \
  45. do { \
  46. } while (0)
  47. #define DEBUG_ASSERT_MSG(_a_, _desc_, ...) \
  48. do { \
  49. } while (0)
  50. #endif
  51. #define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!")
  52. #define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__)
  53. #define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!")
  54. #define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__)
  55. // If the assert is ignored, execute _b_
  56. #define ASSERT_OR_EXECUTE(_a_, _b_) \
  57. do { \
  58. ASSERT(_a_); \
  59. if (!(_a_)) [[unlikely]] { \
  60. _b_ \
  61. } \
  62. } while (0)
  63. // If the assert is ignored, execute _b_
  64. #define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \
  65. do { \
  66. ASSERT_MSG(_a_, __VA_ARGS__); \
  67. if (!(_a_)) [[unlikely]] { \
  68. _b_ \
  69. } \
  70. } while (0)