Compiler throws no error on writing to individual record fields via a setter
Original Reporter info from Mantis: Nitorami
-
Reporter name:
Original Reporter info from Mantis: Nitorami
- Reporter name:
Description:
The code below defines a 2D Matrix of complex numbers. The elements are stored in linear array "data", and can be accessed via getters/setters. The setter expects type complex, it is not possible to make an assignment to the real or imaginary part only, and the compiler throws an error "Argument cannot be assigned to".
However when writing to an element within a "with" construct, the compiler accepts this, although the write process will fail.
I do not know if this is a bug, or if it can be fixed easily. I just find it pretty dangerous, and fell for it a couple of times.
{$mode objfpc}
{$modeswitch advancedrecords}
type complex = record re,im: double; end;
type TMatrix = record
strict private
sizex, sizey: longint;
function GetItem (const x,y: longint): complex;
procedure PutItem (const x,y: longint; a: complex);
property Item [const x,y:longint]: complex read GetItem write PutItem; default;
procedure SetSize (const x,y: longint);
private
Data: array of complex;
public
property dimx: longint read sizex;
property dimy: longint read sizey;
procedure init (const x,y: longint);
procedure print;
end;
function TMatrix.GetItem (const x,y: longint): complex;
begin
result := Data[x*sizey+y];
end;
procedure TMatrix.PutItem (const x,y: longint; a: complex);
begin
Data[x*sizey+y] := a;
end;
procedure TMatrix.SetSize (const x,y: longint);
begin
SetLength (Data,x*y);
sizex := x; sizey := y;
end;
procedure TMatrix.init (const x,y: longint);
begin
Data := nil;
SetSize (x,y);
end;
procedure TMatrix.print;
var x,y: longint;
begin
for y := 0 to dimy-1 do begin
for x := 0 to dimx-1 do write (self[x,y].re:6:2,'',self[x,y].im:6:2,'j ');
writeln;
end;
writeln;
end;
var A: TMatrix;
i: longint;
begin
A.Init (1,1);
// Direct array access works
with A.data[0] do begin
re := 5;
im := -5;
end;
A.print;
A.Init (1,1);
// Access via setter fails - assignments to A are ignored without a warning
with A[0,0] do begin
re := 5;
im := -5;
end;
A.print;
// THIS of course causes a compiler error
// A[0,0].re := 4;
end.
Steps to reproduce:
Just compile and run the attached code.
Does not matter whether 32- or 64-bit compiler version.
Mantis conversion info:
- Mantis ID: 36029
- OS: windows10
- Platform: PC
- Version: 3.0.4