Type helpers do not work properly for subrange types

Original Reporter info from Mantis: avra @zeljkoavramovic
  • Reporter name: Zeljko Avramovic

Description:

Writing to a type helper property does not work for subrange types. Attached snippet demonstrates this behavior.

Steps to reproduce:

program subrange-type-helper-test;
 
{$mode delphi} {$H+}
{$modeswitch typehelpers}
 
uses
  cthreads;
 
type
  TNewJ1939PGN = 0..(1 shl 18)-1; // does not work with subrange, but works if type is changed to dword
 
  TNewJ1939CanID = bitpacked record
    SA:       byte;         // if PGN was a record, bit packing would not work and
    PGN:      TNewJ1939PGN; // Priority bits would not be put immediately after PGN bits
    Priority: 0..7;         // since PGN record would then be byte aligned by pascal
  end;                      // and there is no solution for that, so let's try type helpers instead
 
  TNewJ1939PGNHelper = type helper for TNewJ1939PGN
  private
    function  GetPS: byte;
    procedure SetPS(const ANewPS: byte);
  public
    property  PS: byte read GetPS write SetPS;
  end;
 
function TNewJ1939PGNHelper.GetPS: byte;
begin
  Result := Self and $FF; //  and %00 00000000 11111111 (PS is in lowest 8 bits)
end;
 
procedure TNewJ1939PGNHelper.SetPS(const ANewPS: byte);
begin // debug says that Self was 100 and becomes 255, but PGN value is not changed
  Self := (Self and $3FF00) or ANewPS; //  and %11 11111111 00000000
end;  // If I change type TNewJ1939PGN to dword, although debug says that Self becomes 255 it does not propagate further
 
var
  NewJ1939CanID: TNewJ1939CanID;
begin
  NewJ1939CanID.PGN    := 100;
  NewJ1939CanID.PGN.PS := 255;
  WriteLn('BitSizeOf(NewJ1939CanID)           = ', BitSizeOf(NewJ1939CanID));
  WriteLn('BitSizeOf(NewJ1939CanID.SA)        = ', BitSizeOf(NewJ1939CanID.SA));
  WriteLn('BitSizeOf(NewJ1939CanID.PGN)       = ', BitSizeOf(NewJ1939CanID.PGN));
  WriteLn('BitSizeOf(NewJ1939CanID.Priority)  = ', BitSizeOf(NewJ1939CanID.Priority));
  WriteLn('NewJ1939CanID.PGN                  = ', NewJ1939CanID.PGN);    // this should show 255 but it shows 100 instead
  WriteLn('NewJ1939CanID.PGN.PS               = ', NewJ1939CanID.PGN.PS); // this should show 255 but it shows 100 instead
end.

Mantis conversion info:

  • Mantis ID: 38678
  • OS: all
  • OS Build: all
  • Build: 2021-03-01 SVN64623 x64 Debian
  • Platform: all
  • Version: 3.3.1
  • Monitored by: » @zeljkoavramovic (Zeljko Avramovic)