I have some code that is running fine for me at home using gnat/gcc 12.2. I decided to test it out on various versions of gnat, so I fired up godbolt and tried a few. I found that starting with version 13, my code throws an exception when the program ends:
raised PROGRAM_ERROR : example.adb:4 finalize/adjust raised exception
I wanted to double check and make sure I am not doing anything illegal and 13 catches it vs 13 just having a bug. I had to make a kinda convoluted example since the original code was from a much larger code base, so apologies if the generic formals and code don’t look too practical. I spent a few hours whittling it down from the original. Full code on godbolt is here:
Code is below:
example.adb:
with Ada.Text_IO; use Ada.Text_IO;
with Test;
procedure Example is
package B is
type Instance is limited interface;
function Make return Instance is abstract;
end B;
package C is
type Instance is new B.Instance with null record;
function Make return Instance is (null record);
end C; use C;
package T is new Test(B.Instance, C.Instance, C.Make);
Thing : B.Instance'Class := T.Make(2);
begin
Put_Line("Hello World");
end Example;
test.ads:
generic
type First(<>) is abstract tagged limited private;
type Second(<>) is new First with private;
with function Make return Second is <>;
package Test is
function Make(Key : Integer) return First'Class;
private
type Some_Access is not null access function return First'Class;
function Make_Delegate return First'Class;
Thing_Access : constant Some_Access := Make_Delegate'Access;
end Test;
test.adb:
with Ada.Containers.Indefinite_Ordered_Maps;
package body Test is
package Maps is new Ada.Containers.Indefinite_Ordered_Maps
(Key_Type => Integer,
Element_Type => Some_Access);
Map : Maps.Map;
function Make(Key : Integer) return First'Class is
begin
return Map(Key).all;
end Make;
function Make_Delegate return First'Class is
begin
return Make;
end Make_Delegate;
begin
Map.Insert(2,Thing_Access);
end Test;
It’s essentially a map of function pointers (only one in this example). I had to use a wrapper function (Make_Delegate) in order to have correct accessibility to it within the generic.