[fpc-devel] Dangerous optimization in CASE..OF
Martok
listbox at martoks-place.de
Tue Jul 18 15:26:20 CEST 2017
>> And then there's bitpacked records...
>
> Indeed, and range checking. I mean, if you have the above declarations,
> then what should be the behaviour in the following cases:
Delphi generates no range checking code for enum assignments at all, only for
mutation. All your examples work without error, just maybe not in a way you'd want.
I think this is a bug, not any assumption - they do check the range in things
like conditional expressions, just not in proper rangechecks.
> 1)
>
> {$r+}
> var
> a,b: TEnum;
> begin
> a:=tenum(5);
> b:=a;
> end;
Aliasing should not count as an operation, so no rangecheck code inserted at all.
> 2)
>
> {$r+}
> type
> tr = bitpacked record
> f: TEnum;
> end;
> var
> a: tenum;
> r: tr;
> begin
> a:=tenum(5);
> t.f:=a;
> end;
By transition same as 1, but we should get an integer overflow error because
bitsizeof(r.f) < bitsizeof(a).
In my latest proposal it would matter if TEnum has explicit values or not. If it
has, f would be large enough; if not, there should be an overflow check because
two variables of the same type may suddenly not have the same size.
> (which means that in case 2, enums cannot actually be bitpacked)?
I think only automatic enums can be. IMO:
{$Z1}
bitpacked record
f: (a,b,c,d);
end; => OK, bitsize 2
bitpacked record
f: (a=6,b,c,d); => either error (like use as array index in mode FPC)
end; => or OK, bitsize 8 (because of base type)
TEnum = (a=6,b,c,d); => on its own, bitsize 8
bitpacked record
f: a..d;
end; => OK, bitsize 4 (values up to d=9)
That would be consistent with
a) how sets of enums are packed
b) how a subrange over Integer is bitpacked smaller than Integer.
That is, however, again an occasion where the only real use of the subrange is
in its declarative use.
> 3)
>
> (does this trigger a range check error in Delphi?)
>
> {$r+}
> var
> arr: array[tenum] of byte;;
> a: tenum;
> begin
> a:=tenum(5);
> arr[a]:=1;
> end;
Again, no RC code in Delphi, which would be valid only for auto enums.
Bonus:
4)
{$r+}
type
tenum = (a,b=3,c);
ta = array[tenum] of byte;
var
arr: ta;
v: tenum;
begin
for v := low(arr) to high(arr) do begin
arr[v]:=1;
end;
end.
Still no RC code, but now we can be wrong on both sides. Also the loop happily
iterates over the invalid values 1 and 2.
5)
{$r+}
var
a: TEnum;
b: TSubEnum;
begin
a:=tenum(5);
b:=a;
end;
That should include RC code, and be an error. Indeed that is what FPC currently
generates, Delphi gets it wrong again. Part of the reason why I think this is a
bug on their part.
Martok
More information about the fpc-devel
mailing list