7

The following code gives a stack overflow:

function Func(x : Double) : Double; overload;
function Func(x : Integer) : Double; overload;


function Func(x : Double) : Double;
begin
  Result := Func(Round(x));
end;


function Func(x : Integer) : Double;
begin
  Result := 1.0;
end;

The Integer overloaded function is never called, the Double overloaded function calls itself until the stack overflows.

The following code works as expected:

function Func2(x : Double) : Double; overload;
function Func2(x : Integer) : Double; overload;

function Func2(x : Double) : Double;
var
  ix : Integer;
begin
  ix := Round(x);
  Result := Func(ix);
end;


function Func2(x : Integer) : Double;
begin
  Result := 1.0;
end;

Is this a compiler bug or expected behavior?

Fabrizio
  • 7,603
  • 6
  • 44
  • 104
Matej
  • 442
  • 3
  • 9

2 Answers2

7

This is, I suspect, to be expected.

The issue is that the compiler-intrinsic Round function returns a 64-bit integer. Both CodeInsight and the official documentation tells me that. And if the compiler has to chose between a routine taking a 32-bit integer or a double, when given a 64-bit integer, it chooses the routine accepting a double.

To verify this, try

procedure Test(x: Double); overload;
begin
  ShowMessage('double');
end;

procedure Test(x: Integer); overload;
begin
  ShowMessage('integer');
end;

procedure TForm5.FormCreate(Sender: TObject);
begin
  Test(Int64.MaxValue)
end;
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
6

System.Round function results an Int64 value.

I think that the compiler retains that the Double overload of your Func function is more appropriated than the Integer overload.

In fact, the Integer overload could cause information loss if the param's value exceeds the Integer's type min-max (from -2147483648 to 2147483647, see System.Integer).

Changing the Integer param to an Int64 param will solve the problem and avoid information losses.

function Func(x : Double) : Double; overload;
function Func(x : Int64) : Double; overload;

...

function Func(x : Double) : Double;
begin
  Result := Func(Round(x));
end;

function Func(x : Int64) : Double;
begin
  Result := 1.0;
end;
Fabrizio
  • 7,603
  • 6
  • 44
  • 104