Skip to content

Arguments of functions cannot directly capture a local function, they can be captured using temporary variable

Summary

When calling a function that takes a reference to a procedure as argument, the expression @SomeLocalfunction is not recognized as a valid function reference. When using a temporary variable of the same type as the argument, assigning the same expression it works. The temp variable can then be used as an argument in the function.

System Information

  • Operating system: N/A
  • Processor architecture: N/A
  • Compiler version: 3.3.1
  • Device: N/A

Steps to reproduce

Compile the below project. You will get an error

tb.pp(28,3) Error: Can't take address of a subroutine marked as local

The line marked OK (line 27) compiles fine, the line marked Not OK (line 28) does not compile, when functionally, line 28 is the same as lines 26 and 27.

Example Project

program tb;

{$mode objfpc}
{$modeswitch functionreferences}

type
  TNotifyProc = reference to procedure(Sender : TObject);

Procedure DoCall(aProc : TNotifyProc);

begin
  aProc(Nil);
end;

Procedure DoTest;

  procedure HandleCall(Sender : TObject);
  begin
    Writeln('Nil passed: ',Sender=Nil);
  end;

var
 p : TNotifyProc;

begin
  P:=@HandleCall;
  DoCall(P); // OK
  DoCall(@HandleCall); // Not OK
end;

begin
  DoTest; 
end.

What is the current bug behavior?

Error on line 28 (marked Not OK)

tb.pp(28,3) Error: Can't take address of a subroutine marked as local

What is the expected (correct) behavior?

No error.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information