Search code examples
delphidelphi-xe5win64

How to adjust the code made for WINx86 to compile for WINx64


I was using assignment of Component Tag (NativeInt) value adding it to the set of bytes. The program worked properly when compiled for WIN32 but doesn't compile for WINx64. (Error 2001 Ordinal type required) Here is an MCVE:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Classes;
  var 
  S:set of byte;
  C:TComponent;

begin
   C:=TComponent.Create(nil);
   C.Tag:=1;
   s:=[C.Tag];
   C.Free;
 end.

How can I adjust the code to make it suitable for WINx64 compilation?


Solution

  • Tag is NativeInt. That is 32 bits in x86, and 64 bits in x64. As I understand it, a 32 bit integer is deemed to be an ordinal, and a 64 bit integer is not an ordinal. That is the reason for the compiler error, I think, although quite why Integer is deemed to be an ordinal type, and Int64 is not, I cannot tell you. If I had to guess, I would imagine that this is related to the fact that Int64 does not fit into a register on x86, and so requires quite different treatment from the compiler in comparison to 1, 2 and 4 byte ordinal types.

    Since you probably don't want something that changes size, I expect you are fine to cast to Integer:

    s := [Integer(C.Tag)];
    

    And since you are only using the low 8 bits anyway, you should probably cast it to Byte:

    s := [Byte(C.Tag)];
    

    Preferably with an assertion that you are in range:

    Assert((C.Tag >= low(Byte)) and (C.Tag <= high(Byte)))
    

    Frankly though, you are, in my view, better avoiding Tag altogether. Store your data in a variable dedicated to the task, with a type that you can choose. As a general rule, in my view, Tag is something that you should avoid using. It's not type safe unless you happen to have a NatoiveInt to store, its name gives no indication of its contents, and it's all to easy to have collisions when multiple parties attempt to use it.