Wrong pointer arithmetics in conjunction with constant folding
Very serious and important bug!
Pointer arithmetics behaves wrong when doing several additions in a row, regardless of the base type. (Subtractions are mysteriously fine.)
See this program:
{$mode objfpc} {$h+} {$typedaddress on}
type
pBaseType = ^BaseType;
BaseType = uint32; // can be replaced with an arbitrary-sized array or record
procedure Check(pstart, px: pBaseType; refIx: SizeInt; const desc: string);
var
ix: SizeInt;
begin
ix := px - pstart;
writeln(desc, ' points at element #', ix);
if ix = refIx then
writeln('ok')
else
writeln('WRONG, must be #', refIx);
writeln;
end;
var
x: array[0 .. 19] of BaseType;
p: pBaseType;
begin
p := pBaseType(x);
Check(p, p + 2, 2, 'p + 2');
Check(p, p + 2 + 3, 5, 'p + 2 + 3');
Check(p, p + 2 + 3 + 5, 10, 'p + 2 + 3 + 5');
// These casts don't help.
Check(p, pBaseType(pBaseType(p + 2) + 3) + 5, 10, 'pBaseType(pBaseType(p + 2) + 3) + 5');
// These work, but prevent constant folding.
Check(p, pBaseType(pointer(pBaseType(pointer(p + 2)) + 3)) + 5, 10, 'pBaseType(pointer(pBaseType(pointer(p + 2)) + 3)) + 5');
Check(p, p + (2 + 3 + 5), 10, 'p + (2 + 3 + 5)');
Check(p, p + 2 + 3 + 5 + 7, 17, 'p + 2 + 3 + 5 + 7');
end.
and its output:
p + 2 points at element #2
ok
p + 2 + 3 points at element #20
WRONG, must be #5
p + 2 + 3 + 5 points at element #100
WRONG, must be #10
pUint32(pUint32(p + 2) + 3) + 5 points at element #100
WRONG, must be #10
pUint32(pointer(pUint32(pointer(p + 2)) + 3)) + 5 points at element #10
ok
p + (2 + 3 + 5) points at element #10
ok
p + 2 + 3 + 5 + 7 points at element #428
WRONG, must be #17
Edited by Rika