[COMMITTED,45/51] ada: Adjust RESULT_DECL of functions after updating their profile if needed

Message ID 20260602084541.3829876-45-poulhies@adacore.com
State Committed
Headers
Series [COMMITTED,01/51] ada: Rename Private_Component function |

Commit Message

Marc Poulhiès June 2, 2026, 8:45 a.m. UTC
  From: Eric Botcazou <ebotcazou@adacore.com>

Adjusting the RESULT_DECL of functions is necessary before handing them over
to the middle-end when they return by invisible reference and are defined in
the current translation unit, so that's done in Subprogram_Body_to_gnu.

That's also needed when the functions are generated by the middle-end, like
GNU thunks.  But, in this case, the transformation can only be applied when
the full view of the type is available, which is not guaranteed by the time
maybe_make_gnu_thunk is invoked, so the transformation needs to be delayed
and applied by update_profile when the full view is eventually encountered.

gcc/ada/ChangeLog:

	PR ada/89609
	* gcc-interface/gigi.h (adjust_result_decl_for_invisible_reference):
	New inline function.
	* gcc-interface/decl.cc (update_profile): Adjust the RESULT_DECL of
	the function if it returns by invisible reference.
	* gcc-interface/trans.cc (Subprogram_Body_to_gnu): Replace manual
	adjustment by a call to adjust_result_decl_for_invisible_reference.
	(maybe_make_gnu_thunk): Likewise.
	* gcc-interface/targtyps.cc: Include stor-layout.h header file.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/gcc-interface/decl.cc     |  3 +++
 gcc/ada/gcc-interface/gigi.h      | 24 ++++++++++++++++++++++++
 gcc/ada/gcc-interface/targtyps.cc |  1 +
 gcc/ada/gcc-interface/trans.cc    | 25 ++++---------------------
 4 files changed, 32 insertions(+), 21 deletions(-)
  

Patch

diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc
index 7f39113186f..d9b70019c4a 100644
--- a/gcc/ada/gcc-interface/decl.cc
+++ b/gcc/ada/gcc-interface/decl.cc
@@ -6018,6 +6018,9 @@  update_profile (Entity_Id gnat_subprog)
 
       DECL_ARGUMENTS (gnu_subprog) = gnu_param_list;
       finish_subprog_decl (gnu_subprog, gnu_ext_name, gnu_type);
+
+      /* If the function returns by invisible reference, make it explicit.  */
+      adjust_result_decl_for_invisible_reference (gnu_subprog);
     }
 }
 
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 793d7145b5e..f4d79119518 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -1208,6 +1208,30 @@  return_type_with_variable_size_p (tree type)
   return false;
 }
 
+/* Adjust RESULT_DECL of a function that returns by invisible reference.
+
+   Adjusting the RESULT_DECL of functions is needed before handing them over
+   to the middle-end when they return by invisible reference and are defined
+   in the current translation unit, which is done in Subprogram_Body_to_gnu.
+
+   That's also needed when the functions are generated by the middle-end, like
+   GNU thunks.  But, in this case, the transformation can only be applied when
+   the full view of the type is available, which is not guaranteed by the time
+   maybe_make_gnu_thunk is invoked, so the transformation needs to be delayed
+   and applied by update_profile when the full view is eventually seen.  */
+
+static inline void
+adjust_result_decl_for_invisible_reference (tree subprog)
+{
+  if (TREE_ADDRESSABLE (TREE_TYPE (subprog))
+      && TREE_CODE (TREE_TYPE (DECL_RESULT (subprog))) != REFERENCE_TYPE)
+    {
+      TREE_TYPE (DECL_RESULT (subprog))
+	= build_reference_type (TREE_TYPE (DECL_RESULT (subprog)));
+      relayout_decl (DECL_RESULT (subprog));
+    }
+}
+
 /* Return the unsigned version of TYPE_NODE, a scalar type.  */
 
 static inline tree
diff --git a/gcc/ada/gcc-interface/targtyps.cc b/gcc/ada/gcc-interface/targtyps.cc
index 4fc97cfb3fd..4768322e15a 100644
--- a/gcc/ada/gcc-interface/targtyps.cc
+++ b/gcc/ada/gcc-interface/targtyps.cc
@@ -31,6 +31,7 @@ 
 #include "tm.h"
 #include "target.h"
 #include "tree.h"
+#include "stor-layout.h"
 
 #include "ada.h"
 #include "types.h"
diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc
index 6eca5a49cd5..f66d0b99ba3 100644
--- a/gcc/ada/gcc-interface/trans.cc
+++ b/gcc/ada/gcc-interface/trans.cc
@@ -3995,17 +3995,8 @@  Subprogram_Body_to_gnu (Node_Id gnat_node)
   else
     gnu_return_var_elmt = NULL_TREE;
 
-  /* If the function returns by invisible reference, make it explicit in the
-     function body, but beware that maybe_make_gnu_thunk may already have done
-     it if the function is inlined across units.  See gnat_to_gnu_subprog_type
-     for more details.  */
-  if (TREE_ADDRESSABLE (gnu_subprog_type)
-      && TREE_CODE (TREE_TYPE (gnu_result_decl)) != REFERENCE_TYPE)
-    {
-      TREE_TYPE (gnu_result_decl)
-	= build_reference_type (TREE_TYPE (gnu_result_decl));
-      relayout_decl (gnu_result_decl);
-    }
+  /* If the function returns by invisible reference, make it explicit.  */
+  adjust_result_decl_for_invisible_reference (gnu_subprog);
 
   /* Set the line number in the decl to correspond to that of the body.  */
   if (DECL_IGNORED_P (gnu_subprog))
@@ -11514,16 +11505,8 @@  maybe_make_gnu_thunk (Entity_Id gnat_thunk, tree gnu_thunk)
       indirect_offset = (HOST_WIDE_INT) (POINTER_SIZE / BITS_PER_UNIT);
     }
 
-  /* If the target returns by invisible reference and is external, apply the
-     same transformation as Subprogram_Body_to_gnu here.  */
-  if (TREE_ADDRESSABLE (TREE_TYPE (gnu_target))
-      && DECL_EXTERNAL (gnu_target)
-      && TREE_CODE (TREE_TYPE (DECL_RESULT (gnu_target))) != REFERENCE_TYPE)
-    {
-      TREE_TYPE (DECL_RESULT (gnu_target))
-	= build_reference_type (TREE_TYPE (DECL_RESULT (gnu_target)));
-      relayout_decl (DECL_RESULT (gnu_target));
-    }
+  /* If the function returns by invisible reference, make it explicit.  */
+  adjust_result_decl_for_invisible_reference (gnu_target);
 
   /* The thunk expander requires the return types of thunk and target to be
      compatible, which is not fully the case with the CICO mechanism.  */