assertion.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include <cstdlib>
  9. // Ensures/Expects.
  10. #include <gsl/assert>
  11. namespace base {
  12. namespace assertion {
  13. void log(const char *message, const char *file, int line);
  14. // Release build assertions.
  15. inline constexpr void noop() {
  16. }
  17. [[noreturn]] inline void fail(
  18. const char *message,
  19. const char *file,
  20. int line) {
  21. log(message, file, line);
  22. // Crash with access violation and generate crash report.
  23. volatile auto nullptr_value = (int*)nullptr;
  24. *nullptr_value = 0;
  25. // Silent the possible failure to comply noreturn warning.
  26. std::abort();
  27. }
  28. constexpr const char* extract_basename(const char* path, size_t size) {
  29. while (size != 0 && path[size - 1] != '/' && path[size - 1] != '\\') {
  30. --size;
  31. }
  32. return path + size;
  33. }
  34. } // namespace assertion
  35. } // namespace base
  36. #if defined(__clang__) || defined(__GNUC__)
  37. #define AssertUnlikelyHelper(x) __builtin_expect(!!(x), 0)
  38. #else
  39. #define AssertUnlikelyHelper(x) (!!(x))
  40. #endif
  41. #define AssertValidationCondition(condition, message, file, line)\
  42. ((AssertUnlikelyHelper(!(condition)))\
  43. ? ::base::assertion::fail(message, file, line)\
  44. : ::base::assertion::noop())
  45. #define SOURCE_FILE_BASENAME (::base::assertion::extract_basename(\
  46. __FILE__,\
  47. sizeof(__FILE__)))
  48. #define AssertCustom(condition, message) (AssertValidationCondition(\
  49. condition,\
  50. message,\
  51. SOURCE_FILE_BASENAME,\
  52. __LINE__))
  53. #define Assert(condition) AssertCustom(condition, "\"" #condition "\"")
  54. // Define our own versions of Expects() and Ensures().
  55. // Let them crash with reports and logging.
  56. #ifdef Expects
  57. #undef Expects
  58. #endif // Expects
  59. #define Expects(condition) (AssertValidationCondition(\
  60. condition,\
  61. "\"" #condition "\"",\
  62. SOURCE_FILE_BASENAME,\
  63. __LINE__))
  64. #ifdef Ensures
  65. #undef Ensures
  66. #endif // Ensures
  67. #define Ensures(condition) (AssertValidationCondition(\
  68. condition,\
  69. "\"" #condition "\"",\
  70. SOURCE_FILE_BASENAME,\
  71. __LINE__))
  72. #ifdef Unexpected
  73. #undef Unexpected
  74. #endif // Unexpected
  75. #define Unexpected(message) (::base::assertion::fail(\
  76. "Unexpected: " message,\
  77. SOURCE_FILE_BASENAME,\
  78. __LINE__))
  79. #ifdef _DEBUG
  80. #define AssertIsDebug(...)
  81. #endif // _DEBUG