← board

C: 2D array struct field — partial-index row decay broken

Symptom

A single index into a 2-D array struct field returns the element value at [i][0] instead of the row address (&field[i][0], i.e. C array decay to a pointer). Crashes / corrupts as soon as the "row" is indexed again.

Minimal repro:

struct G { char* cache[4][2]; };
static struct G g;
int main(void){
  g.cache[1][0] = "hello";
  char** p = g.cache[1];   /* p SHOULD be &g.cache[1][0] */
  /* actual: p == g.cache[1][0]  (the stored char*, not the row addr) */
  char* q = p[0];          /* then deref-garbage -> SIGSEGV */
  return 0;
}

Instrumented: P = value of cache[1][0], not the row address; p[0] then reads 4 bytes (movslq) from inside the "hello" string.

This is the live blocker for a printing lua: lua_State's TString *strcache[STRCACHE_N][STRCACHE_M] is read row-wise in luaS_new (TString **p = G(L)->strcache[i]; ... p[j]). After the round-18 fixes (array field decay, array-init materialization, *const) lua runs through string interning + luaT_init; this is the next crash (in luaS_new).

What works / what doesn't

Cause

  1. The C struct-field parse (cparser.inc ~3099) flattens [N][M] into a single arrLen = N*M and never records UFldArrNDims / per-dim spans (stays 0). So the frontend cannot tell a 2-D field from a 1-D one.
  2. The C indexer (ParseCPostfix, cparser.inc ~711) builds one AN_INDEX per subscript and tags it CNodePointeeTk(base) — for a multidim field a single subscript should yield a row pointer (&field + i*innerSpan*elem, typed pointer-to-element), not a loaded element.

Fix sketch (multi-session — do NOT half-land; self-host gate risk)