From 8fbc2e82c308dd6b2f3e9e23766c1e91d5e3c6fe Mon Sep 17 00:00:00 2001 From: jedarden Date: Fri, 3 Jul 2026 12:42:09 -0400 Subject: [PATCH] test: document setjmp volatile-analysis in firmware host harness loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a comment next to the per-test setjmp(g_test_jmp) guard in main()'s loop recording the C11 7.13.2.1 volatile analysis: the loop index i is read in the post-longjmp path (g_tests[i].name) but is not modified between the setjmp() call and a possible longjmp() — the body only reads i, and the only write is the for-loop increment, which runs after control returns. So no volatile qualifier is needed. (bf-2ftl) Co-Authored-By: Claude Bead-Id: bf-2ftl --- firmware/test/test_runner.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/firmware/test/test_runner.c b/firmware/test/test_runner.c index e5cd7f9..7fad69c 100644 --- a/firmware/test/test_runner.c +++ b/firmware/test/test_runner.c @@ -234,6 +234,25 @@ int main(void) int failed = 0; for (int i = 0; i < g_test_count; i++) { + /* + * Per-test recovery guard. setjmp() establishes the longjmp() target + * that test_record_failure() jumps into on a failed assertion. On the + * direct call setjmp() returns 0 and the body runs as before; on a + * longjmp() return it yields non-zero and we take the else branch — + * the body is NOT re-invoked, the loop just falls through to the next + * i. That is the whole point: a failure in test N never blocks N+1. + * + * volatile analysis (C11 7.13.2.1): an automatic variable modified + * between setjmp() and longjmp() AND read after the longjmp returns + * has indeterminate value unless it is volatile-qualified. The loop + * index i IS read in the post-longjmp path (g_tests[i].name in the + * else branch), so the question is whether i is modified between the + * setjmp() call and a possible longjmp(). It is not: between them the + * body only READS i (g_tests[i].fn()), and the only write to i is the + * for-loop increment, which runs AFTER control returns here (whether + * via a normal body return or the longjmp). So no volatile is needed + * on i — confirmed safe. + */ if (setjmp(g_test_jmp) == 0) { g_tests[i].fn(); printf("PASS: %s\n", g_tests[i].name);