aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_util.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_util.adb')
-rw-r--r--gcc/ada/sem_util.adb175
1 files changed, 175 insertions, 0 deletions
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 15e6a64..d2d8a41 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -8324,6 +8324,181 @@ package body Sem_Util is
Is_RTE (Root_Type (Under), RO_WW_Super_String));
end Is_Bounded_String;
+ -------------------------
+ -- Is_Child_Or_Sibling --
+ -------------------------
+
+ function Is_Child_Or_Sibling
+ (Pack_1 : Entity_Id;
+ Pack_2 : Entity_Id;
+ Private_Child : Boolean) return Boolean
+ is
+ function Distance_From_Standard (Pack : Entity_Id) return Nat;
+ -- Given an arbitrary package, return the number of "climbs" necessary
+ -- to reach scope Standard_Standard.
+
+ procedure Equalize_Depths
+ (Pack : in out Entity_Id;
+ Depth : in out Nat;
+ Depth_To_Reach : Nat);
+ -- Given an arbitrary package, its depth and a target depth to reach,
+ -- climb the scope chain until the said depth is reached. The pointer
+ -- to the package and its depth a modified during the climb.
+
+ function Is_Child (Pack : Entity_Id) return Boolean;
+ -- Given a package Pack, determine whether it is a child package that
+ -- satisfies the privacy requirement (if set).
+
+ ----------------------------
+ -- Distance_From_Standard --
+ ----------------------------
+
+ function Distance_From_Standard (Pack : Entity_Id) return Nat is
+ Dist : Nat;
+ Scop : Entity_Id;
+
+ begin
+ Dist := 0;
+ Scop := Pack;
+ while Present (Scop) and then Scop /= Standard_Standard loop
+ Dist := Dist + 1;
+ Scop := Scope (Scop);
+ end loop;
+
+ return Dist;
+ end Distance_From_Standard;
+
+ ---------------------
+ -- Equalize_Depths --
+ ---------------------
+
+ procedure Equalize_Depths
+ (Pack : in out Entity_Id;
+ Depth : in out Nat;
+ Depth_To_Reach : Nat)
+ is
+ begin
+ -- The package must be at a greater or equal depth
+
+ if Depth < Depth_To_Reach then
+ raise Program_Error;
+ end if;
+
+ -- Climb the scope chain until the desired depth is reached
+
+ while Present (Pack) and then Depth /= Depth_To_Reach loop
+ Pack := Scope (Pack);
+ Depth := Depth - 1;
+ end loop;
+ end Equalize_Depths;
+
+ --------------
+ -- Is_Child --
+ --------------
+
+ function Is_Child (Pack : Entity_Id) return Boolean is
+ begin
+ if Is_Child_Unit (Pack) then
+ if Private_Child then
+ return Is_Private_Descendant (Pack);
+ else
+ return True;
+ end if;
+
+ -- The package is nested, it cannot act a child or a sibling
+
+ else
+ return False;
+ end if;
+ end Is_Child;
+
+ -- Local variables
+
+ P_1 : Entity_Id := Pack_1;
+ P_1_Child : Boolean := False;
+ P_1_Depth : Nat := Distance_From_Standard (P_1);
+ P_2 : Entity_Id := Pack_2;
+ P_2_Child : Boolean := False;
+ P_2_Depth : Nat := Distance_From_Standard (P_2);
+
+ -- Start of processing for Is_Child_Or_Sibling
+
+ begin
+ pragma Assert
+ (Ekind (Pack_1) = E_Package and then Ekind (Pack_2) = E_Package);
+
+ -- Both packages denote the same entity, therefore they cannot be
+ -- children or siblings.
+
+ if P_1 = P_2 then
+ return False;
+
+ -- One of the packages is at a deeper level than the other. Note that
+ -- both may still come from differen hierarchies.
+
+ -- (root) P_2
+ -- / \ :
+ -- X P_2 or X
+ -- : :
+ -- P_1 P_1
+
+ elsif P_1_Depth > P_2_Depth then
+ Equalize_Depths (P_1, P_1_Depth, P_2_Depth);
+ P_1_Child := True;
+
+ -- (root) P_1
+ -- / \ :
+ -- P_1 X or X
+ -- : :
+ -- P_2 P_2
+
+ elsif P_2_Depth > P_1_Depth then
+ Equalize_Depths (P_2, P_2_Depth, P_1_Depth);
+ P_2_Child := True;
+ end if;
+
+ -- At this stage the package pointers have been elevated to the same
+ -- depth. If the related entities are the same, then one package is a
+ -- potential child of the other:
+
+ -- P_1
+ -- :
+ -- X became P_1 P_2 or vica versa
+ -- :
+ -- P_2
+
+ if P_1 = P_2 then
+ if P_1_Child then
+ return Is_Child (Pack_1);
+ else pragma Assert (P_2_Child);
+ return Is_Child (Pack_2);
+ end if;
+
+ -- The packages may come from the same package chain or from entirely
+ -- different hierarcies. To determine this, climb the scope stack until
+ -- a common root is found.
+
+ -- (root) (root 1) (root 2)
+ -- / \ | |
+ -- P_1 P_2 P_1 P_2
+
+ else
+ while Present (P_1) and then Present (P_2) loop
+
+ -- The two packages may be siblings
+
+ if P_1 = P_2 then
+ return Is_Child (Pack_1) and then Is_Child (Pack_2);
+ end if;
+
+ P_1 := Scope (P_1);
+ P_2 := Scope (P_2);
+ end loop;
+ end if;
+
+ return False;
+ end Is_Child_Or_Sibling;
+
-----------------------------
-- Is_Concurrent_Interface --
-----------------------------