← board

C static local with an initializer re-runs the initializer every call

Repro

#include <stdio.h>

int counter(void) {
    static int n = 10;
    n = n + 1;
    return n;
}

int main(void) {
    printf("%d\n", counter());
    printf("%d\n", counter());
    printf("%d\n", counter());
    return 0;
}

Expected (and what real C / this project's own x86-64 output should be):

11
12
13

Actual:

11
11
11

Without an explicit initializer (static int n;, relying on implicit zero-init) the same pattern works correctly — n = n + 1 across 3 calls correctly prints 1 2 3. So the storage itself does persist (BSS, per the cparser.inc:2826 comment about pointer survival for sqlite's static vfs table) — only the explicit initializer is the problem: static int n = 10; is being lowered as an assignment statement that runs on every function entry, not a one-time load-time initializer.

Why it matters

static locals with initializers are an extremely ordinary, common C pattern (counters, lazily-initialized caches, "have I warned about this once" flags, static const lookup tables assigned via a runtime expression). Currently any state seeded through a static-local initializer is silently reset to its initial value on every call — this is a silent-wrong-behavior bug, not a compile error, so it will not be caught by "does it compile" checks; it needs an actual runtime comparison to notice (as this probe did).

Suggested investigation

CLocalStaticDecl (cparser.inc:2826) routes through the normal ParseCLocalDeclAST path with the flag set to move storage to BSS/global, but the initializer expression is still emitted inline in the function body (as for a normal auto local) instead of being hoisted to a load-time/global initializer that runs exactly once. Fix likely needs the static-local's initializer to be treated the same way a global variable's initializer is (one-time, at program start), gated so it doesn't re-run per call — while still allowing the non-initialized case (implicit zero, which already works) to fall through unchanged.

Acceptance

Log