[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