Can call Inc on a property - when property is structure, increment doesn't happen
Original Reporter info from Mantis: ahydra
-
Reporter name: Colin Haywood
Original Reporter info from Mantis: ahydra
- Reporter name: Colin Haywood
Description:
See program below. When I tried with the array being of integer rather than record type, the code worked fine. However with records the Inc(...) line has no effect.
This problem affects both generics and regular classes.
I tried two alternative formulations of the Inc(...) lines:
a.TopEntry.x := a.TopEntry.x + 1; // Compiler error: Argument can't be assigned to
a.TopEntry.x += 1; // compiles but gives same result as Inc(...)
Steps to reproduce:
program project1;
{$mode objfpc}{$H+}
uses
sysutils, Classes;
type
generic TBroken<_T> = class
type private
T_TArray = array of _T;
var private
FArray: T_TArray;
private
function FGetTopEntry(): _T;
procedure FSetTopEntry(Value: _T);
public
constructor Create(Len: integer);
property TopEntry: _T read FGetTopEntry write FSetTopEntry;
end;
TRecord = record
x, y, z: integer;
end;
TMaybeBroken = class
private
FArray: array of TRecord;
function FGetTopEntry(): TRecord;
procedure FSetTopEntry(Value: TRecord);
public
constructor Create(Len: integer);
property TopEntry: TRecord read FGetTopEntry write FSetTopEntry;
end;
TBrokenRecord = specialize TBroken&LtPos;TRecord>; // pun intended
var
a: TBrokenRecord;
b: TMaybeBroken;
i: integer;
constructor TBroken.Create(Len: integer);
var
i: integer;
begin
SetLength(FArray, Len);
FillChar(FArray[0], SizeOf(_T) * Len, 0);
end;
function TBroken.FGetTopEntry(): _T;
begin
Result := FArray[High(FArray)];
end;
procedure TBroken.FSetTopEntry(Value: _T);
begin
FArray[High(FArray)] := Value;
end;
constructor TMaybeBroken.Create(Len: integer);
var
i: integer;
begin
SetLength(FArray, Len);
FillChar(FArray[0], SizeOf(TRecord) * Len, 0);
end;
function TMaybeBroken.FGetTopEntry(): TRecord;
begin
Result := FArray[High(FArray)];
end;
procedure TMaybeBroken.FSetTopEntry(Value: TRecord);
begin
FArray[High(FArray)] := Value;
end;
begin
a := TBrokenRecord.Create(10);
Inc(a.TopEntry.x);
for i := 0 to 9 do writeln(inttostr(a.FArray[i].x));
a.Free();
writeln('---');
b := TMaybeBroken.Create(10);
Inc(b.TopEntry.x);
for i := 0 to 9 do writeln(inttostr(b.FArray[i].x));
b.Free();
Readln();
end.
Additional information:
Here's the ASM (from the attached compiler output) which shows GetTopEntry being called and the increment being made but the value is never stored.
leal -52(%ebp),%edx
movl U_P$PROJECT1_A,%eax
call PPROJECT1_TBROKEN
TRECORD___FGETTOPENTRY
$TRECORD
incl -52(%ebp)
Mantis conversion info:
- Mantis ID: 20095
- OS: Windows
- OS Build: XP Home 32bit
- Platform: x86
- Version: 2.4.2
- Fixed in version: 2.6.1
- Fixed in revision: 20427 (#75aac428)