Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2022-09

Arguments gets corrupted with anonymous nested function

8 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Hairy Pixels

The following program uses an anonymous nested function which captures a local variable. It seems the arguments get corrupted (likely because of the hidden first param for the nested function signature) and prints garbled data. I reduced this snippet down from another project but I’m not sure if this is the best way to reproduce the real issue.

Is this a compiler bug or am I doing something wrong?

===========================

{$mode objfpc}
{$modeswitch anonymousfunctions}
{$modeswitch nestedprocvars}
program test;
type
  generic TMyClass<T> = class
    type
      TCallback = procedure (data: T) is nested;
    procedure Call(callback: TCallback);
    procedure Test;
  end;
procedure TMyClass.Call(callback: TCallback);
begin
  callback(default(T));
end;
procedure TMyClass.Test;
var
  i: integer;
begin
  Call(procedure(data: T)
  begin
    Inc(i);
    writeln(data);  // prints garbled data like 73251232
  end);
end;
begin
  specialize TMyClass<Integer>.Create.Test;
end.

Regards,
Ryan Joseph

Sven Barth
to Hairy Pixels

Hairy Pixels via fpc-pascal schrieb am
So., 4. Sep. 2022, 18:07:

Show quoted text 45 lines
The following program uses an anonymous nested function which captures a local variable. It seems the arguments get corrupted (likely because of the hidden first param for the nested function signature) and prints garbled data. I reduced this snippet down from another project but I’m not sure if this is the best way to reproduce the real issue. Is this a compiler bug or am I doing something wrong? =========================== {$mode objfpc} {$modeswitch anonymousfunctions} {$modeswitch nestedprocvars} program test; type generic TMyClass<T> = class type TCallback = procedure (data: T) is nested; procedure Call(callback: TCallback); procedure Test; end; procedure TMyClass.Call(callback: TCallback); begin callback(default(T)); end; procedure TMyClass.Test; var i: integer; begin Call(procedure(data: T) begin Inc(i); writeln(data); // prints garbled data like 73251232 end); end; begin specialize TMyClass<Integer>.Create.Test; end.

Does this also happen if you don't use a class? Otherwise it might be related with the other error you already reported. But report this anyway, I'll simply mark it as duplicate if necessary...

Regards,
Sven

Hairy Pixels
to Sven Barth
On Sep 4, 2022, at 1:36 PM, Sven Barth wrote: Does this also happen if you don't use a class? Otherwise it might be related with the other error you already reported. But report this anyway, I'll simply mark it as duplicate if necessary...

I only reproduced using a class with generics. I already reported this? Looking at GitLab now and I don’t see which one it may be.

Regards,
Ryan Joseph

Sven Barth
to Hairy Pixels
Hairy Pixels wrote 6 lines
> On Sep 4, 2022, at 1:36 PM, Sven Barth wrote: > > Does this also happen if you don't use a class? Otherwise it might be related with the other error you already reported. But report this anyway, I'll simply mark it as duplicate if necessary... > I only reproduced using a class with generics. I already reported this? Looking at GitLab now and I don’t see which one it may be.

I was thinking about this one:
https://gitlab.com/freepascal.org/fpc/source/-/issues/39810

Cause in that case the compiler inserts a Self parameter where it shouldn't and it's likely that it does the same in the case you presented here.

Regards,
Sven

Sven Barth
to Peter B

Peter B via fpc-pascal schrieb am Mi., 7.
Sep. 2022, 13:58:

Show quoted text 8 lines
I'm wondering if this is related to https://gitlab.com/freepascal.org/fpc/source/-/issues/38703 That caused a parameter corruption in a standard function. https://lists.freepascal.org/pipermail/fpc-pascal/2022-March/060361.html Should be easy to check. Just try compiling with -O1

It's more likely (and also known!) that the compiler has a problem when converting anonymous and/or nested functions.

Regards,
Sven

Benito van der Zander
to Peter B: I'm wondering if this is related to https://gitlab.com/freepascal.org/fpc/source/-/issues/…

Hi,

Show quoted text 14 lines
https://gitlab.com/freepascal.org/fpc/source/-/issues/38703 I'm afraid that with -O4 it is by design. -O4 enables -OoUNCERTAIN, and the documentation about -OoUNCERTAIN notes that: “If uncertain optimizations are enabled, the CSE algorithm assumes that — If something is written to a local/global register or a procedure/function parameter, this value doesn’t overwrite the value to which a pointer points. — If something is written to memory pointed to by a pointer variable, this value doesn’t overwrite the value of a local/global variable or a procedure/function parameter.”

is it doing that? did it ever do that? It might break a lot of my code

But I cannot find any place in FPC where it is doing any OoUNCERTAIN optimizations

Best,
Benito

Peter B wrote 14 lines
I'm wondering if this is related to https://gitlab.com/freepascal.org/fpc/source/-/issues/38703 That caused a parameter corruption in a standard function. https://lists.freepascal.org/pipermail/fpc-pascal/2022-March/060361.html Should be easy to check. Just try compiling with -O1 Cheers, Peter _______________________________________________ fpc-pascal maillist  - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Jonas Maebe
to Benito van der Zander
Benito van der Zander wrote 18 lines
Hi, > https://gitlab.com/freepascal.org/fpc/source/-/issues/38703 > I'm afraid that with -O4 it is by design. > -O4 enables -OoUNCERTAIN, and the documentation about -OoUNCERTAIN > notes that: > > "If uncertain optimizations are enabled, the CSE algorithm assumes > that > -- If something is written to a local/global register or a > procedure/function parameter, this value doesn't overwrite the value > to which a pointer points. > -- If something is written to memory pointed to by a pointer variable, > this value doesn't overwrite the value of a local/global variable or a > procedure/function parameter." is it doing that? did it ever do that?

It did that when the old assembler-level CSE optimiser still existed. It's been removed for a long time now.

Jonas