That's an oversight in Declare_Inherited_Private_Subprograms, which does not 
deal with formal types specially as it should per RM 3.2.3(7.d/2).

Tested on x86-64/Linux, applied on the mainline.


2025-10-27  Eric Botcazou  <[email protected]>

        PR ada/29958
        * sem_ch7.adb (Declare_Inherited_Private_Subprograms): Deal with
        formal types specially.


2025-10-27  Eric Botcazou  <[email protected]>

        * gnat.dg/specs/private3-child.ads: New test.
        * gnat.dg/specs/private3.ads: New helper.

-- 
Eric Botcazou
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
index 2002cc7621f..989e6bfd2d0 100644
--- a/gcc/ada/sem_ch7.adb
+++ b/gcc/ada/sem_ch7.adb
@@ -2266,7 +2266,32 @@ package body Sem_Ch7 is
                         Next_Elmt (Op_Elmt_2);
                      end loop;
 
-                     --  Case 2: We have not found any explicit overriding and
+                     --  Case 2: For a formal type, we need to explicitly check
+                     --  whether a local subprogram hides from all visibility
+                     --  the implicitly declared primitive, because subprograms
+                     --  declared in a generic package specification are never
+                     --  primitive for a formal type, even if they happen to
+                     --  override an operation of the type (RM 3.2.3(7.d/2)).
+
+                     if Is_Generic_Type (E) then
+                        declare
+                           S : Entity_Id;
+
+                        begin
+                           S := E;
+                           while Present (S) loop
+                              if Chars (S) = Chars (Parent_Subp)
+                                and then Type_Conformant (Prim_Op, S)
+                              then
+                                 goto Next_Primitive;
+                              end if;
+
+                              Next_Entity (S);
+                           end loop;
+                        end;
+                     end if;
+
+                     --  Case 3: We have not found any explicit overriding and
                      --  hence we need to declare the operation (i.e., make it
                      --  visible).
 
package Private3 is

  type T is tagged null record;

private

  procedure P_Private (X : in out T) is null;

end Private3;
-- { dg-do compile }

generic

  type Ext is new T with private;

package Private3.Child is

  procedure P_Private (X : in out Ext) is null;

end Private3.Child;

Reply via email to