IntToHex(Value: QWord; Digits: Integer) internally casts QWord to Int64, which causes incorrect behavior for values ≥ 2^63.

Summary

IntToHex(Value: QWord; Digits: Integer) internally casts QWord to Int64, which causes incorrect behavior for values ≥ 2^63. This leads to signed interpretation and compile-time range check warnings when round-tripped into Pascal source.

System Information

Operating system: Windows / Linux Processor architecture: x86-64 Compiler version: 3.2.2 and trunk (confirmed via sysstr.inc) Device: Standard PC

Steps to reproduce

  1. Compile and run the following code: '''pascal uses SysUtils;

var V: QWord; begin V := $A769CDDE6CFC0000; WriteLn('As QWord: ', V); WriteLn('As Hex: ', IntToHex(V, 16)); end. '''

  1. Observe that the hex output appears visually correct, but this hides a problem: the function internally casts QWord → Int64.

  2. Now emit this output back into a .pas source file: '''pascal C: array[0..0] of QWord = ( $A769CDDE6CFC0000 ); '''

  3. Warning: range check error while evaluating constants (-6383344641626079232 must be between 0 and 18446744073709551615)

Example Project

What is the current bug behavior?

IntToHex(Value: QWord, Digits) casts QWord to Int64, which silently corrupts unsigned values above $7FFFFFFFFFFFFFFF. The output appears hex-correct but becomes signed and causes range-check issues when reused.

What is the expected (correct) behavior?

IntToHex(QWord) should preserve the unsigned value fully and never rely on narrowing casts. Values above 2^63 should be printed as 16-digit hex without triggering signed overflow or invalid constants.

Relevant logs and/or screenshots

Example of invalid constant being produced: '''pascal C: array[0..0] of QWord = ( $A769CDDE6CFC0000 // → interpreted as -6383344641626079232 ); '''

Line with the issue

in sysstr.inc on line 917 uint64 is casted to a int64:

function IntToHex(Value: QWord; Digits: integer): string;
begin
  result := IntToHex(Int64(Value), Digits); // this cast is unsafe
end;

Possible fixes

function IntToHex(Value: QWord; Digits: Integer): string;
const
  HexDigits: array[0..15] of Char = '0123456789ABCDEF';
var
  I: Integer;
begin
  SetLength(Result, Digits);
  for I := Digits downto 1 do
  begin
    Result[I] := HexDigits[Value and $F];
    Value := Value shr 4;
  end;
end;