[COMMITTED,07/26] ada: Reject illegal uses of type/subtype current instance

Message ID 20240802071210.413366-7-poulhies@adacore.com
State Committed
Commit e2fe0b18a66aafdd489ba9dbf148794906732f64
Headers
Series [COMMITTED,01/26] ada: Fix detection of suspicious loop patterns |

Commit Message

Marc Poulhiès Aug. 2, 2024, 7:11 a.m. UTC
  From: Steve Baird <baird@adacore.com>

The current instance of a type or subtype (see RM 8.6) is an object or
value, not a type or subtype. So a name denoting such a current instance is
illegal in any context that requires a name denoting a type or subtype.
In some cases this error was not detected.

gcc/ada/

	* sem_ch8.adb (Find_Type): If Is_Current_Instance returns True for
	N (and Comes_From_Source (N) is also True) then flag an error.
	Call Is_Current_Instance (twice) instead of duplicating (twice)
	N_Access_Definition-related code in Is_Current_Instance.
	* sem_util.adb (Is_Current_Instance): Implement
	access-type-related clauses of the RM 8.6 current instance rule.
	For pragmas Predicate and Predicate_Failure, distinguish between
	the first and subsequent pragma arguments.

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

---
 gcc/ada/sem_ch8.adb  | 24 ++++++++++++++----------
 gcc/ada/sem_util.adb | 31 ++++++++++++++++++++++++++++++-
 2 files changed, 44 insertions(+), 11 deletions(-)
  

Patch

diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index d2752af320e..c77a69e5118 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -8801,6 +8801,16 @@  package body Sem_Ch8 is
             Error_Msg_NE ("\\found & declared#", N, T_Name);
             Set_Entity (N, Any_Type);
 
+         elsif Is_Current_Instance (N) and then Comes_From_Source (N) then
+            if Nkind (Parent (T_Name)) = N_Subtype_Declaration then
+               Error_Msg_N ("reference to current instance of subtype" &
+                            " does not denote a subtype (RM 8.6)", N);
+            else
+               Error_Msg_N ("reference to current instance of type" &
+                            " does not denote a type (RM 8.6)", N);
+            end if;
+            Set_Entity (N, Any_Type);
+
          else
             --  If the type is an incomplete type created to handle
             --  anonymous access components of a record type, then the
@@ -8831,12 +8841,9 @@  package body Sem_Ch8 is
             if In_Open_Scopes (T_Name) then
                if Ekind (Base_Type (T_Name)) = E_Task_Type then
 
-                  --  In Ada 2005, a task name can be used in an access
-                  --  definition within its own body.
+                  --  OK if the "current instance" rule does not apply.
 
-                  if Ada_Version >= Ada_2005
-                    and then Nkind (Parent (N)) = N_Access_Definition
-                  then
+                  if not Is_Current_Instance (N) then
                      Set_Entity (N, T_Name);
                      Set_Etype  (N, T_Name);
                      return;
@@ -8849,12 +8856,9 @@  package body Sem_Ch8 is
 
                elsif Ekind (Base_Type (T_Name)) = E_Protected_Type then
 
-                  --  In Ada 2005, a protected name can be used in an access
-                  --  definition within its own body.
+                  --  OK if the "current instance" rule does not apply.
 
-                  if Ada_Version >= Ada_2005
-                    and then Nkind (Parent (N)) = N_Access_Definition
-                  then
+                  if not Is_Current_Instance (N) then
                      Set_Entity (N, T_Name);
                      Set_Etype  (N, T_Name);
                      return;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 032684f3ddb..7901eb8ee38 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -16080,6 +16080,29 @@  package body Sem_Util is
       P   : Node_Id;
 
    begin
+      --  Since Ada 2005, the "current instance" rule does not apply
+      --  to a type_mark in an access_definition (RM 8.6),
+      --  although it does apply in an access_to_object definition.
+      --  So the rule does not apply in the definition of an anonymous
+      --  access type, but it does apply in the definition of a named
+      --  access-to-object type.
+      --  The rule also does not apply in a designated subprogram profile.
+
+      if Ada_Version >= Ada_2005 then
+         case Nkind (Parent (N)) is
+            when N_Access_Definition | N_Access_Function_Definition =>
+               return False;
+            when N_Parameter_Specification =>
+               if Nkind (Parent (Parent (N))) in
+                 N_Access_To_Subprogram_Definition
+               then
+                  return False;
+               end if;
+            when others =>
+               null;
+         end case;
+      end if;
+
       --  Simplest case: entity is a concurrent type and we are currently
       --  inside the body. This will eventually be expanded into a call to
       --  Self (for tasks) or _object (for protected objects).
@@ -16129,6 +16152,12 @@  package body Sem_Util is
             elsif Nkind (P) = N_Pragma
               and then Get_Pragma_Id (P) in Pragma_Predicate
                                           | Pragma_Predicate_Failure
+
+              --  For "pragma Predicate (T, Is_OK (T))", return False for the
+              --  first use of T and True for the second.
+
+              and then
+                N /= Expression (First (Pragma_Argument_Associations (P)))
             then
                declare
                   Arg : constant Entity_Id :=
@@ -16144,7 +16173,7 @@  package body Sem_Util is
          end loop;
       end if;
 
-      --  In any other context this is not a current occurrence
+      --  In any other context this is not a current instance reference.
 
       return False;
    end Is_Current_Instance;