← board

A struct field's partial index uses the outer row stride, and stamps no stride at all

Measured (gcc oracle, tools/gcc_diff_probe.sh)

struct S2 { int m[3][4]; } s;          /* filled m[i][j] = 10*i + j */
struct S3 { int m[2][3][4]; } t;       /* filled 100*i + 10*j + k   */
expression gcc pxx (before)
*(s.m[1] + 1) 11 184549376 (= 11 shl 24)
*(s.m[2] + 3) 23 5376
int *q = t.m[1][2]; q[0] 120 -2121552008
q[3] 123 32767

The last row is the loud one: the address had left the object entirely. The same four expressions written against a bare int m[3][4] / int m[2][3][4] were correct throughout — which is what says these are defects and not a dialect choice.

Two causes, both in the struct-field arm of ParseCPostfixTail

The array arm and the field arm build the same thing — &base + flat*stride over a base retagged tyInt64 — from two separate blocks. Each defect is the field arm missing something the array arm does.

  1. No ASTSLen stamp on the add node. Retagging the base tyInt64 is what makes the add a raw byte add, and it is also what blinds IRPointerStride: neither operand is a pointer any more, so it falls to its size-1 default and the decayed row steps one byte. The builder is the only place that still knows the row's stride, so it must stamp it. [[bug-c-a-multidim-array-decays-with-the-element-stride]] found exactly this and fixed the ARRAY arm; the field arm was the sibling nobody grepped for. (normalise-dont-special-case.md: "if you fix a bug on one arm of a double case, grep for the sibling before closing the ticket." Eight months later, here it is.)

  2. RecFieldRowStride is the OUTER row, used at every depth. That helper answers for ONE subscript — elem * product(span[1..n-1]). With ndi subscripts consumed the multiplier is the product of the remaining spans, which is what the array arm computes for itself. On int m[2][3][4], t.m[1][2] therefore multiplied by 48 where 16 was right.

Fix

Both in the struct-field partial-index arm, compiler/cparser.inc:

Gate — and what it proved about coverage

Log