← board

High(TGap) counts the members instead of reading their values

Repro

type
  TGap = (gX = 3, gY = 4, gZ = 9);
  TCol = (cRed, cGreen = 5, cBlue, cGold = 20);
FPC 3.2.2 pxx (before)
Ord(Low(TGap)) 3 0
Ord(High(TGap)) 9 2
Ord(High(TCol)) 20 3
for g := Low(TGap) to High(TGap) 3,4,5,6,7,8,9 0,1,2

Ord(gX), Ord(cGold) etc. were already right — only the type's bounds were wrong. So the enum's own values check out and only the loop that walks them is broken, which is why this survived: nothing in the corpus iterates an enum whose members carry explicit ordinals.

Root cause

0 .. EnumTypeValCount[etid] - 1 was written out longhand at four sites as the stand-in for "the ordinal range of this enum type":

site what it bounds
TryConstHighLowValue (parser.inc) Low/High in a constant expression
TryFoldHighLowType (parser.inc) Low/High in an expression
BuildForInSetLoop (parser.inc) the for x in <set of enum> membership scan
the array-index-type bound (parser.inc) array[TEnum] of …

That shorthand is exact for a plain (a, b, c) and wrong for every enum with an explicit = N. EnumTypeHasHoles already existed and already recorded that the declaration broke contiguity — it was consulted only to refuse for x in TEnum, never to correct a bound.

Fix

One accessor, EnumTypeOrdRange(etid, var lo, hi) in symtab.inc, scanning EnumValOrd over the type's member slice; all four sites call it. The change is a no-op for a contiguous enum (min = 0, max = count-1 by construction) and a fix for every other one — so the set scan and the array-index bound are corrected by the same edit that fixes Low/High, rather than each growing its own patch.

Fallout worth naming: array[TGap] of Integer is now 7 slots indexed from 3, not 3 slots indexed from 0. FPC refuses that declaration outright; pxx accepts it and now sizes it the only way that can work, since ag[gZ] was previously an out-of-bounds write six elements past the array.

Test

test/test_enum_explicit_ordinal_low_high.pas — 24 assertions: the contiguous enum (unchanged, so a regression is caught), the all-explicit one, the mid-declaration gap, set of a holed enum (in, Include, Exclude, for-in), and array[TGap]. Every expectation is FPC 3.2.2's except array[TGap], which FPC will not compile.

Gate

make compiler/pascal26 fixedpoint + tools/gate.sh quick.

Log