Linking error with generics: undefined reference to `SYSTEM$_$TOBJECT_$__$$_GETHASHCODE$$<unknown type>'
Summary
Compiling and linking a generic procedure where the type has a count causes a linker error, even though the generic procedure is unused.
System Information
- Operating system: Linux, x86_64, OpenSuse Leap 15.6 (also on AlmaLinux 9.4)
- Processor architecture: x86-64, 64-bit
- Compiler version: trunk, 3.3.1, 3.3.1-16505-gfdae200281
- Device: Desktop Personal Computer
Steps to reproduce
Given these three source files:
unit_a.pas
unit unit_a;
interface
type
tLoopAll = reference to procedure (const i: integer);
tMemberSeqId = reference to procedure (const member: pointer; const seqId: integer);
procedure loop (const start: integer; const final_value: integer; const loopPr: tLoopAll);
generic procedure loop<T> (const list: T; const doItem: tMemberSeqId);
implementation
procedure loop (const start: integer; const final_value: integer; const loopPr: tLoopAll);
procedure forward_iterate (i: integer = 0);
begin
for i := start to final_value do loopPr(i);
end;
procedure reverse_iterate (i: integer = 0);
begin
for i := start downto final_value do loopPr(i);
end;
begin
if final_value < start then reverse_iterate
else
forward_iterate;
end;
generic procedure loop<T> (const list: T; const doItem: tMemberSeqId);
begin
loop(0, list.count - 1, procedure (const i: integer)
begin
doItem(list.items[i], i);
end);
end;
end.
// CudaText: lexer_file=Pascal; tab_size=2; tab_spaces=Yes; newline=LF;
unit_b.pas
unit unit_b;
interface
type
tProc = reference to procedure;
tProcs = array of tProc;
procedure pick_all (const procs: tProcs);
implementation
uses unit_a;
procedure pick_all (const procs: tProcs);
begin
if length(procs) > 0 then loop(low(procs), high(procs), procedure (const i: integer)
begin
procs[i]();
end);
end;
end.
// CudaText: lexer_file=Pascal; tab_size=2; tab_spaces=Yes; newline=LF
appmain.pas
program appmain;
uses unit_b;
begin
end.
// CudaText: lexer_file=Pascal; tab_size=2; tab_spaces=Yes; newline=LF;
When compiling it the following occurs:
$ fpc -Mobjfpc -Sh -Fcutf8 -MadvancedRecords -MtypeHelpers -MfunctionReferences -ManonymousFunctions -MimplicitFunctionSpecialization -gh -gl -gp -gw3 -Xi -Sm -Sg -Os -Si appmain.pas
Free Pascal Compiler version 3.3.1 [2024/09/26] for x86_64
Copyright (c) 1993-2024 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling appmain.pas
Compiling unit_b.pas
Compiling unit_a.pas
Linking appmain
/usr/bin/ld.bfd: unit_b.o:(.data.n_VMT_$UNIT_B$_$PICK_ALL$TPROCS_$$_$CAPTURERCLASS_9_1_15_11+0xb8): undefined reference to `SYSTEM$_$TOBJECT_$__$$_GETHASHCODE$$<unknown type>'
appmain.pas(6,1) Error: Error while linking
appmain.pas(6,1) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
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, compiler gives a Fatal: Internal error 2021010301 error.
What is the expected (correct) behavior?
That the code compile with no errors. Something to note is if the generic procedure is commented out, the code compiles and links. See #40925
unit_a.pas
unit unit_a;
interface
type
tLoopAll = reference to procedure (const i: integer);
tMemberSeqId = reference to procedure (const member: pointer; const seqId: integer);
procedure loop (const start: integer; const final_value: integer; const loopPr: tLoopAll);
//generic procedure loop<T> (const list: T; const doItem: tMemberSeqId);
implementation
procedure loop (const start: integer; const final_value: integer; const loopPr: tLoopAll);
procedure forward_iterate (i: integer = 0);
begin
for i := start to final_value do loopPr(i);
end;
procedure reverse_iterate (i: integer = 0);
begin
for i := start downto final_value do loopPr(i);
end;
begin
if final_value < start then reverse_iterate
else
forward_iterate;
end;
{
generic procedure loop<T> (const list: T; const doItem: tMemberSeqId);
begin
loop(0, list.count - 1, procedure (const i: integer)
begin
doItem(list.items[i], i);
end);
end;
}
end.
// CudaText: lexer_file=Pascal; tab_size=2; tab_spaces=Yes; newline=LF;
Code compiles without error:
$ fpc -Mobjfpc -Sh -Fcutf8 -MadvancedRecords -MtypeHelpers -MfunctionReferences -ManonymousFunctions -MimplicitFunctionSpecialization -gh -gl -gp -gw3 -Xi -Sm -Sg -Os -Si appmain.pas
Free Pascal Compiler version 3.3.1 [2024/09/26] for x86_64
Copyright (c) 1993-2024 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling appmain.pas
Compiling unit_b.pas
Compiling unit_a.pas
Linking appmain
72 lines compiled, 0.1 sec, 174496 bytes code, 1152456 bytes data
Relevant logs and/or screenshots
See Steps to reproduce
Possible fixes
Not sure, I the code that I had to isolate this repro example from was building and running last year. This is related to #40925