← board

C: multi-dim array indexed by another multi-dim array read miscompiles

Minimal repros

static int g3[2][3] = {{1,2,3},{4,5,6}};
static int g9[3][1][3] = {{{0,0,0}},{{0,0,0}},{{1,0,0}}};   /* g9[2][0][0]=1 */
int r = g3[1][g9[2][0][0]];          /* want g3[1][1]=5; pxx=0  (RVALUE read) */
g3[g9[0][0][0]][g9[2][0][0]] = 88;   /* want g3[0][1]=88; pxx writes wrong slot */

TWO root causes (both needed for a full fix)

  1. Parse-time NDInfo clobber.* The multi-dim flatten (ParseCPostfixTail, the NodeArrNDInfo(node) branch) uses the SHARED globals NDInfoNDims/NDInfoLo/ NDInfoSpan. Parsing a later subscript that is itself a multi-dim read re-calls NodeArrNDInfo (for the inner array) and CLOBBERS those globals, so the outer array's while (nIdx < NDInfoNDims) bound and BuildFlatNDIndex spans are the INNER array's -> wrong flatten (wrong full-vs-partial decision + wrong strides). DRAFT FIX (reverted): re-call NodeArrNDInfo(node) after each subscript's ParseCExpr to restore the globals. This made 5004/40020 compile AND match gcc, but a hand lvalue test still failed -> bug #2 remains, so the draft was reverted (a partial fix that masks a residual silent miscompile is worse than a loud compile-fail).

  2. Codegen nested-index clobber. Even with a correct flatten AST, AN_INDEX(g3_multidim, index-expr-containing-a-nested-AN_INDEX) reads the wrong element on the RVALUE path (IRLowerAST). A 1-D array with the same nested-index expression (a[3 + g9[2][0][0]]) is CORRECT, and hoisting the inner read to a temp is CORRECT — so it is specific to the multi-dim IR_INDEX codegen: the nested IR_INDEX in the index subtree clobbers a register the outer index/base computation needs. The lvalue path (IRLowerAddress) handles some cases but not all.

Fix plan

Do BOTH: (1) snapshot/restore NDInfo* across subscript parsing (the reverted draft, made robust), AND (2) fix the multi-dim IR_INDEX codegen to save/restore the base (or evaluate the index into a temp) when the index subtree contains a nested IR_INDEX. Verify with a hand rvalue+lvalue matrix AND re-run csmith.

Acceptance

Log