Преглед изворни кода

avutil/avassert: Add av_unreachable() and av_assume() macros

Useful to let the compiler and static analyzers know that
something is unreachable without adding an av_assert
(which would be either dead for the compiler or add runtime
overhead) for this.
The implementation used here enforces the use of a message
to provide a reason why a particular code is supposed to be
unreachable.

Reviewed-by: Ramiro Polla <ramiro.polla@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Andreas Rheinhardt пре 4 година
родитељ
комит
004cc60f0e
3 измењених фајлова са 46 додато и 1 уклоњено
  1. 3 0
      doc/APIchanges
  2. 42 0
      libavutil/avassert.h
  3. 1 1
      libavutil/version.h

+ 3 - 0
doc/APIchanges

@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
 
 API changes, most recent first:
 
+2025-05-21 - xxxxxxxxxx - lavu 60.3.100 - avassert.h
+  Add av_unreachable() and av_assume() macros.
+
 2025-02-xx - xxxxxxxxxx - lavfi 10.10.100 - avfilter.h
   Add avfilter_link_get_hw_frames_ctx().
 

+ 42 - 0
libavutil/avassert.h

@@ -31,6 +31,7 @@
 #ifdef HAVE_AV_CONFIG_H
 #   include "config.h"
 #endif
+#include "attributes.h"
 #include "log.h"
 #include "macros.h"
 
@@ -75,4 +76,45 @@
  */
 void av_assert0_fpu(void);
 
+/**
+ * Asserts that are used as compiler optimization hints depending
+ * upon ASSERT_LEVEL and NBDEBUG.
+ *
+ * Undefined behaviour occurs if execution reaches a point marked
+ * with av_unreachable() or if a condition used with av_assume()
+ * is false.
+ *
+ * The condition used with av_assume() should not have side-effects
+ * and should be visible to the compiler.
+ */
+#if defined(ASSERT_LEVEL) ? ASSERT_LEVEL > 0 : !defined(HAVE_AV_CONFIG_H) && !defined(NDEBUG)
+#define av_unreachable(msg)                                             \
+do {                                                                    \
+    av_log(NULL, AV_LOG_PANIC,                                          \
+           "Reached supposedly unreachable code at %s:%d: %s\n",        \
+           __FILE__, __LINE__, msg);                                    \
+    abort();                                                            \
+} while (0)
+#define av_assume(cond) av_assert0(cond)
+#else
+#if AV_GCC_VERSION_AT_LEAST(4, 5) || AV_HAS_BUILTIN(__builtin_unreachable)
+#define av_unreachable(msg) __builtin_unreachable()
+#elif  defined(_MSC_VER)
+#define av_unreachable(msg) __assume(0)
+#define av_assume(cond)     __assume(cond)
+#elif __STDC_VERSION__ >= 202311L
+#include <stddef.h>
+#define av_unreachable(msg) unreachable()
+#else
+#define av_unreachable(msg) ((void)0)
+#endif
+
+#ifndef av_assume
+#define av_assume(cond) do { \
+    if (!(cond))             \
+        av_unreachable();    \
+} while (0)
+#endif
+#endif
+
 #endif /* AVUTIL_AVASSERT_H */

+ 1 - 1
libavutil/version.h

@@ -79,7 +79,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  60
-#define LIBAVUTIL_VERSION_MINOR   2
+#define LIBAVUTIL_VERSION_MINOR   3
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \