===================================================================
@@ -34,6 +34,7 @@
with Fname; use Fname;
with Fname.UF; use Fname.UF;
with Freeze; use Freeze;
+with Ghost; use Ghost;
with Impunit; use Impunit;
with Inline; use Inline;
with Lib; use Lib;
@@ -2826,6 +2827,8 @@
Set_Fatal_Error (Current_Sem_Unit, Error_Ignored);
end if;
end case;
+
+ Mark_Ghost_Clause (N);
end Analyze_With_Clause;
------------------------------
===================================================================
@@ -1430,6 +1430,34 @@
end Mark_Ghost_Declaration_Or_Body;
-----------------------
+ -- Mark_Ghost_Clause --
+ -----------------------
+
+ procedure Mark_Ghost_Clause (N : Node_Id) is
+ Nam : Node_Id := Empty;
+
+ begin
+ if Nkind (N) = N_Use_Package_Clause then
+ Nam := First (Names (N));
+
+ elsif Nkind (N) = N_Use_Type_Clause then
+ Nam := First (Subtype_Marks (N));
+
+ elsif Nkind (N) = N_With_Clause then
+ Nam := Name (N);
+ end if;
+
+ if Present (Nam)
+ and then Is_Entity_Name (Nam)
+ and then Present (Entity (Nam))
+ and then Is_Ignored_Ghost_Entity (Entity (Nam))
+ then
+ Set_Is_Ignored_Ghost_Node (N);
+ Propagate_Ignored_Ghost_Code (N);
+ end if;
+ end Mark_Ghost_Clause;
+
+ -----------------------
-- Mark_Ghost_Pragma --
-----------------------
@@ -1574,10 +1602,17 @@
Id : Entity_Id;
begin
+ -- Do not prune compilation unit nodes because many mechanisms
+ -- depend on their presence. Note that context items must still
+ -- be processed.
+
+ if Nkind (N) = N_Compilation_Unit then
+ return OK;
+
-- The node is either declared as ignored Ghost or is a byproduct
-- of expansion. Destroy it and stop the traversal on this branch.
- if Is_Ignored_Ghost_Node (N) then
+ elsif Is_Ignored_Ghost_Node (N) then
Prune (N);
return Skip;
@@ -1628,7 +1663,7 @@
begin
for Index in Ignored_Ghost_Units.First .. Ignored_Ghost_Units.Last loop
- Prune_Tree (Unit (Ignored_Ghost_Units.Table (Index)));
+ Prune_Tree (Ignored_Ghost_Units.Table (Index));
end loop;
end Remove_Ignored_Ghost_Code;
===================================================================
@@ -183,6 +183,11 @@
-- prior to processing the procedure call. This routine starts a Ghost
-- region and must be used in conjunction with Restore_Ghost_Mode.
+ procedure Mark_Ghost_Clause (N : Node_Id);
+ -- Mark use package, use type, or with clause N as Ghost when:
+ --
+ -- * The clause mentions a Ghost entity
+
procedure Mark_Ghost_Pragma
(N : Node_Id;
Id : Entity_Id);
===================================================================
@@ -3616,11 +3616,11 @@
-- within the package itself, ignore it.
procedure Analyze_Use_Package (N : Node_Id) is
+ Ghost_Id : Entity_Id := Empty;
+ Living_Id : Entity_Id := Empty;
+ Pack : Entity_Id;
Pack_Name : Node_Id;
- Pack : Entity_Id;
- -- Start of processing for Analyze_Use_Package
-
begin
Check_SPARK_05_Restriction ("use clause is not allowed", N);
@@ -3664,8 +3664,8 @@
if Entity (Pref) = Standard_Standard then
Error_Msg_N
- ("predefined package Standard cannot appear"
- & " in a context clause", Pref);
+ ("predefined package Standard cannot appear in a context "
+ & "clause", Pref);
end if;
end;
end if;
@@ -3673,8 +3673,8 @@
Next (Pack_Name);
end loop;
- -- Loop through package names to mark all entities as potentially
- -- use visible.
+ -- Loop through package names to mark all entities as potentially use
+ -- visible.
Pack_Name := First (Names (N));
while Present (Pack_Name) loop
@@ -3710,6 +3710,21 @@
if Applicable_Use (Pack_Name) then
Use_One_Package (Pack, N);
end if;
+
+ -- Capture the first Ghost package and the first living package
+
+ if Is_Entity_Name (Pack_Name) then
+ Pack := Entity (Pack_Name);
+
+ if Is_Ghost_Entity (Pack) then
+ if No (Ghost_Id) then
+ Ghost_Id := Pack;
+ end if;
+
+ elsif No (Living_Id) then
+ Living_Id := Pack;
+ end if;
+ end if;
end if;
-- Report error because name denotes something other than a package
@@ -3720,6 +3735,25 @@
Next (Pack_Name);
end loop;
+
+ -- Detect a mixture of Ghost packages and living packages within the
+ -- same use package clause. Ideally one would split a use package clause
+ -- with multiple names into multiple use package clauses with a single
+ -- name, however clients of the front end would have to adapt to this
+ -- change.
+
+ if Present (Ghost_Id) and then Present (Living_Id) then
+ Error_Msg_N
+ ("use clause cannot mention ghost and non-ghost ghost units", N);
+
+ Error_Msg_Sloc := Sloc (Ghost_Id);
+ Error_Msg_NE ("\& # declared as ghost", N, Ghost_Id);
+
+ Error_Msg_Sloc := Sloc (Living_Id);
+ Error_Msg_NE ("\& # declared as non-ghost", N, Living_Id);
+ end if;
+
+ Mark_Ghost_Clause (N);
end Analyze_Use_Package;
----------------------
@@ -3727,8 +3761,10 @@
----------------------
procedure Analyze_Use_Type (N : Node_Id) is
- E : Entity_Id;
- Id : Node_Id;
+ E : Entity_Id;
+ Ghost_Id : Entity_Id := Empty;
+ Id : Node_Id;
+ Living_Id : Entity_Id := Empty;
begin
Set_Hidden_By_Use_Clause (N, No_Elist);
@@ -3834,8 +3870,37 @@
end if;
end if;
+ -- Capture the first Ghost type and the first living type
+
+ if Is_Ghost_Entity (E) then
+ if No (Ghost_Id) then
+ Ghost_Id := E;
+ end if;
+
+ elsif No (Living_Id) then
+ Living_Id := E;
+ end if;
+
Next (Id);
end loop;
+
+ -- Detect a mixture of Ghost types and living types within the same use
+ -- type clause. Ideally one would split a use type clause with multiple
+ -- marks into multiple use type clauses with a single mark, however
+ -- clients of the front end will have to adapt to this change.
+
+ if Present (Ghost_Id) and then Present (Living_Id) then
+ Error_Msg_N
+ ("use clause cannot mention ghost and non-ghost ghost types", N);
+
+ Error_Msg_Sloc := Sloc (Ghost_Id);
+ Error_Msg_NE ("\& # declared as ghost", N, Ghost_Id);
+
+ Error_Msg_Sloc := Sloc (Living_Id);
+ Error_Msg_NE ("\& # declared as non-ghost", N, Living_Id);
+ end if;
+
+ Mark_Ghost_Clause (N);
end Analyze_Use_Type;
--------------------