Skip to content

Anonymous function call and access of record method causes a compiler unhanded exception to occur. (When called from a record class method).

Summary

When calling an anonymous function that returns an advanced record, and the result of the call is used to access a method of that record, the compiler raises an internal exception. However, it only does this in a class procedure of the record in question, not in a procedure that is not associated with the record.

System Information

  • Operating system: Linux, AlmaLinux 9.1 x86_64
  • Processor architecture: x86_64
  • Compiler version: 3.3.1-12241-gcf41a549
  • Device: Computer

Steps to reproduce

Given this program:

program record_member;
{$mode objfpc}{$H+}
{$modeswitch AnonymousFunctions}
{$modeswitch AdvancedRecords}

uses
        sysutils;

type
        TSomeRec = record
                a: integer;
                procedure print;
                function text: string;
                class procedure main; static;
        end;

function some_fun_0: TSomeRec;
        begin
                result.a := 4;
        end;

procedure TSomeRec.print;
        begin
                writeln('a = ', a);
        end;

function TSomeRec.text: string;
        begin
                result := format('a = %d', [a]);
        end;

procedure main;
        begin
                some_fun_0().print;
                (function: TSomeRec begin result.a := 5 end()).print;
                writeln((function: TSomeRec begin result.a := 10 end()).text);
        end;

class procedure TSomeRec.main; static;
        begin
                some_fun_0().print;
                (function: TSomeRec begin result.a := 5 end()).print;
                writeln((function: TSomeRec begin result.a := 10 end()).text);
        end;

begin
        main;
        TSomeRec.main;
end.

When compiled, the following occurs:

$ fpc record_member.pas
Free Pascal Compiler version 3.3.1 [2022/12/26] for x86_64
Copyright (c) 1993-2022 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling record_member.pas
record_member.pas(42,4) Error: Compilation raised exception internally
Fatal: Compilation aborted
An unhandled exception occurred at $0000000000527E12:
EAccessViolation: Access violation
  $0000000000527E12

Error: /home/dev/fpc_usr/lib/fpc/3.3.1/ppcx64 returned an error exitcode

Example Project

See steps to reproduce.

What is the current bug behavior?

See steps to reproduce, an internal exception is raised by the compiler.

What is the expected (correct) behavior?

The program should compile and run.

Why? Because the following program compiles and runs:

program record_member2;
{$mode objfpc}{$H+}
{$modeswitch AnonymousFunctions}
{$modeswitch AdvancedRecords}

uses
        sysutils;

type
        TSomeRec = record
                a: integer;
                procedure print;
                function text: string;
                class procedure main; static;
        end;

function some_fun_0: TSomeRec;
        begin
                result.a := 4;
        end;

procedure TSomeRec.print;
        begin
                writeln('a = ', a);
        end;

function TSomeRec.text: string;
        begin
                result := format('a = %d', [a]);
        end;

procedure main;
        begin
                some_fun_0().print;
                (function: TSomeRec begin result.a := 5 end()).print;
                writeln((function: TSomeRec begin result.a := 10 end()).text);
        end;

class procedure TSomeRec.main; static;
        function one: TSomeRec; begin result.a := 5 end;
        function two: TSomeRec; begin result.a := 10 end;
        begin
                some_fun_0().print;
                one.print;
                writeln(two.text);
        end;

begin
        main;
        TSomeRec.main;
end.

Compiler output:

$ fpc record_member2.pas
Free Pascal Compiler version 3.3.1 [2022/12/26] for x86_64
Copyright (c) 1993-2022 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling record_member2.pas
Linking record_member2
51 lines compiled, 0.2 sec, 374976 bytes code, 166456 bytes data

Program output:

$ ./record_member2
a = 4
a = 5
a = 10
a = 4
a = 5
a = 10

Relevant logs and/or screenshots

See steps to reproduce.

Possible fixes

None that I know of.

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