Repro
program r;
type TE = (a, b, c);
const K = TE(2);
begin WriteLn(Ord(K)); end.
| compiler | result |
|---|---|
| fpc 3.2.2 | compiles; prints 2 |
pxx @ efe06a903 |
pascal26:3: error: not a constant |
What is and is not the cause, isolated
The shape was found on an enum with explicitly assigned range bounds, which is the interesting-looking part and is a red herring. Varied one axis at a time:
| form | pxx |
|---|---|
const K = TE(2), TE = (a, b, c) |
refused |
const K = TRegister($ffffffff), explicit Low(longint)/High(longint) bounds |
refused |
const K = SomeIntAlias($ffffffff) |
accepted |
const K = High(SomeOrdinalType) |
accepted |
So it is the enum target, not the range, not the literal's width, and not casting-in-a-const generally.
Where it was found
cgbase.pas:401 in the FPC compiler corpus:
TRegister = (
TRegisterLowEnum := Low(longint),
TRegisterHighEnum := High(longint)
);
...
NR_INVALID = tregister($ffffffff);
FPC's own comment says the enum spelling is deliberate — "TRegister is defined as an enum to make it incompatible with TSuperRegister to avoid mixing them" — so this is idiomatic source someone meant to write, not an edge case.
It became the first failure of those 14 units only on 2026-09-17, when
efe06a903 accepted constructor/destructor on an old-style object and let
the parse get 25 lines further down the same file. The in: line is what
identifies it: the diagnostic's first line carries no file name, and reading the
line number against the subject unit gives the wrong file every time.
Log
- 2026-09-17 — resolved; this names the commit that carried the resolve, which is not always the one that carried the change — commit fc482e82e.