]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Follow up fixes for Put_Image/streaming regressions
authorSteve Baird <baird@adacore.com>
Sat, 17 Feb 2024 01:05:09 +0000 (17:05 -0800)
committerMarc Poulhiès <poulhies@adacore.com>
Thu, 16 May 2024 08:49:28 +0000 (10:49 +0200)
A recent change to reduce duplication of compiler-generated Put_Image and
streaming subprograms introduced some regressions. The fix for one of them
was incomplete.

gcc/ada/

* exp_attr.adb (Build_And_Insert_Type_Attr_Subp): Further tweaking
of the point where a compiler-generated Put_Image or streaming
subprogram is to be inserted in the tree. If one such subprogram
calls another (as is often the case with, for example, Put_Image
procedures for composite type and for a component type thereof),
then we want to avoid use-before-definition problems that can
result from inserting the caller ahead of the callee.

gcc/ada/exp_attr.adb

index e12e8b4a439af34d2c335ee775337f9f2e5b4d05..03bf4cf329c3c3d4c51fa65099e24314929c6caa 100644 (file)
@@ -1954,6 +1954,44 @@ package body Exp_Attr is
             while Present (Ancestor) loop
                if Is_List_Member (Ancestor) then
                   Insertion_Point := First (List_Containing (Ancestor));
+
+                  --  A hazard to avoid here is use-before-definition
+                  --  errors that can result when we have two of these
+                  --  subprograms where one calls the other (e.g., given
+                  --  Put_Image procedures for a composite type and
+                  --  for a component type, the former will often call
+                  --  the latter). At the time a subprogram is inserted,
+                  --  we know that the one and only call to it is
+                  --  somewhere in the subtree rooted at Ancestor.
+                  --  So that placement constraint is easy to satisfy.
+                  --  But if we construct another subprogram later and
+                  --  if that second subprogram calls the first one,
+                  --  then we need to be careful not to place the
+                  --  second one ahead of the first one. That is the goal
+                  --  of this loop. This may need to be revised if it turns
+                  --  out that other stuff is being inserted on the list,
+                  --  so that the loop terminates too early.
+
+                  --  On the other hand, it seems like inserting things
+                  --  earlier offers more opportunities for sharing.
+                  --  If Ancestor occurs in the statement list of a
+                  --  subprogram body (ignore the HSS node for now),
+                  --  then perhaps we should look for an insertion site
+                  --  in the decl list of the subprogram body and only
+                  --  look in the statement list if the decl list is empty.
+                  --  Similarly if Ancestor occors in the private decls list
+                  --  for a package spec that has a non-empty visible
+                  --  decls list. No examples where this would result in more
+                  --  sharing and less duplication have been observed, so this
+                  --  is just speculation.
+
+                  while Insertion_Point /= Ancestor
+                    and then Nkind (Insertion_Point) = N_Subprogram_Body
+                    and then not Comes_From_Source (Insertion_Point)
+                  loop
+                     Next (Insertion_Point);
+                  end loop;
+
                   pragma Assert (Present (Insertion_Point));
                end if;
                Ancestor := Parent (Ancestor);