https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124596

            Bug ID: 124596
           Summary: overriding indicator incorrectly rejected for
                    procedure on protected type in generic
           Product: gcc
           Version: 15.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ada
          Assignee: unassigned at gcc dot gnu.org
          Reporter: liam at liampwll dot com
                CC: dkm at gcc dot gnu.org
  Target Milestone: ---

In the below code I have a protected type implementing a synchronized
interface. Obviously the procedure here is overriding, but GNAT rejects the
code, saying that it is not. Interestingly, the code is also rejected when not
overriding is used, but the error message moves from the specification to the
body.

This is not a high priority as excluding the overriding_indicator completely
makes this work but that makes the code less readable.

This comes from this code in a real codebase:
https://github.com/Prunt3D/prunt/blob/dae3d3c07fa54b393bc6de4e78f0a014d579b9f8/src/prunt-default_modules-config_saving.ads#L81-L82

The issue here is that in Check_Synchronized_Overriding, when looping over the
parameters, Iface_Typ refers to the full record declaration but Prim_Typ refers
to the public part. This comes from Find_Parameter_Type where there's a ???:

      --  For an access parameter, obtain the type from the formal entity
      --  itself, because access to subprogram nodes do not carry a type.
      --  Shouldn't we always use the formal entity ???

Resolving that ??? like so solves the issue and doesn't cause any tests to
fail, but I still want to figure out why the behaviour is like that before I
say this is the correct fix:

modified   gcc/ada/sem_util.adb
@@ -8999,16 +8999,8 @@ package body Sem_Util is
    begin
       if Nkind (Param) /= N_Parameter_Specification then
          return Empty;
-
-      --  For an access parameter, obtain the type from the formal entity
-      --  itself, because access to subprogram nodes do not carry a type.
-      --  Shouldn't we always use the formal entity ???
-
-      elsif Nkind (Parameter_Type (Param)) = N_Access_Definition then
-         return Etype (Defining_Identifier (Param));
-
       else
-         return Etype (Parameter_Type (Param));
+         return Etype (Defining_Identifier (Param));
       end if;
    end Find_Parameter_Type;

Reproducer follows:

with Ada.Text_IO;

procedure Example is
   package Config is
      type Config_Data is private;
   private
      type Config_Data is null record;
   end Config;

   generic
   package Config_Saving is

      type Config_Saver is synchronized interface;

      procedure Register_For_Saving
        (This : in out Config_Saver; Config_Data : Config.Config_Data)
      is abstract;

      type Instance is synchronized new Config_Saver with private;

   private

      protected type Instance is new Config_Saver with
         overriding
         procedure Register_For_Saving (Config_Data : Config.Config_Data);
      end Instance;

   end Config_Saving;

   package body Config_Saving is

      protected body Instance is
         procedure Register_For_Saving (Config_Data : Config.Config_Data) is
         begin
            Ada.Text_IO.Put_Line ("Test.");
         end Register_For_Saving;
      end Instance;

   end Config_Saving;

   package My_Config_Saving is new Config_Saving;

   X : aliased My_Config_Saving.Instance;
   Y : access My_Config_Saving.Config_Saver'Class := X'Access;
   Z : Config.Config_Data;
begin
   Y.Register_For_Saving (Z);
end Example;

Reply via email to