[fpc-devel] [Suggestion] Enumeration range-check intrinsic
Martin Frb
lazarus at mfriebe.de
Sat Jul 13 13:28:38 CEST 2019
On 11/07/2019 15:46, J. Gareth Moreton wrote:
>
> For my personal point of view, I would like these operators to be the
> exception to the rule of the compiler assuming an enum always contains
> a valid value,
As much as I would like to agree with you (and yes I think such a check,
if possible, would be desirable - even if it meant to ignore certain
language design principles), it is indeed not possible.
Maybe it would be today (as in today's fpc implementation), maybe not. I
do not know.
But it would not be future safe.
Lets say "fpc breaks the rule for "is/as" and only for those".
FooEnum := SomeApi();
if not (FooEnum is TFooEnum) then FooEnum := low(TFooEnum);
Now we do *not* know what the optimizer does in the first line. And that
is the problem.
On some platform (that we have no clue of today), the compiler may store
the value bitpacked into a temp var/register. The storage is shared with
other values.
If the result of "SomeApi()" is out of bounds, it might overwrite one of
the other values stored in that var/register.
The "is" can only check the part of the storage actually meant to be
used by the enum. The change to the other value goes unnoticed.
So in such a future case, the is may do what you expect. A later "case
FooEnum" will be ok, as FooEnum is "forced" to be valid.
But your program still crashes, due to the other var being modified
unexpectedly.
Yes that may sound far fetched. But maybe some embedded system, with
scarce resources requires such behaviour?
----------------
Maybe a possible solution would be based on:
On 13/07/2019 12:48, Jonas Maebe wrote:
> In Delphi's type system (and in C, C++, and C#), the valid values for
> an enum are always all values that fit within its storage size, and
> that storage size is fixed.
Create such an enum type in fpc too (as a new type / assignment
compatible with the current enum)
{modeswitch StorageSizeValidEnum}
type TFullFooEnum = (a,b,c);
would treat all values of the (unpacked) storage as valid.
As a consequence:
- it can not be packed / it would keep its full size
- many optimizations can not be applied
But for such a type, that has explicitly been defined as having all the
other values, you could use "is".
Of course not straight forward. Because now 255 is a valid value for
that enum, so "is" would return true. But with:
{modeswitch StorageSizeValidEnum on}
type TFullFooEnum = (a,b,c);
{modeswitch StorageSizeValidEnum off}
type TFooEnum = (a,b,c);
this would work:
if FullFooEnum is TFooEnum then
Since this is only/mainly used for "external" data, the extra type def
would not be to much overhead.
Of course, it is merely syntactical sugar, since it is identical too
type TFullFooEnum = integer; //or whatever represents the storage size
type TFooEnum = (a,b,c);
It only allows to have named values for that "integer"
More information about the fpc-devel
mailing list