+#ifdef BT_DEV_MODE
+/* Developer mode version of BT_ASSERT_PRE_MSG(). */
+# define BT_ASSERT_PRE_DEV_MSG(_fmt, ...) \
+ BT_ASSERT_PRE_MSG(_fmt, ##__VA_ARGS__)
+
+/* Developer mode version of BT_ASSERT_PRE(). */
+# define BT_ASSERT_PRE_DEV(_cond, _fmt, ...) \
+ BT_ASSERT_PRE((_cond), _fmt, ##__VA_ARGS__)
+
+/* Developer mode version of BT_ASSERT_PRE_NON_NULL() */
+# define BT_ASSERT_PRE_DEV_NON_NULL(_obj, _obj_name) \
+ BT_ASSERT_PRE_NON_NULL((_obj), (_obj_name))
+
+/*
+ * Developer mode: asserts that a given object `_obj` named `_obj_name`
+ * (capitalized) is NOT frozen. This macro checks the `frozen` field of
+ * `_obj`.
+ *
+ * This currently only exists in developer mode because some freezing
+ * functions can be called on the fast path, so they too are only
+ * enabled in developer mode.
+ */
+# define BT_ASSERT_PRE_DEV_HOT(_obj, _obj_name, _fmt, ...) \
+ BT_ASSERT_PRE(!(_obj)->frozen, "%s is frozen" _fmt, _obj_name, \
+ ##__VA_ARGS__)
+
+/* Developer mode version of BT_ASSERT_PRE_VALID_INDEX() */
+# define BT_ASSERT_PRE_DEV_VALID_INDEX(_index, _length) \
+ BT_ASSERT_PRE_VALID_INDEX((_index), (_length))
+
+/*
+ * Marks a function as being only used within a BT_ASSERT_PRE_DEV()
+ * context.
+ */
+# define BT_ASSERT_PRE_DEV_FUNC
+#else
+# define BT_ASSERT_PRE_DEV_MSG(_fmt, ...)
+# define BT_ASSERT_PRE_DEV(_cond, _fmt, ...) ((void) sizeof((void) (_cond), 0))
+# define BT_ASSERT_PRE_DEV_NON_NULL(_obj, _obj_name) \
+ ((void) sizeof((void) (_obj), (void) (_obj_name), 0))
+# define BT_ASSERT_PRE_DEV_HOT(_obj, _obj_name, _fmt, ...) \
+ ((void) sizeof((void) (_obj), (void) (_obj_name), 0))
+# define BT_ASSERT_PRE_DEV_VALID_INDEX(_index, _length) \
+ ((void) sizeof((void) (_index), (void) (_length), 0))
+# define BT_ASSERT_PRE_DEV_FUNC __attribute__((unused))
+#endif /* BT_DEV_MODE */
+
+#define BT_ASSERT_PRE_SUPPORTED
+