From 4e8310b33c37d1eaaa4ffd08aca404a787252cf5 Mon Sep 17 00:00:00 2001
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Mon, 9 May 2022 08:56:27 +0200
Subject: [PATCH] [Ada] Do not freeze subprogram body without spec too early

This fixes a small oddity whereby a subprogram body declared without a spec
would be frozen before its entity is fully processed as an overloaded name.
Now the latter step computes useful information, for example whether the
body is a (late) primitive of a tagged type, which can be required during
the freezing process.  The change also adjusts Check_Dispatching_Operation
accordingly.  No functional changes.

gcc/ada/

	* sem_ch6.adb (Analyze_Subprogram_Body_Helper): For the case where
	there is no previous declaration, freeze the body entity only after
	it has been processed as a new overloaded name.
	Use Was_Expression_Function to recognize expression functions.
	* sem_disp.adb (Check_Dispatching_Operation): Do not require a body
	which is the last primitive to be frozen here.
---
 gcc/ada/sem_ch6.adb  | 43 ++++++++++++++++++++++++-------------------
 gcc/ada/sem_disp.adb |  5 ++---
 2 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 5a3692cc9145..cfe396ec1dd7 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -4389,25 +4389,15 @@ package body Sem_Ch6 is
             end if;
 
             --  A subprogram body should cause freezing of its own declaration,
-            --  but if there was no previous explicit declaration, then the
-            --  subprogram will get frozen too late (there may be code within
-            --  the body that depends on the subprogram having been frozen,
-            --  such as uses of extra formals), so we force it to be frozen
-            --  here. Same holds if the body and spec are compilation units.
-            --  Finally, if the return type is an anonymous access to protected
-            --  subprogram, it must be frozen before the body because its
-            --  expansion has generated an equivalent type that is used when
-            --  elaborating the body.
-
-            --  An exception in the case of Ada 2012, AI05-177: The bodies
-            --  created for expression functions do not freeze.
-
-            if No (Spec_Id)
-              and then Nkind (Original_Node (N)) /= N_Expression_Function
+            --  so, if the body and spec are compilation units, we must do it
+            --  manually here. Moreover, if the return type is anonymous access
+            --  to protected subprogram, it must be frozen before the body
+            --  because its expansion has generated an equivalent type that is
+            --  used when elaborating the body.
+
+            if Present (Spec_Id)
+              and then Nkind (Parent (N)) = N_Compilation_Unit
             then
-               Freeze_Before (N, Body_Id);
-
-            elsif Nkind (Parent (N)) = N_Compilation_Unit then
                Freeze_Before (N, Spec_Id);
 
             elsif Is_Access_Subprogram_Type (Etype (Body_Id)) then
@@ -4775,13 +4765,28 @@ package body Sem_Ch6 is
 
            --  No warnings for expression functions
 
-           and then Nkind (Original_Node (N)) /= N_Expression_Function
+           and then (Nkind (N) /= N_Subprogram_Body
+                      or else not Was_Expression_Function (N))
          then
             Style.Body_With_No_Spec (N);
          end if;
 
          New_Overloaded_Entity (Body_Id);
 
+         --  A subprogram body should cause freezing of its own declaration,
+         --  but if there was no previous explicit declaration, then the
+         --  subprogram will get frozen too late (there may be code within
+         --  the body that depends on the subprogram having been frozen,
+         --  such as uses of extra formals), so we force it to be frozen here.
+         --  An exception in Ada 2012 is that the body created for expression
+         --  functions does not freeze.
+
+         if Nkind (N) /= N_Subprogram_Body
+           or else not Was_Expression_Function (N)
+         then
+            Freeze_Before (N, Body_Id);
+         end if;
+
          if Nkind (N) /= N_Subprogram_Body_Stub then
             Set_Acts_As_Spec (N);
             Generate_Definition (Body_Id);
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 79af10a81f05..d5893914f275 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -1516,11 +1516,10 @@ package body Sem_Disp is
                        ("\spec should appear immediately after the type!",
                         Subp);
 
-                  elsif Is_Frozen (Subp) then
+                  else
 
                      --  The subprogram body declares a primitive operation.
-                     --  If the subprogram is already frozen, we must update
-                     --  its dispatching information explicitly here. The
+                     --  We must update its dispatching information here. The
                      --  information is taken from the overridden subprogram.
                      --  We must also generate a cross-reference entry because
                      --  references to other primitives were already created
-- 
GitLab