Likely bug in bit field size computation lazarus / 64-FPC development ---------------------------------------------------------------------- 440bx · 2025-12-22 05:52 Hello, When compiling for 32 bit, there are cases when FPC v3.2.2 incorrectly calculates the total size of bitfields. The code below is attached to this post along with 32 and 64 bit project files to make testing simple: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$APPTYPE CONSOLE} program BitFieldsSize; type   _1bit     = 0 ..                $1;   _2bits    = 0 ..                $3;   _3bits    = 0 ..              $7;   _4bits    = 0 ..                $F;   _5bits    = 0 ..             $1F;   _6bits    = 0 ..               $3F;   _7bits    = 0 ..               $7F;   _8bits    = 0 ..               $FF;    { byte                            }   _9bits    = 0 ..              $1FF;   _10bits    = 0 ..              $3FF;  _11bits    = 0 ..              $7FF;  _12bits    = 0 ..              $FFF;  _13bits    = 0 ..           $1FFF;  _14bits    = 0 ..             $3FFF;  _15bits    = 0 ..           $7FFF;  _16bits    = 0 ..             $FFFF;    { word                            }  _17bits    = 0 ..            $1FFFF;  _18bits    = 0 ..            $3FFFF;  _19bits    = 0 ..            $7FFFF;   _20bits    = 0 ..            $FFFFF;  _21bits    = 0 ..         $1FFFFF;  _22bits    = 0 ..           $3FFFFF;  _23bits    = 0 ..           $7FFFFF;  _24bits    = 0 ..           $FFFFFF;  _25bits  = 0 ..          $1FFFFFF;  _26bits    = 0 ..          $3FFFFFF;  _27bits    = 0 ..          $7FFFFFF;  _28bits    = 0 ..          $FFFFFFF;  _29bits    = 0 ..         $1FFFFFFF;   _30bits    = 0 ..       $3FFFFFFF;  _31bits    = 0 ..         $7FFFFFFF;  _32bits    = 0 ..         $FFFFFFFF;    { DWORD                             }   _33bits    = 0 ..        $1FFFFFFFF;  _34bits    = 0 ..        $3FFFFFFFF;  _35bits    = 0 ..        $7FFFFFFFF;  _36bits    = 0 ..      $FFFFFFFFF;  _37bits    = 0 ..       $1FFFFFFFFF;  _38bits    = 0 ..       $3FFFFFFFFF;  _39bits    = 0 ..       $7FFFFFFFFF;   _40bits    = 0 ..       $FFFFFFFFFF;  _41bits    = 0 ..      $1FFFFFFFFFF;  _42bits    = 0 ..      $3FFFFFFFFFF;  _43bits    = 0 ..      $7FFFFFFFFFF;  _44bits    = 0 ..      $FFFFFFFFFFF;  _45bits  = 0 ..     $1FFFFFFFFFFF;  _46bits    = 0 ..     $3FFFFFFFFFFF;  _47bits    = 0 ..     $7FFFFFFFFFFF;  _48bits    = 0 ..     $FFFFFFFFFFFF;  _49bits    = 0 ..    $1FFFFFFFFFFFF;   _50bits    = 0 ..    $3FFFFFFFFFFFF;  _51bits    = 0 ..    $7FFFFFFFFFFFF;  _52bits  = 0 ..    $FFFFFFFFFFFFF;  _53bits    = 0 ..   $1FFFFFFFFFFFFF;  _54bits    = 0 ..   $3FFFFFFFFFFFFF;  _55bits    = 0 ..   $7FFFFFFFFFFFFF;  _56bits    = 0 ..   $FFFFFFFFFFFFFF;  _57bits    = 0 ..  $1FFFFFFFFFFFFFF;  _58bits    = 0 ..  $3FFFFFFFFFFFFFF;  _59bits  = 0 ..  $7FFFFFFFFFFFFFF;   _60bits    = 0 ..  $FFFFFFFFFFFFFFF;  _61bits    = 0 .. $1FFFFFFFFFFFFFFF;  _62bits    = 0 .. $3FFFFFFFFFFFFFFF;  _63bits    = 0 .. $7FFFFFFFFFFFFFFF;  const  QWORD_DEC_MAX  = 18446744073709551615;   QWORD_HEX_MAX  = qword($FFFFFFFFFFFFFFFF);  // must typecast, otherwise error type  _64bitsDec     = 0..QWORD_DEC_MAX; type  _64bitsHex     = 0..QWORD_HEX_MAX;  type  { _SYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION                                 }    { $f3  243 }  { SystemTrustedAppsRuntimeInformation                        }   PSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION = ^TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION;  TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION = record    union                                   : bitpacked record      case integer of        1 : (             Flags                                : qword;          );        2 : (             Supported                            :  _2bits;             Spare                                : _62bits;          );    end;     { removed this field to simplify                                        }  end;   {$ifdef WIN32}    { when compiling for 32 bit the following condition evaluates to FALSE    }  { which is incorrect.                                                   }     {$if sizeof(TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION) <> $8}      {$FATAL sizeof TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION does not equal $8}    {$endif}  {$endif}   {$ifdef WIN64}    {$if sizeof(TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION) <> $8}      {$FATAL sizeof TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION does not equal $8}    {$endif}  {$endif}   begin  writeln;  writeln(QWORD_DEC_MAX);  writeln(QWORD_HEX_MAX);  writeln;   if sizeof(pointer) = 4 then writeln('32 bit size') else writeln('64 bit size');   writeln;  writeln('sizeof TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION: ',           sizeof(TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION));   readln;end.   When compiling the above code for 32 bit, the compiler complains that the size of the record does not equal 8 when it is 8, fact which can be verified by compiling for 64 bit (in this case the record size is bitness independent.) It would be nice to know if the upcoming v3.2,4 exhibits the same problem. Comments welcome. ETA: There is also a problem calculating bit field sizes in 64 bits.  To see the problem change "Supported  : _1bit;" and "Spare : _63bits" and the program will no longer compile in 64 bit.  (IOW, move 1 bit from the current "Supported" value to the "Spare" field value.  With that change the program will no longer compile in 64 bit (and, it definitely should.) ---------------------------------------------------------------------- paweld · 2025-12-22 06:59 For 32-bit, it does not compile on either 3.2.3 (fixes) or 3.3.1 (trunk). After changing to 1/63, it does not compile for 64-bit only in 3.2.3 (fixes), but it is OK in 3.3.1 (trunk). ---------------------------------------------------------------------- ALLIGATOR · 2025-12-22 07:25 FPC [main] Windows x64: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 1844674407370955161518446744073709551615 64 bit size sizeof TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION: 8 x32: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i BitFieldsSize.lpr(116,8) Error: User defined: sizeof TSYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION does not equal $8 ---------------------------------------------------------------------- 440bx · 2025-12-22 07:38 In the meantime, I've been doing some additional testing. It seems that part of the problem is when the total number of bits adds up to 64.  if they add up to less than 64 then it seems the compiler's behavior is ok (I say "seems" because I couldn't claim the testing I've done is extensive.) One particularly insidious problem I found in 64 bit is that if a pointer field is defined where the comment  "{ removed this field to simplify }" currently is, then the compilation succeeds but the offset to the field is incorrect (it's off by 4 bytes.) I wonder what v3.2.4RC1 does ... if someone has it installed and cares to test, I'd appreciate that. ---------------------------------------------------------------------- ALLIGATOR · 2025-12-22 08:12 Interesting! Run this code first under x64, then under x32 Amazing! 😁 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program BitFieldsSize; type  TRec64_v0 = bitpacked record    Half1: 0..UInt64(1 shl 32)-1;    Half2: 0..UInt64(1 shl 32)-1;  end;  TRec64_v1 = bitpacked record    Half1: 0..UInt64(1 shl  1)-1;    Half2: 0..UInt64(1 shl 63)-1;  end;  TRec64_v2 = bitpacked record    Half1: 0..UInt64(1 shl 16)-1;    Half2: 0..UInt64(1 shl 48)-1;  end; begin  writeln('sizeof TRec64_v0: ', sizeof(TRec64_v0));  writeln('sizeof TRec64_v1: ', sizeof(TRec64_v1));  writeln('sizeof TRec64_v2: ', sizeof(TRec64_v2));   readln;end. ---------------------------------------------------------------------- 440bx · 2025-12-22 08:21 Yes, interesting indeed. ---------------------------------------------------------------------- ASerge · 2025-12-22 14:20 Quote from: 440bx on December 22, 2025, 09:21:51 amYes, interesting indeed. Especially if change 63 to 62. On x64: Quotesizeof TRec64_v0: 8 sizeof TRec64_v1: 0 sizeof TRec64_v2: 8 ---------------------------------------------------------------------- paweld · 2025-12-22 16:55 Quote from: 440bx on December 22, 2025, 08:38:14 am I wonder what v3.2.4RC1 does ... if someone has it installed and cares to test, I'd appreciate that. Version 3.2.4rc1 behaves exactly the same as 3.2-fixes. ---------------------------------------------------------------------- 440bx · 2025-12-22 18:10 Reported as a bug. Link: https://gitlab.com/freepascal.org/fpc/source/-/issues/41554 Ticket: 41554