Commit 17bd4311a4 for ffmpeg

commit 17bd4311a47e62cb6ae9ac83e40b5753c83ccc92
Author: Niklas Haas <git@haasn.dev>
Date:   Fri Oct 23 20:20:09 2026 +0200

    Squashed 'tests/checkasm/ext/' changes from dc9930dd0b..59b5d6d438

    59b5d6d438 riscv/cpu: define _GNU_SOURCE before including internal.h
    3bbd9e31ed Allow adding attributes to BUF_RECT() buffers
    61fd704965 Avoid compiling empty translation units
    fc6b9f911b utils: limit statusline to terminal width
    a2f3c11121 utils: distinguish between known and unknown terminal width
    d7d0c463b8 utils: move statusline clear/print logic to helper functions

    git-subtree-dir: tests/checkasm/ext
    git-subtree-split: 59b5d6d43824fea3678a2e7b1602de01d029bd2c

diff --git a/docs/writing-tests.md b/docs/writing-tests.md
index 62daedd348..9e953d0cb3 100644
--- a/docs/writing-tests.md
+++ b/docs/writing-tests.md
@@ -75,6 +75,9 @@ CHECKASM_ALIGN(uint8_t buf[1024]);
 // For 2D buffers with automatic padding and stride calculation
 // - Defines `dst` as a pointer to a 64x32 area, and `dst_stride` (in bytes)
 BUF_RECT(uint8_t, dst, 64, 32);
+
+// Large buffers can be made static to avoid overflowing the stack
+static BUF_RECT(uint16_t, frame, 3840, 2160);
 @endcode

 **Important:** Apply CHECKASM_ALIGN() to each buffer individually:
diff --git a/include/checkasm/utils.h b/include/checkasm/utils.h
index 518b4e84e2..58b3200ad8 100644
--- a/include/checkasm/utils.h
+++ b/include/checkasm/utils.h
@@ -670,6 +670,10 @@ CHECKASM_API int checkasm_check_impl_float_ulp(const char *file, int line,
  * - name_buf_h: Total buffer height in lines (with padding)
  * - name: Pointer to start of usable region
  *
+ * @note This macro can be prefixed with additional attributes, e.g. `static`,
+ * to affect the storage class of the actual array. The other variables are
+ * always local, so this must still be used inside a function.
+ *
  * @code
  * BUF_RECT(uint8_t, src, 64, 32);
  * BUF_RECT(uint8_t, dst, 64, 32);
@@ -678,12 +682,14 @@ CHECKASM_API int checkasm_check_impl_float_ulp(const char *file, int line,
  * CLEAR_BUF_RECT(dst);
  * // ...
  * checkasm_call_new(dst, dst_stride, src, src_stride, 64, 32);
+ *
+ * static BUF_RECT(uint8_t, big, 4096, 2160); // not allocated on the stack
  * @endcode
  */
 #define BUF_RECT(type, name, w, h)                                                       \
+    CHECKASM_ALIGN(type name##_buf[((h) + 32) * (CHECKASM_ROUND(w, 64) + 64) + 64]);     \
     DECL_CHECK_FUNC(*checkasm_check_impl_##name##_type, type)                            \
         = checkasm_check_impl_##type;                                                    \
-    CHECKASM_ALIGN(type name##_buf[((h) + 32) * (CHECKASM_ROUND(w, 64) + 64) + 64]);     \
     const int name##_buf_w = CHECKASM_ROUND(w, 64) + 64;                                 \
     const int name##_buf_h = (h) + 32;                                                   \
     ptrdiff_t name##_stride = sizeof(type) * name##_buf_w;                               \
diff --git a/src/perf/linux.c b/src/perf/linux.c
index 70c972cc80..de1f686e78 100644
--- a/src/perf/linux.c
+++ b/src/perf/linux.c
@@ -28,11 +28,13 @@

 #include "checkasm_config.h"

-#if HAVE_LINUX_PERF
+#ifndef _GNU_SOURCE
+  #define _GNU_SOURCE
+#endif

-  #ifndef _GNU_SOURCE
-    #define _GNU_SOURCE
-  #endif
+#include "internal.h"
+
+#if HAVE_LINUX_PERF

   #include <linux/perf_event.h>
   #include <sys/ioctl.h>
@@ -43,8 +45,6 @@
     #include <pthread.h>
   #endif

-  #include "internal.h"
-
 static int perf_sysfd = -1;

 /* The pinned CPU index, or -1 unless the thread is pinned to one CPU */
diff --git a/src/perf/macos_kperf.c b/src/perf/macos_kperf.c
index 93f845f918..02665259a1 100644
--- a/src/perf/macos_kperf.c
+++ b/src/perf/macos_kperf.c
@@ -28,14 +28,13 @@

 #include "checkasm_config.h"

+#include "internal.h"
 #include "perf_internal.h"

 #if HAVE_MACOS_KPERF

   #include <dlfcn.h>

-  #include "internal.h"
-
   #define CFGWORD_EL0A64EN_MASK       (0x20000)
   #define CPMU_CORE_CYCLE             0x02
   #define KPC_CLASS_FIXED_MASK        (1 << 0)
diff --git a/src/riscv/cpu.c b/src/riscv/cpu.c
index 4f3121086c..64e903e592 100644
--- a/src/riscv/cpu.c
+++ b/src/riscv/cpu.c
@@ -27,14 +27,15 @@

 #include "checkasm_config.h"

-#if ARCH_RISCV
+#ifndef _GNU_SOURCE
+  #define _GNU_SOURCE
+#endif

-  #ifndef _GNU_SOURCE
-    #define _GNU_SOURCE
-  #endif
+#include "internal.h"
+
+#if ARCH_RISCV

   #include "cpu.h"
-  #include "internal.h"

   #include <inttypes.h>
   #include <limits.h>
diff --git a/src/utils.c b/src/utils.c
index 03c2e71186..7c51383d1a 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -468,6 +468,27 @@ DEF_CHECKASM_INIT_MASK(16, uint16_t)
 static int use_printf_color[2];
 static char statusline[256];
 static int statusline_visible;
+static int get_terminal_width(void);
+
+static void statusline_clear(void)
+{
+    if (!statusline_visible)
+        return;
+    fprintf(stderr, "\r\033[K"); /* clear line */
+    statusline_visible = 0;
+}
+
+static void statusline_show(void)
+{
+    if (!statusline[0])
+        return;
+    const int term_w = get_terminal_width();
+    int len = (int) strlen(statusline);
+    if (term_w && len > term_w)
+        len = term_w;
+    fprintf(stderr, "%.*s", len, statusline);
+    statusline_visible = 1;
+}

 /* Print colored text to stderr if the terminal supports it */
 int checkasm_vfprintf(FILE *const f, const int color, const char *const fmt, va_list arg)
@@ -477,10 +498,8 @@ int checkasm_vfprintf(FILE *const f, const int color, const char *const fmt, va_
     if (!use_color || !fmt_len)
         return vfprintf(f, fmt, arg);

-    if (f == stderr && statusline_visible) {
-        fprintf(f, "\r\033[K"); /* clear line */
-        statusline_visible = 0;
-    }
+    if (f == stderr)
+        statusline_clear();

     if (color >= 0)
         fprintf(f, "\x1b[0;%dm", color);
@@ -490,10 +509,8 @@ int checkasm_vfprintf(FILE *const f, const int color, const char *const fmt, va_
     if (color >= 0)
         fprintf(f, "\x1b[0m");

-    if (f == stderr && statusline[0] && fmt[fmt_len - 1] == '\n') {
-        fprintf(f, "%s", statusline);
-        statusline_visible = 1;
-    }
+    if (f == stderr && fmt[fmt_len - 1] == '\n')
+        statusline_show();

     return ret;
 }
@@ -508,15 +525,9 @@ void checkasm_statusline(const char *status)

     snprintf(statusline, sizeof(statusline), "%s", status);

-    if (statusline_visible) {
-        fprintf(stderr, "\r\033[K");
-        statusline_visible = 0;
-    }
-
-    if (statusline[0]) {
-        fprintf(stderr, "%s", statusline);
-        statusline_visible = 1;
-    }
+    /* refresh statusline */
+    statusline_clear();
+    statusline_show();
 }

 static COLD int should_use_color(FILE *const f)
@@ -564,7 +575,7 @@ static int get_terminal_width(void)
     if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
         return w.ws_col;
 #endif
-    return 80;
+    return 0;
 }

 void checkasm_json(CheckasmJson *json, const char *key, const char *const fmt, ...)
@@ -799,7 +810,8 @@ static int check_err(const char *const file, const int line, const char *const n
 #define DEF_CHECKASM_CHECK_BODY(compare, type, fmt, fmtw)                                \
     do {                                                                                 \
         const int overhead   = 5 + 3 + 3;                                                \
-        const int term_width = get_terminal_width() - overhead;                          \
+        const int term_w_raw = get_terminal_width();                                     \
+        const int term_width = (term_w_raw ? term_w_raw : 80) - overhead;                \
         const int aligned_w  = (w + align_w - 1) & ~(align_w - 1);                       \
         stride1 /= sizeof(type);                                                         \
         stride2 /= sizeof(type);                                                         \
diff --git a/tests/generic.c b/tests/generic.c
index 407a288c0d..a8ed85a028 100644
--- a/tests/generic.c
+++ b/tests/generic.c
@@ -38,7 +38,11 @@ void selftest_test_copy(copy_func fun, const char *name, const int min_width)
 {
 #define WIDTH 256
     BUF_RECT(uint8_t, c_dst, WIDTH, 1);
-    BUF_RECT(uint8_t, a_dst, WIDTH, 1);
+    static BUF_RECT(uint8_t, a_dst, WIDTH, 1);
+
+    /* Only compiles if a_dst_buf has static storage duration */
+    static const uint8_t *const a_dst_static = a_dst_buf;
+    (void) a_dst_static;

     CHECKASM_ALIGN(uint8_t src[WIDTH]);
     INITIALIZE_BUF(src);