[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