[fpc-devel] Use of Enumerations in header translations

Martok listbox at martoks-place.de
Sun Aug 13 14:54:30 CEST 2017


Hi all,

so, some time ago, Jonas asked this:

> I don't know, but I still don't understand why on Earth you would want
> them [binary-compatible C-style enums] in a strongly typed language.
To which my reply was: header translations!

I've spent some time on Saturday with ppudump and jq to find out what
enumerations with offsets are used for in the FPC tree itself. (Mainly because I
wanted to know what in your opinion the intended and correct application is - I
still *really* want to fix that and get back to it every couple of days.)

The results are interesting: use in packages is exclusively header translations
and on-disk file formats.
Use in the compiler itself is widespread too: the TRegister range type is an
enum where the whole point is that it can contain any value of the base type.
tmsgstate is an enum (with jumps). Binary constants for DWARF are enums.
tinlinenumber is an enum.

All of which I have been told in no uncertain terms are not intended to be safe
and should just not be done.

Many people clearly thought otherwise at some point.

A really good and short header example of the clean and very Pascal-y code
possible by translating enums as enums is the NVAPI header. One instance of our
original issue I could quickly Google up is something like this:
------------------------------------------
var bt: NV_GPU_BUS_TYPE;
NvAPI_GPU_GetBusType(hPhysicalGPU, bt);
case bt of
  NVAPI_GPU_BUS_TYPE_UNDEFINED   : WriteLn('Driver doesn''t know hardware!');
  NVAPI_GPU_BUS_TYPE_PCI         : WriteLn('You have a PCI card!');
  NVAPI_GPU_BUS_TYPE_AGP         : WriteLn('You have an AGP card!');
  NVAPI_GPU_BUS_TYPE_PCI_EXPRESS : WriteLn('You have a PCIe card!');
  NVAPI_GPU_BUS_TYPE_FPCI        : WriteLn('You have an FPCI card!');
else
  WriteLn('You have some future interface!');
end;
------------------------------------------
Looks perfectly sane, right?
NV have in the meantime extended the upstream C enum to include
NVAPI_GPU_BUS_TYPE_AXI = 5. We have an else statement to catch that, but the
compiler may choose to not even generate code for it. This is bad.

Of course, AndiH wrote that header first for Delphi, where it is reliably safe...


Why am I posting this? Well, if it is really your intention that enums are only
safe to read if all writes happen in Pascal code without casts, then all of
those imports are plain and simple wrong, and must be changed. If enumerated
types can only formally contain the values explicitly named, then the entire
codegen is undefined.
Or we could just agree that C-style enums must be treated as low-level, which
some committers obviously assumed anyway.


Affected packages visible from win32 target:
==========================
compiler itself (see type names above)
rtl             (windows.pp)

cairo
fcl-db
fcl-sdo
fcl-xml
fftw            (very minor)
gtk1            (with more affected
gtk2             code in the LCL)
httpd22
httpd24
libcurl
libenet
libusb
libvlc
libxml2
mad
mysql
nvapi
oracle
winunits-base
winunits-jedi
zorba


--
Martok





More information about the fpc-devel mailing list