Delphi anonymous function is passed to inline function

I stumbled upon unexpected behavior in Delphi 2009. After examining a strange error in my code, I was able to narrow down the problem and create the minimal example below.

Of course, the following code prints the value 1:

program Example1;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 1;
    end, 0));

end.

      

Likewise, this program prints the value 2:

program Example2;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 2;
    end, 0));

end.

      

"Obviously" this third program prints the same value as the first, namely: 1:

program Produce;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 1;
    end, 0));

  fcn(function(const X: integer): integer
    begin
      result := 2;
    end, 0); // discard the output

end.

      

However, the output is not 1, but 2. It looks like the compiler is using the second anonymous function in the call fcn

to writeln

.

It seems to me that this is a bug in the Delphi 2009 compiler, but it may also just be not understanding the finer details of anonymous functions in Delphi. What do you think?

+3


source to share


1 answer


This is definitely a bug and according to the comments received on the subject, this has been fixed in Delphi XE. Probably the simplest workaround is to skip the insert request if the compiler can't handle it:

program Solve;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer;
  {$IF CompilerVersion >= 22}inline;{$IFEND} {Warning: Horrible bug in Delphi 2009}
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 1;
    end, 0));

  fcn(function(const X: integer): integer
    begin
      result := 2;
    end, 0); // discard the output

end.

      



In most cases, the performance loss should be negligible in Delphi 2009 and you are requesting inlining in XE and later. Of course, if you don't think the attachment is important at all, you can simply delete the request altogether.

+1


source







All Articles