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;