]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Fix missing dispatching for default implementation of S'Class'{Read,Write}
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 14 Apr 2026 18:52:00 +0000 (20:52 +0200)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Tue, 2 Jun 2026 08:42:27 +0000 (10:42 +0200)
Note that 'Output and 'Put_Image are also affected since they share a common
implementation with the others.

gcc/ada/ChangeLog:

PR ada/18205
* exp_attr.adb (Rewrite_Attribute_Proc_Call): Skip the conversion to
the formal type only if the actual is of a class-wide type. Generate
a dispatching call when both the prefix is a class-wide type and the
subprogram is a dispatching operation.
(Expand_N_Attribute_Reference) <Input>: Use U_Type consistently and
remove an useless invocation of Root_Type.
<Put_Image>: Minor comment tweak.
<Read>: Likewise.
<Write>: Likewise.

gcc/ada/exp_attr.adb

index 403b5899ce5e663c2ece4203bbb53356c2307601..b299dacebfc6ffe4e485968bb8ad15952714c879 100644 (file)
@@ -2233,6 +2233,8 @@ package body Exp_Attr is
          Formal_Typ : constant Entity_Id := Etype (Formal);
          Is_Written : constant Boolean   := Ekind (Formal) /= E_In_Parameter;
 
+         Call : Node_Id;
+
       begin
          --  The expansion depends on Item, the second actual, which is
          --  the object being streamed in or out.
@@ -2286,8 +2288,8 @@ package body Exp_Attr is
          --  operation is not inherited), we are all set, and can use the
          --  argument unchanged.
 
-         if not Is_Class_Wide_Type (Entity (Pref))
-           and then not Is_Class_Wide_Type (Etype (Item))
+         if not Is_Class_Wide_Type (Item_Typ)
+           and then not Is_Class_Wide_Type (Formal_Typ)
            and then Base_Type (Item_Typ) /= Base_Type (Formal_Typ)
          then
             --  Perform an unchecked conversion when either the argument or
@@ -2333,11 +2335,21 @@ package body Exp_Attr is
 
          --  And now rewrite the call
 
-         Rewrite (N,
-           Make_Procedure_Call_Statement (Loc,
-             Name                   => New_Occurrence_Of (Pname, Loc),
-             Parameter_Associations => Exprs));
+         Call := Make_Procedure_Call_Statement (Loc,
+           Name                   => New_Occurrence_Of (Pname, Loc),
+           Parameter_Associations => Exprs);
+
+         --  If the attribute has not been specified for a CW type, then we
+         --  must dispatch to the attribute of the specific type identified
+         --  by the tag of Item.
+
+         if Is_Class_Wide_Type (Entity (Pref))
+           and then Is_Dispatching_Operation (Pname)
+         then
+            Set_Controlling_Argument (Call, Item);
+         end if;
 
+         Rewrite (N, Call);
          Analyze (N);
       end Rewrite_Attribute_Proc_Call;
 
@@ -4951,9 +4963,9 @@ package body Exp_Attr is
 
             --  Dispatching case with class-wide type
 
-            elsif Is_Class_Wide_Type (P_Type) then
+            elsif Is_Class_Wide_Type (U_Type) then
 
-               if Is_Mutably_Tagged_Type (P_Type) then
+               if Is_Mutably_Tagged_Type (U_Type) then
 
                   --  In mutably tagged case, rewrite
                   --    T'Class'Input (Strm)
@@ -5003,7 +5015,7 @@ package body Exp_Attr is
                end if;
 
                Read_Controlling_Tag (P_Type, Cntrl);
-               Fname := Find_Prim_Op (Root_Type (P_Type), TSS_Stream_Input);
+               Fname := Find_Prim_Op (U_Type, TSS_Stream_Input);
 
             --  For tagged types, use the primitive Input function
 
@@ -6642,8 +6654,7 @@ package body Exp_Attr is
                end if;
 
             --  Tagged type case, use the primitive Put_Image function. Note
-            --  that this will dispatch in the class-wide case which is what we
-            --  want.
+            --  that this will dispatch in the class-wide case as required.
 
             elsif Is_Tagged_Type (U_Type) then
                Pname := Find_Optional_Prim_Op (U_Type, TSS_Put_Image);
@@ -7064,7 +7075,7 @@ package body Exp_Attr is
                end;
 
             --  Tagged type case, use the primitive Read function. Note that
-            --  this will dispatch in the class-wide case which is what we want
+            --  this will dispatch in the class-wide case as required.
 
             elsif Is_Tagged_Type (U_Type) then
 
@@ -8790,7 +8801,7 @@ package body Exp_Attr is
                end;
 
             --  Tagged type case, use the primitive Write function. Note that
-            --  this will dispatch in the class-wide case which is what we want
+            --  this will dispatch in the class-wide case as required.
 
             elsif Is_Tagged_Type (U_Type) then