← board

C: p[i] / p+i on a struct pointer uses the wrong element stride

Symptom (minimal, no lua headers)

struct V { int val; };
int main(void){
  struct V a[3];
  a[2].val = 42;
  struct V *p = a;
  return p[2].val;          /* gcc 42, pxx 0 */
}

a[2].val direct = 42 (correct). p[0].val = 42 (correct). But p[2].val reads 0. (char*)&a[2] - (char*)&p[2] = 8 (should be 0): p[2] is addressed with stride 8 (pointer size) instead of sizeof(struct V) = 4. So indexing a struct pointer beyond element 0 lands on the wrong object — a SILENT miscompile (no error), already present in the committed compiler. Pervasive in lua/sqlite (every stack[i].field / p[i].field).

Where to look

ir.inc ~604–619 (pointer indexing p[i]): it already intends if PtrElemTk = tyRecord then elemSize := RecSize(PtrElemRec) else TypeSize(PtrElemTk). The observed stride 8 means the tyRecord branch is NOT taken for struct V *p — i.e. the symbol's PtrElemTk/PtrElemRec is not tyRecord/the struct (so it falls to TypeSize = pointer size 8), OR the p = a array-decay assignment clobbers p's element metadata. First check Syms[p].PtrElemTk/PtrElemRec right after struct V *p is declared and again after p = a. (RecSize(V) is correct — sizeof(struct V) returns 4.) Fix so the struct element size is used; then p[i].field, (p+i)->field, and the bug-c-field-on-pointer-arithmetic Unsupported all resolve.

Note

This is the ROOT of bug-c-field-on-pointer-arithmetic: once pointer arithmetic on a struct pointer scales correctly AND (p+i) keeps its pointer type, both p[i].field and (p+i)->field work. A type-only fix for (p+i)->field (tagging the binop pointer) was tried and reverted because it turned the loud "Unsupported" into a SILENT wrong value via this stride bug — fix the stride first.

Resolution