Possible compiler bug?

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.

gcc -14.0.0-aarch64 of 20231120 raises an ICE.

gcc-13.?.0-aarch64 fails with a stack overflow, something going wrong in finalization.

I don’t have 14.0.0-x86_64 built at the moment … but godbolt has it at version (trunk), and it shows the ICE. Do you want to post it?

I’ll be honest, the last time I tried to submit a multi-file bug, I missed a detail somewhere in the instructions and got yelled at pretty harshly. I’ve gotten too old to deal with folks yelling at me, so I’ve since just tried to come up with workarounds to any bugs I come across.

I just wasn’t sure if this was a bug or not, but based on what you are seeing with the different effects for different versions, I think it sounds like it is a bug, especially since one ends in a stack overflow for a one element map.

2 Likes

Since I’ve actually seen the ICE I would be happy to post it.

1 Like

Thanks!! I was just gonna live with it, so that is super nice of you. Thank you.

This reminds me the following issue (which has been fixed now):

with Ada.Strings.Unbounded, Ada.Text_IO;

procedure Trouble is
  type UA is array (positive range <>) of
    Ada.Strings.Unbounded.Unbounded_String;
  type C (s : Natural) is record
    x : UA (1 .. s);
  end record;
  function Get (n : Natural) return C is
    result : UA (1 .. n);
  begin
    Ada.Text_IO.Put (n'Image);
    return (n, result (1 .. n));
  exception
    when others => raise;
  end;
begin
  for i in 0 .. 10 loop
    declare
      x : C := Get (i);
    begin
      null;
    end;
  end loop;
end;

If you compile it with a not too recent version of GNAT (like the CE 2021), you may get interesting outputs, including finalize/adjust raised exception (it depends on the OS, the GNAT version, the contents of the Get function, the bounds of the loop)…

See 112781 – [13?/14 regression] ICE in generic instantiation

@simonjwright , I think I may have narrowed it down some more. Changing the base class from an interface to an abstract tagged limited null recored removes the exception in my test case. Does that happen for you too?

Since AdaCore’s expert is on the case (well, aware of the case :slight_smile: ) , and I’d not have anything to add really, I’ve been attending to the GNAT-vs-Apple’s-SDK-15 issue

Gotcha! Sorry to bother then!