with Inline; use Inline;
with Lib; use Lib;
with Lib.Load; use Lib.Load;
-with Lib.Xref;
with Live; use Live;
with Namet; use Namet;
with Nlists; use Nlists;
-- Output waiting warning messages
- Lib.Xref.Process_Deferred_References;
Sem_Warn.Output_Non_Modified_In_Out_Warnings;
Sem_Warn.Output_Unreferenced_Messages;
Sem_Warn.Check_Unused_Withs;
-- Declarations --
------------------
- package Deferred_References is new Table.Table (
- Table_Component_Type => Deferred_Reference_Entry,
- Table_Index_Type => Int,
- Table_Low_Bound => 0,
- Table_Initial => 512,
- Table_Increment => 200,
- Table_Name => "Name_Deferred_References");
-
-- The Xref table is used to record references. The Loc field is set
-- to No_Location for a definition entry.
end if;
end Add_Entry;
- ---------------------
- -- Defer_Reference --
- ---------------------
-
- procedure Defer_Reference (Deferred_Reference : Deferred_Reference_Entry) is
- begin
- -- If Get_Ignore_Errors, then we are in Preanalyze_Without_Errors, and
- -- we should not record cross references, because that will cause
- -- duplicates when we call Analyze.
-
- if not Get_Ignore_Errors then
- Deferred_References.Append (Deferred_Reference);
- end if;
- end Defer_Reference;
-
-----------
-- Equal --
-----------
return E;
end Get_Key;
- ----------------------------
- -- Has_Deferred_Reference --
- ----------------------------
-
- function Has_Deferred_Reference (Ent : Entity_Id) return Boolean is
- begin
- for J in Deferred_References.First .. Deferred_References.Last loop
- if Deferred_References.Table (J).E = Ent then
- return True;
- end if;
- end loop;
-
- return False;
- end Has_Deferred_Reference;
-
----------
-- Hash --
----------
end Output_Refs;
end Output_References;
- ---------------------------------
- -- Process_Deferred_References --
- ---------------------------------
-
- procedure Process_Deferred_References is
- begin
- for J in Deferred_References.First .. Deferred_References.Last loop
- declare
- D : Deferred_Reference_Entry renames Deferred_References.Table (J);
-
- begin
- case Known_To_Be_Assigned (D.N) is
- when True =>
- Generate_Reference (D.E, D.N, 'm');
-
- when False =>
- Generate_Reference (D.E, D.N, 'r');
-
- end case;
- end;
- end loop;
-
- -- Clear processed entries from table
-
- Deferred_References.Init;
- end Process_Deferred_References;
-
-- Start of elaboration for Lib.Xref
begin
-- Export at line 4, that its body is exported to C, and that the link name
-- as given in the pragma is "here".
- -------------------------
- -- Deferred_References --
- -------------------------
-
- -- Normally we generate references as we go along, but as discussed in
- -- Sem_Util.Is_LHS, and Sem_Ch8.Find_Direct_Name/Find_Selected_Component,
- -- we have one case where that is tricky, which is when we have something
- -- like X.A := 3, where we don't know until we know the type of X whether
- -- this is a reference (if X is an access type, so what we really have is
- -- X.all.A := 3) or a modification, where X is not an access type.
-
- -- What we do in such cases is to gather nodes, where we would have liked
- -- to call Generate_Reference but we couldn't because we didn't know enough
- -- into a table, then we deal with generating references later on when we
- -- have sufficient information to do it right.
-
- type Deferred_Reference_Entry is record
- E : Entity_Id;
- N : Node_Id;
- end record;
- -- One entry, E, N are as required for Generate_Reference call
-
- procedure Defer_Reference (Deferred_Reference : Deferred_Reference_Entry);
- -- Add one entry to the deferred reference table
-
- procedure Process_Deferred_References;
- -- This procedure is called from Frontend to process these table entries.
- -- It is also called from Sem_Warn.
-
- function Has_Deferred_Reference (Ent : Entity_Id) return Boolean;
- -- Determine whether arbitrary entity Ent has a pending reference in order
- -- to suppress premature warnings about useless assignments. See comments
- -- in Analyze_Assignment in sem_ch5.adb.
-
-----------------------------
-- SPARK Xrefs Information --
-----------------------------
-- If the current scope is a subprogram, entry or task body or declare
-- block then this is the right place to check for hanging useless
-- assignments from the statement sequence. Skip this in the body of a
- -- postcondition, since in that case there are no source references, and
- -- we need to preserve deferred references from the enclosing scope.
+ -- postcondition, since in that case there are no source references.
if (Is_Subprogram_Or_Entry (Current_Scope)
and then Chars (Current_Scope) /= Name_uPostconditions)
-- There may have been a previous reference to a component of
-- the variable, which in general removes the Last_Assignment
-- field of the variable to indicate a relevant use of the
- -- previous assignment. However, if the assignment is to a
- -- subcomponent the reference may not have registered, because
- -- it is not possible to determine whether the context is an
- -- assignment. In those cases we generate a Deferred_Reference,
- -- to be used at the end of compilation to generate the right
- -- kind of reference, and we suppress a potential warning for
- -- a useless assignment, which might be premature. This may
- -- lose a warning in rare cases, but seems preferable to a
- -- misleading warning.
+ -- previous assignment.
if Warn_On_Modified_Unread
and then Is_Assignable (Ent)
and then Comes_From_Source (N)
and then In_Extended_Main_Source_Unit (Ent)
- and then not Has_Deferred_Reference (Ent)
and then not Has_Target_Names (N)
then
Warn_On_Useless_Assignment (Ent, N);
else
T := Etype (P);
-
- -- If the prefix is an entity it may have a deferred reference set
- -- during analysis of the selected component. After resolution we
- -- can transform it into a proper reference. This prevents spurious
- -- warnings on useless assignments when the same selected component
- -- is the actual for an out parameter in a subsequent call.
-
- if Is_Entity_Name (P)
- and then Has_Deferred_Reference (Entity (P))
- then
- if Known_To_Be_Assigned (N) then
- Generate_Reference (Entity (P), P, 'm');
- else
- Generate_Reference (Entity (P), P, 'r');
- end if;
- end if;
end if;
-- Set flag for expander if discriminant check required on a component
return;
-- An actual that is the prefix in a prefixed call may have
- -- been rewritten in the call, after the deferred reference
- -- was collected. Check if sloc and kinds and names match.
+ -- been rewritten in the call. Check if sloc and kinds and
+ -- names match.
elsif Sloc (Actual) = Sloc (N)
and then Nkind (Actual) = N_Identifier
with Errout; use Errout;
with Exp_Code; use Exp_Code;
with Lib; use Lib;
-with Lib.Xref; use Lib.Xref;
with Namet; use Namet;
with Nlists; use Nlists;
with Opt; use Opt;
-- Start of processing for Check_References
begin
- Process_Deferred_References;
-
-- No messages if warnings are suppressed, or if we have detected any
-- real errors so far (this last check avoids junk messages resulting
-- from errors, e.g. a subunit that is not loaded).
return;
end if;
- Process_Deferred_References;
-
-- Flag any unused with clauses. For a subunit, check only the units
-- in its context, not those of the parent, which may be needed by other
-- subunits. We will get the full warnings when we compile the parent,
Ent : Entity_Id;
begin
- Process_Deferred_References;
-
if Warn_On_Modified_Unread
and then In_Extended_Main_Source_Unit (E)
then