summary refs log tree commit diff
path: root/src/Common/Assert.hpp
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2024-02-05 11:29:12 +0100
committerMel <einebeere@gmail.com>2024-02-05 11:29:12 +0100
commitbcb89e0554e43d37daf74b3ef6e466b6630752cd (patch)
tree4bd01a9180d85c51258647d8974dbdd1d7c660d1 /src/Common/Assert.hpp
parente2e52b7069d2eeed18e935616d72af5774b14a97 (diff)
downloadmeowcraft-bcb89e0554e43d37daf74b3ef6e466b6630752cd.tar.zst
meowcraft-bcb89e0554e43d37daf74b3ef6e466b6630752cd.zip
Custom debuggable ASSERT macro
Diffstat (limited to 'src/Common/Assert.hpp')
-rw-r--r--src/Common/Assert.hpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/Common/Assert.hpp b/src/Common/Assert.hpp
new file mode 100644
index 0000000..9fc84ce
--- /dev/null
+++ b/src/Common/Assert.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <csignal>
+
+// https://stackoverflow.com/a/26100478/11342122
+// Two levels are needed to make sure that the argument is expanded before stringification
+#define _ASSERT_IS_DEFINED(x) _ASSERT_IS_DEFINED2(x)
+// TODO: This doesn't compile away on -O0, but it's not a big deal
+#define _ASSERT_IS_DEFINED2(x) (#x[0] == 0 || (#x[0] >= '1' && #x[0] <= '9'))
+
+// Stopping macro, non-fatal in debug mode
+#define _ASSERT_STOP (_ASSERT_IS_DEFINED(NDEBUG) ? std::abort() : (void)raise(SIGTRAP))
+
+// Assertion message macros, with optional message
+#define _ASSERT_NOTIFY_NO_MESSAGE(start) std::fprintf(stderr, start ".\n", __FILE__, __LINE__)
+#define _ASSERT_NOTIFY_WITH_MESSAGE(start, message) std::fprintf(stderr, start ": %s\n", __FILE__, __LINE__, message "")
+#define _ASSERT_NOTIFY(start, ...) ((strcmp(__VA_ARGS__ "", "") == 0) ? _ASSERT_NOTIFY_NO_MESSAGE(start) : _ASSERT_NOTIFY_WITH_MESSAGE(start, __VA_ARGS__))
+
+// Debuggable assertion macro, with optional message
+#define ASSERT(condition, ...) do { \
+    if (__builtin_expect(!(condition), 0)) { \
+        _ASSERT_NOTIFY("ASSERT(" #condition ") failed at %s:%d", __VA_ARGS__); \
+        _ASSERT_STOP; \
+    } \
+} while (0)
+
+// Debuggable unreachable macro, with optional message
+#define UNREACHABLE(...) do { \
+    _ASSERT_NOTIFY("UNREACHABLE() reached at %s:%d", __VA_ARGS__); \
+    _ASSERT_STOP; \
+} while (0)
\ No newline at end of file