[fpc-devel] nestedprocvar questions

Sven Barth pascaldragon at googlemail.com
Wed Aug 1 11:20:49 CEST 2012


Am 31.07.2012 22:40, schrieb Craig Peterson:
> Hi Sven,
>
> On 7/31/2012 3:11 PM, Sven Barth wrote:
>> Delphi does not use the "@" to designate the function address, so this
>> isn't to take the address of a function/method. In Delphi you just use
>> "r" (in your example).
>
> Normally Delphi doesn't allow assigning local functions to procedure
> variables or arguments (just like FPC without 'nestedprocvar').  If the
> nested function doesn't access arguments or variables in the outer scope
> it generates the stack frame differently and the resulting function is
> identical to a standalone non-nested one.  You can then use @ to bypass
> the typechecking.
>

Ok... I now tested myself as well using Delphi XE, FPC 2.7.1 (2.6.0 
works also) and the following code:

=== source begin ===

program tnested;

{$ifdef fpc}
   {$mode delphi}
{$endif}
{$APPTYPE CONSOLE}

type
   TFunc = function: LongInt;

procedure DoTest(aFunc: TFunc);
begin
   Writeln(aFunc);
end;

procedure Test;
var
   t: Integer;

   function Test1: LongInt;
   begin
     Result := 42;
   end;

   function Test2: LongInt;
   begin
     Result := t;
   end;

begin
   DoTest(@Test1);
   t := 21;
   DoTest(@Test2);
   t := 42;
   DoTest(@Test2);
end;

begin
   Test;
   Readln;
end.

=== source end ===

Without the "@" the compilation in Delphi indeed fails (it also does in 
FPC, but with a different error).

The output of the one compiled with Delphi is the following:

=== output Delphi begin ===

42
4230595
4230595

=== output Delphi end ===

The output of the FPC one is this:

=== output FPC begin ===

42
0
0

=== output FPC end ===

In both cases the output printed by Test2 can be considered garbage and 
thus Delphi and FPC behave identical (the value of "t" in the context of 
"Test2" is undefined).

> What David posted is working Delphi code.  We use that style in a few
> places to better group and encapsulate procedures for callbacks without
> polluting the unit namespace.
>
>> Adding "nestedprocvar" automatically wouldn't change anything as you'd
>> still need "is nested" to have a procvar to which nested functions can
>> be passed to.
>
> The posted code crashes with an EAccessViolation if you run it using
> FreePascal's default behavior.  Adding {$modeswitch nestedprocvar} and
> nothing else makes it work correctly, so there's some change in compiler
> behavior even if "is nested" isn't used.
>

I now tested exactly David's code and you're right... as far as I can 
see this is because nested functions are all marked as "delphi style 
nested call" in case the modeswitch "nestedprocvar" is set (note: the 
access violation might be, because Strings are used and thus 
initialization and finalization has to take place).

>> How exactly do you mean this?
>
> Is the behavior described above (the $modeswitch without "is nested")
> intentional behavior we can rely on, or an unexpected side effect?  Can
> it be added to {$MODE DELPHI} to increase Delphi compatibility?

I don't know whether it is intentional behavior as Jonas is the one who 
implemented this, but you can open a feature request issue on the 
bugtracker where you describe your situation similar to here (with a 
stress on Delphi compatiblity ;) ) and then Jonas can decide whether he 
enables it for mode Delphi or not (Note: he is currently on vacation, so 
it might take a bit longer). And please attach a full compilable example 
(that compiles in Delphi in should also compile in FPC (using Delphi mode)).

Regards,
Sven



More information about the fpc-devel mailing list