[fpc-devel] Type helper bug

Zeljko Avramovic avra at writeme.com
Wed May 5 12:37:40 CEST 2021


In example bellow, both record field ID.PGN and type helper for that record field ID.PGN.PS point to the same memory location in a bitpacked record not aligned to a byte. ID.PGN can be modified correctly. ID.PGN.PS can not be modified correctly. If a field in a bitpacked record can work well (probably by masking and bit shifting), then helper should be able to do the same.

Could someone please take a look? Thanks!

Here is the bug report: https://bugs.freepascal.org/view.php?id=38678

---------------------------------------------------------------------

program TestTypeHelperBug;
{$mode delphi} {$H+}
{$modeswitch typehelpers}

type
  T18bits = 0..(1 shl 18)-1;

  TBitPackedRec = bitpacked record
    SA:  0..(1 shl 7)-1;
    PGN: T18bits;
    PR:  0..7;
  end;

  T18bitsHelper = type helper for T18bits
  private
    function  GetPS: byte;
    procedure SetPS(const ANewPS: byte);
  public
    property PS: byte read GetPS write SetPS;
  end;

function T18bitsHelper.GetPS: byte;
begin
  Result := Self and $FF; // and %00 00000000 11111111 (PS is in lowest 8 bits)
end;

procedure T18bitsHelper.SetPS(const ANewPS: byte);
begin
  Self := (Self and $3FF00) or ANewPS; // and %11 11111111 00000000
end;

var
  PGN: T18bits;
  ID:  TBitPackedRec;
begin
  PGN    := 100;
  WriteLn('1. PGN    = ', PGN);          // PGN is 100 as it should be
  WriteLn('1. PGN.PS = ', PGN.PS);       // PGN.PS is 100 as it should be
  PGN.PS := 255;
  WriteLn('2. PGN    = ', PGN);          // PGN is 255 as it should be
  WriteLn('2. PGN.PS = ', PGN.PS);       // PGN.PS is 255 as it should be

  ID.SA  := $55;
  ID.PR  := 3;
  ID.PGN := 100;
  WriteLn('1. ID.PGN    = ', ID.PGN);    // PGN is 100 as it should be
  WriteLn('1. ID.PGN.PS = ', ID.PGN.PS); // PGN.PS is 100 as it should be
  WriteLn('1. ID.SA     = ', ID.SA);     // PGN.SA is 85 as it should be
  WriteLn('1. ID.PR     = ', ID.PR);     // PGN.PR is 3 as it should be
  ID.PGN.PS := 255;
  WriteLn('2. ID.PGN    = ', ID.PGN);    // PGN is 100    ( <<< WRONG!!! IT SHOULD BE 255)
  WriteLn('2. ID.PGN.PS = ', ID.PGN.PS); // PGN.PS is 100 (WRONG!!! IT SHOULD BE 255)
  WriteLn('2. ID.SA     = ', ID.SA);     // PGN.SA is 85 as it should be
  WriteLn('2. ID.PR     = ', ID.PR);     // PGN.PR is 3 as it should be
end.


More information about the fpc-devel mailing list