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(-)
@@ -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;
@@ -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;