[fpc-devel] Gaps in a non-contiguous enum

Juha Manninen juha.manninen62 at gmail.com
Thu Aug 11 13:38:06 CEST 2022


I was able to fix issue
 https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/39832
about TEnumPropertyEditor in Lazarus IdeIntf.
Explanation:
function GetEnumName() in FPC's rtl/objpas/typinfo.pp returns the enum's
unit name for one gap in a non-contiguous enum, and an empty string for the
other gaps. IMO returning the unit name can be considered a bug in FPC code.
Fortunately TPropertyEditor has a method GetPropTypeUnitName(), made by
Mattias I guess, which I could use to filter out the unit name. An enum
element cannot have the same name as the unit which makes this a robust
solution.
This is the fixed property editor method:

procedure TEnumPropertyEditor.GetValues(Proc: TGetStrProc);
var
  I: Integer;
  EnumType: PTypeInfo;
  s, EnumUnitName: String;
begin
  EnumType := GetPropType;
  EnumUnitName := GetPropTypeUnitName;
  with GetTypeData(EnumType)^ do
    for I := MinValue to MaxValue do begin
      s := GetEnumName(EnumType, I);
      // An empty string and the enum's unit name happen in gaps
      // of a non-contiguous enum. Why the unit name? A bug in FPC code?
      if (s <> '') and (s <> EnumUnitName) then
        Proc(s);
    end;
end;

Property editors deal with RTTI.
I started to think about how such enum elements are iterated in a normal
user code which doesn't need RTTI.
I came up with this, using the Fruit example enum from the bug report:

program enumconsole;
type
  //TFruit = (fApple, fOrange, fBanana, fGrapes, fPear);
  TFruitMore = (fmApple=0, fmOrange=2, fmBanana=4, fmGrapes, fmPear);
const
  CFruitMoreSet = [fmApple, fmOrange, fmBanana, fmGrapes, fmPear];
var
  e: TFruitMore;
begin
  for e := Low(TFruitMore) to High(TFruitMore) do
    if e in CFruitMoreSet then
      WriteLn(Ord(e), ': ', e);
end.

It seems there is no easy way, or at least I didn't find any.
The code requires a constant set with all enum elements included. Feels
like a hack.
Leaving out the test "if e in CFruitMoreSet then" leads to a run time error.
If there is a better way to iterate, please tell me.

Regards,
Juha
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20220811/923c7fc7/attachment.htm>


More information about the fpc-devel mailing list