← board

Measured, 2026-08-25

type TRec = record a, b: Integer; end;  PRec = ^TRec;
var p: PRec;
begin
  p := New(PRec);        { fpc: ok — pxx: undefined variable (New) }
  p^.a := 3; p^.b := 4;
  Dispose(p);
end.

The statement form New(p) worked and always has. Only the value-returning spelling was missing, and it is missing for a structural reason worth recording: the intrinsic lived only in the statement parser, so no expression position could reach it.

Fix (landed 2026-08-25)

An arm in ParseFactorCore (compiler/pasparser_expr.inc) with the same lowering the statement arm uses — GetMem(SizeOf(pointee)) — reading the size off the ALIAS row instead of off a variable's symbol, which is the only real difference between the two spellings. Guarded so it can fire on nothing else: no user New proc or variable in scope, a ( must follow, and the argument must be an identifier naming a POINTER type alias (so New(p) over a variable stays the statement form and never reaches here).

Regression test test/test_new_as_a_function_over_a_pointer_type.pas asserts both spellings over both a record and a scalar pointee, so the two arms cannot drift on the size rule; .expected from fpc 3.2.2.

Where it was found

[[feature-pascal-corpus-generics]] — Result := New(PSpoofInterfacedTypeSizeObject) in TComparerService.CreateInterface, Generics.Defaults line 2074.

Log