From: Viljar Indus <[email protected]>
The Check_Ghost_Equality_Op predicate was checking the type directly
instead of its underlying type, so a limited private type whose full
view is a non-limited record was incorrectly bypassing the check.
Additionally, the check was never deferred to Process_Full_View, so
equality operators declared in the visible part of a package were
not re-checked once the full view became available.
gcc/ada/ChangeLog:
* ghost.adb (Check_Ghost_Equality_Op): Use Underlying_Type to
look through the private view before checking Is_Record_Type and
Is_Limited_Record.
* sem_ch3.adb (Process_Full_View): After completing the full view,
re-check any primitive equality operators on the private type
against SPARK RM 6.9(23) via Check_Ghost_Equality_Op.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/ghost.adb | 10 +++++++++-
gcc/ada/sem_ch3.adb | 21 +++++++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/gcc/ada/ghost.adb b/gcc/ada/ghost.adb
index a87d044524b..afa6b97947f 100644
--- a/gcc/ada/ghost.adb
+++ b/gcc/ada/ghost.adb
@@ -1072,12 +1072,20 @@ package body Ghost is
-----------------------------
procedure Check_Ghost_Equality_Op (Eq_Op : Entity_Id; Typ : Entity_Id) is
+ Underlying : constant Entity_Id := Underlying_Type (Typ);
begin
if not Is_Ghost_Entity (Eq_Op) then
return;
end if;
- if not Is_Record_Type (Typ) or else Is_Limited_Record (Typ) then
+ -- Look through any private view to get the underlying record type,
+ -- since a limited private type whose full view is a non-limited record
+ -- does not have "only limited views" and must be checked.
+
+ if No (Underlying)
+ or else not Is_Record_Type (Underlying)
+ or else Is_Limited_Record (Underlying)
+ then
return;
end if;
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 99799431d87..bc02601fe0c 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -22515,6 +22515,27 @@ package body Sem_Ch3 is
(Underlying_Full_View (Full_T), Priv_T);
end if;
+ -- Now that the full view is known, check any primitive equality
+ -- operators declared in the visible part against SPARK RM 6.9(23).
+ -- This check is deferred from Check_For_Primitive_Subprogram because
+ -- the full view of a private type is not available when the operator
+ -- is declared in the visible part of the package.
+
+ if Has_Primitive_Operations (Priv_T) then
+ declare
+ Prim : Elmt_Id := First_Elmt (Primitive_Operations (Priv_T));
+ Op : Entity_Id;
+ begin
+ while Present (Prim) loop
+ Op := Node (Prim);
+ if Chars (Op) = Name_Op_Eq then
+ Check_Ghost_Equality_Op (Op, Priv_T);
+ end if;
+ Next_Elmt (Prim);
+ end loop;
+ end;
+ end if;
+
<<Leave>>
Restore_Ghost_Region (Saved_Ghost_Config);
end Process_Full_View;
--
2.53.0