sem_prag.adb: Revert unwanted change in previous commit, only keep message fix.
2016-06-22 Arnaud Charlet <charlet@adacore.com> * sem_prag.adb: Revert unwanted change in previous commit, only keep message fix. From-SVN: r237699
This commit is contained in:
parent
017d237ede
commit
d13ecc2dc7
@ -1,3 +1,8 @@
|
||||
2016-06-22 Arnaud Charlet <charlet@adacore.com>
|
||||
|
||||
* sem_prag.adb: Revert unwanted change in previous commit,
|
||||
only keep message fix.
|
||||
|
||||
2016-06-22 Ed Schonberg <schonberg@adacore.com>
|
||||
|
||||
* sem_prag.ads (Build_Classwide_Expression): new procedure to
|
||||
|
@ -44,7 +44,6 @@ with Exp_Dist; use Exp_Dist;
|
||||
with Exp_Util; use Exp_Util;
|
||||
with Freeze; use Freeze;
|
||||
with Ghost; use Ghost;
|
||||
with Gnatvsn; use Gnatvsn;
|
||||
with Lib; use Lib;
|
||||
with Lib.Writ; use Lib.Writ;
|
||||
with Lib.Xref; use Lib.Xref;
|
||||
@ -166,39 +165,39 @@ package body Sem_Prag is
|
||||
Table_Increment => 100,
|
||||
Table_Name => "Name_Externals");
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Handling of inherited classwide pre/postconditions --
|
||||
--------------------------------------------------------
|
||||
--------------------------------------------------------
|
||||
-- Handling of inherited classwide pre/postconditions --
|
||||
--------------------------------------------------------
|
||||
|
||||
-- Following AI12-0113, the expression for a classwide condition is
|
||||
-- transformed for a subprogram that inherits it, by replacing calls
|
||||
-- to primitive operations of the original controlling type into the
|
||||
-- corresponding overriding operations of the derived type. The following
|
||||
-- hash table manages this mapping, and is expanded on demand whenever
|
||||
-- such inherited expression needs to be constructed.
|
||||
-- Following AI12-0113, the expression for a classwide condition is
|
||||
-- transformed for a subprogram that inherits it, by replacing calls
|
||||
-- to primitive operations of the original controlling type into the
|
||||
-- corresponding overriding operations of the derived type. The following
|
||||
-- hash table manages this mapping, and is expanded on demand whenever
|
||||
-- such inherited expression needs to be constructed.
|
||||
|
||||
-- The mapping is also used to check whether an inherited operation has
|
||||
-- a condition that depends on overridden operations. For such an
|
||||
-- operation we must create a wrapper that is then treated as a normal
|
||||
-- overriding. In SPARK mode such operations are illegal.
|
||||
-- The mapping is also used to check whether an inherited operation has
|
||||
-- a condition that depends on overridden operations. For such an
|
||||
-- operation we must create a wrapper that is then treated as a normal
|
||||
-- overriding. In SPARK mode such operations are illegal.
|
||||
|
||||
-- For a given root type there may be several type extensions with their
|
||||
-- own overriding operations, so at various times a given operation of
|
||||
-- the root will be mapped into different overridings. The root type is
|
||||
-- also mapped into the current type extension to indicate that its
|
||||
-- operations are mapped into the overriding operations of that current
|
||||
-- type extension.
|
||||
-- For a given root type there may be several type extensions with their
|
||||
-- own overriding operations, so at various times a given operation of
|
||||
-- the root will be mapped into different overridings. The root type is
|
||||
-- also mapped into the current type extension to indicate that its
|
||||
-- operations are mapped into the overriding operations of that current
|
||||
-- type extension.
|
||||
|
||||
subtype Num_Primitives is Integer range 0 .. 510;
|
||||
function Entity_Hash (E : Entity_Id) return Num_Primitives;
|
||||
subtype Num_Primitives is Integer range 0 .. 510;
|
||||
function Entity_Hash (E : Entity_Id) return Num_Primitives;
|
||||
|
||||
package Primitives_Mapping is new Gnat.HTable.Simple_Htable
|
||||
(Header_Num => Num_Primitives,
|
||||
Key => Entity_Id,
|
||||
Element => Entity_Id,
|
||||
No_element => Empty,
|
||||
Hash => Entity_Hash,
|
||||
Equal => "=");
|
||||
package Primitives_Mapping is new Gnat.HTable.Simple_Htable
|
||||
(Header_Num => Num_Primitives,
|
||||
Key => Entity_Id,
|
||||
Element => Entity_Id,
|
||||
No_element => Empty,
|
||||
Hash => Entity_Hash,
|
||||
Equal => "=");
|
||||
|
||||
-------------------------------------
|
||||
-- Local Subprograms and Variables --
|
||||
@ -230,11 +229,6 @@ package body Sem_Prag is
|
||||
-- Query whether a particular item appears in a mixed list of nodes and
|
||||
-- entities. It is assumed that all nodes in the list have entities.
|
||||
|
||||
-- procedure Build_Classwide_Expression (Prag : Node_Id; Subp : Entity_Id);
|
||||
-- Build the expression for an inherited classwide condition. Prag is
|
||||
-- the pragma constructed from the corresponding aspect of the parent
|
||||
-- subprogram, and Subp is the overridding operation.
|
||||
|
||||
procedure Check_Postcondition_Use_In_Inlined_Subprogram
|
||||
(Prag : Node_Id;
|
||||
Spec_Id : Entity_Id);
|
||||
@ -327,18 +321,17 @@ package body Sem_Prag is
|
||||
-- pragma. Entity name for unit and its parents is taken from item in
|
||||
-- previous with_clause that mentions the unit.
|
||||
|
||||
Dummy : Integer := 0;
|
||||
pragma Volatile (Dummy);
|
||||
-- Dummy volatile integer used in bodies of ip/rv to prevent optimization
|
||||
|
||||
procedure Update_Primitives_Mapping
|
||||
(Inher_Id : Entity_Id;
|
||||
Subp_Id : Entity_Id);
|
||||
|
||||
-- map primitive operations of the parent type to the corresponding
|
||||
-- operations of the descendant. note that the descendant type may
|
||||
-- Map primitive operations of the parent type to the corresponding
|
||||
-- operations of the descendant. Note that the descendant type may
|
||||
-- not be frozen yet, so we cannot use the dispatch table directly.
|
||||
|
||||
Dummy : Integer := 0;
|
||||
pragma Volatile (Dummy);
|
||||
-- Dummy volatile integer used in bodies of ip/rv to prevent optimization
|
||||
|
||||
procedure ip;
|
||||
pragma No_Inline (ip);
|
||||
-- A dummy procedure called when pragma Inspection_Point is analyzed. This
|
||||
@ -17630,39 +17623,28 @@ package body Sem_Prag is
|
||||
Check_Valid_Configuration_Pragma;
|
||||
Check_Arg_Count (0);
|
||||
|
||||
-- Remove backward compatibility if Build_Type is FSF or GPL
|
||||
-- and generate a warning.
|
||||
No_Run_Time_Mode := True;
|
||||
Configurable_Run_Time_Mode := True;
|
||||
|
||||
declare
|
||||
Ignore : constant Boolean := Build_Type in FSF .. GPL;
|
||||
begin
|
||||
if Ignore then
|
||||
Error_Pragma ("pragma% is ignored, has no effect??");
|
||||
else
|
||||
No_Run_Time_Mode := True;
|
||||
Configurable_Run_Time_Mode := True;
|
||||
-- Set Duration to 32 bits if word size is 32
|
||||
|
||||
-- Set Duration to 32 bits if word size is 32
|
||||
if Ttypes.System_Word_Size = 32 then
|
||||
Duration_32_Bits_On_Target := True;
|
||||
end if;
|
||||
|
||||
if Ttypes.System_Word_Size = 32 then
|
||||
Duration_32_Bits_On_Target := True;
|
||||
end if;
|
||||
-- Set appropriate restrictions
|
||||
|
||||
-- Set appropriate restrictions
|
||||
Set_Restriction (No_Finalization, N);
|
||||
Set_Restriction (No_Exception_Handlers, N);
|
||||
Set_Restriction (Max_Tasks, N, 0);
|
||||
Set_Restriction (No_Tasking, N);
|
||||
|
||||
Set_Restriction (No_Finalization, N);
|
||||
Set_Restriction (No_Exception_Handlers, N);
|
||||
Set_Restriction (Max_Tasks, N, 0);
|
||||
Set_Restriction (No_Tasking, N);
|
||||
end if;
|
||||
end;
|
||||
-----------------------
|
||||
-- No_Tagged_Streams --
|
||||
-----------------------
|
||||
|
||||
-----------------------
|
||||
-- No_Tagged_Streams --
|
||||
-----------------------
|
||||
|
||||
-- pragma No_Tagged_Streams;
|
||||
-- pragma No_Tagged_Streams ([Entity => ]tagged_type_local_NAME);
|
||||
-- pragma No_Tagged_Streams;
|
||||
-- pragma No_Tagged_Streams ([Entity => ]tagged_type_local_NAME);
|
||||
|
||||
when Pragma_No_Tagged_Streams => No_Tagged_Strms : declare
|
||||
E : Entity_Id;
|
||||
@ -22356,7 +22338,22 @@ package body Sem_Prag is
|
||||
|
||||
when Pragma_Universal_Data =>
|
||||
GNAT_Pragma;
|
||||
Error_Pragma ("??pragma% ignored (applies only to AAMP)");
|
||||
|
||||
-- If this is a configuration pragma, then set the universal
|
||||
-- addressing option, otherwise confirm that the pragma satisfies
|
||||
-- the requirements of library unit pragma placement and leave it
|
||||
-- to the GNAAMP back end to detect the pragma (avoids transitive
|
||||
-- setting of the option due to withed units).
|
||||
|
||||
if Is_Configuration_Pragma then
|
||||
Universal_Addressing_On_AAMP := True;
|
||||
else
|
||||
Check_Valid_Library_Unit_Pragma;
|
||||
end if;
|
||||
|
||||
if not AAMP_On_Target then
|
||||
Error_Pragma ("??pragma% ignored (applies only to AAMP)");
|
||||
end if;
|
||||
|
||||
----------------
|
||||
-- Unmodified --
|
||||
@ -26327,6 +26324,103 @@ package body Sem_Prag is
|
||||
return False;
|
||||
end Appears_In;
|
||||
|
||||
--------------------------------
|
||||
-- Build_Classwide_Expression --
|
||||
--------------------------------
|
||||
|
||||
procedure Build_Classwide_Expression (Prag : Node_Id; Subp : Entity_Id) is
|
||||
function Replace_Entity (N : Node_Id) return Traverse_Result;
|
||||
-- Replace reference to formal of inherited operation or to primitive
|
||||
-- operation of root type, with corresponding entity for derived type,
|
||||
-- when constructing the classwide condition of an overridding
|
||||
-- subprogram.
|
||||
|
||||
--------------------
|
||||
-- Replace_Entity --
|
||||
--------------------
|
||||
|
||||
function Replace_Entity (N : Node_Id) return Traverse_Result is
|
||||
New_E : Entity_Id;
|
||||
|
||||
begin
|
||||
if Nkind (N) = N_Identifier
|
||||
and then Present (Entity (N))
|
||||
and then
|
||||
(Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
|
||||
and then
|
||||
(Nkind (Parent (N)) /= N_Attribute_Reference
|
||||
or else Attribute_Name (Parent (N)) /= Name_Class)
|
||||
then
|
||||
-- The replacement does not apply to dispatching calls within the
|
||||
-- condition, but only to calls whose static tag is that of the
|
||||
-- parent type.
|
||||
|
||||
if Is_Subprogram (Entity (N))
|
||||
and then Nkind (Parent (N)) = N_Function_Call
|
||||
and then Present (Controlling_Argument (Parent (N)))
|
||||
then
|
||||
return OK;
|
||||
end if;
|
||||
|
||||
-- Determine whether entity has a renaming
|
||||
|
||||
New_E := Primitives_Mapping.Get (Entity (N));
|
||||
|
||||
if Present (New_E) then
|
||||
Rewrite (N, New_Occurrence_Of (New_E, Sloc (N)));
|
||||
end if;
|
||||
|
||||
-- Check that there are no calls left to abstract operations if
|
||||
-- the current subprogram is not abstract.
|
||||
|
||||
if Nkind (Parent (N)) = N_Function_Call
|
||||
and then N = Name (Parent (N))
|
||||
then
|
||||
if not Is_Abstract_Subprogram (Subp)
|
||||
and then Is_Abstract_Subprogram (Entity (N))
|
||||
then
|
||||
Error_Msg_Sloc := Sloc (Current_Scope);
|
||||
Error_Msg_NE
|
||||
("cannot call abstract subprogram in inherited condition "
|
||||
& "for&#", N, Current_Scope);
|
||||
|
||||
elsif SPARK_Mode = On
|
||||
and then Warn_On_Suspicious_Contract
|
||||
and then Present (Alias (Subp))
|
||||
then
|
||||
Error_Msg_NE
|
||||
("?inherited condition is modified, build a wrapper "
|
||||
& "for&", Parent (Subp), Subp);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Update type of function call node, which should be the same as
|
||||
-- the function's return type.
|
||||
|
||||
if Is_Subprogram (Entity (N))
|
||||
and then Nkind (Parent (N)) = N_Function_Call
|
||||
then
|
||||
Set_Etype (Parent (N), Etype (Entity (N)));
|
||||
end if;
|
||||
|
||||
-- The whole expression will be reanalyzed
|
||||
|
||||
elsif Nkind (N) in N_Has_Etype then
|
||||
Set_Analyzed (N, False);
|
||||
end if;
|
||||
|
||||
return OK;
|
||||
end Replace_Entity;
|
||||
|
||||
procedure Replace_Condition_Entities is
|
||||
new Traverse_Proc (Replace_Entity);
|
||||
|
||||
-- Start of processing for Build_Classwide_Expression
|
||||
|
||||
begin
|
||||
Replace_Condition_Entities (Prag);
|
||||
end Build_Classwide_Expression;
|
||||
|
||||
-----------------------------------
|
||||
-- Build_Pragma_Check_Equivalent --
|
||||
-----------------------------------
|
||||
@ -26337,7 +26431,6 @@ package body Sem_Prag is
|
||||
Inher_Id : Entity_Id := Empty;
|
||||
Keep_Pragma_Id : Boolean := False) return Node_Id
|
||||
is
|
||||
|
||||
function Suppress_Reference (N : Node_Id) return Traverse_Result;
|
||||
-- Detect whether node N references a formal parameter subject to
|
||||
-- pragma Unreferenced. If this is the case, set Comes_From_Source
|
||||
@ -26355,9 +26448,9 @@ package body Sem_Prag is
|
||||
if Is_Entity_Name (N) and then Present (Entity (N)) then
|
||||
Formal := Entity (N);
|
||||
|
||||
-- The formal parameter is subject to pragma Unreferenced.
|
||||
-- Prevent the generation of a reference by resetting the
|
||||
-- Comes_From_Source flag.
|
||||
-- The formal parameter is subject to pragma Unreferenced. Prevent
|
||||
-- the generation of references by resetting the Comes_From_Source
|
||||
-- flag.
|
||||
|
||||
if Is_Formal (Formal)
|
||||
and then Has_Pragma_Unreferenced (Formal)
|
||||
@ -26835,100 +26928,6 @@ package body Sem_Prag is
|
||||
end if;
|
||||
end Check_Missing_Part_Of;
|
||||
|
||||
--------------------------------
|
||||
-- Build_Classwide_Expression --
|
||||
--------------------------------
|
||||
|
||||
procedure Build_Classwide_Expression (Prag : Node_Id; Subp : Entity_Id) is
|
||||
function Replace_Entity (N : Node_Id) return Traverse_Result;
|
||||
-- Replace reference to formal of inherited operation or to primitive
|
||||
-- operation of root type, with corresponding entity for derived type,
|
||||
-- when constructing the classwide condition of an overridding
|
||||
-- subprogram.
|
||||
|
||||
--------------------
|
||||
-- Replace_Entity --
|
||||
--------------------
|
||||
|
||||
function Replace_Entity (N : Node_Id) return Traverse_Result is
|
||||
New_E : Entity_Id;
|
||||
|
||||
begin
|
||||
if Nkind (N) = N_Identifier
|
||||
and then Present (Entity (N))
|
||||
and then
|
||||
(Is_Formal (Entity (N)) or else Is_Subprogram (Entity (N)))
|
||||
and then
|
||||
(Nkind (Parent (N)) /= N_Attribute_Reference
|
||||
or else Attribute_Name (Parent (N)) /= Name_Class)
|
||||
then
|
||||
-- The replacement does not apply to dispatching calls within the
|
||||
-- condition, but only to calls whose static tag is that of the
|
||||
-- parent type.
|
||||
|
||||
if Is_Subprogram (Entity (N))
|
||||
and then Nkind (Parent (N)) = N_Function_Call
|
||||
and then Present (Controlling_Argument (Parent (N)))
|
||||
then
|
||||
return OK;
|
||||
end if;
|
||||
|
||||
-- Determine whether entity has a renaming
|
||||
|
||||
New_E := Primitives_Mapping.Get (Entity (N));
|
||||
|
||||
if Present (New_E) then
|
||||
Rewrite (N, New_Occurrence_Of (New_E, Sloc (N)));
|
||||
end if;
|
||||
|
||||
-- Check that there are no calls left to abstract operations if
|
||||
-- the current subprogram is not abstract.
|
||||
|
||||
if Nkind (Parent (N)) = N_Function_Call
|
||||
and then N = Name (Parent (N))
|
||||
then
|
||||
if not Is_Abstract_Subprogram (Subp)
|
||||
and then Is_Abstract_Subprogram (Entity (N))
|
||||
then
|
||||
Error_Msg_Sloc := Sloc (Current_Scope);
|
||||
Error_Msg_NE
|
||||
("cannot call abstract subprogram in inherited condition "
|
||||
& "for&#", N, Current_Scope);
|
||||
|
||||
elsif Present (Alias (Subp))
|
||||
and then Warn_On_Suspicious_Contract
|
||||
and then SPARK_Mode = On
|
||||
then
|
||||
Error_Msg_NE ("?inherited condition is modified, "
|
||||
& "build a wrapper for&", Parent (Subp), Subp);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Update type of function call node, which should be the same as
|
||||
-- the function's return type.
|
||||
|
||||
if Is_Subprogram (Entity (N))
|
||||
and then Nkind (Parent (N)) = N_Function_Call
|
||||
then
|
||||
Set_Etype (Parent (N), Etype (Entity (N)));
|
||||
end if;
|
||||
|
||||
-- The whole expression will be reanalyzed
|
||||
|
||||
elsif Nkind (N) in N_Has_Etype then
|
||||
Set_Analyzed (N, False);
|
||||
end if;
|
||||
|
||||
return OK;
|
||||
end Replace_Entity;
|
||||
|
||||
procedure Replace_Condition_Entities is
|
||||
new Traverse_Proc (Replace_Entity);
|
||||
|
||||
begin
|
||||
Replace_Condition_Entities (Prag);
|
||||
end Build_Classwide_Expression;
|
||||
|
||||
---------------------------------------------------
|
||||
-- Check_Postcondition_Use_In_Inlined_Subprogram --
|
||||
---------------------------------------------------
|
||||
@ -27489,6 +27488,15 @@ package body Sem_Prag is
|
||||
end if;
|
||||
end Duplication_Error;
|
||||
|
||||
-----------------
|
||||
-- Entity_Hash --
|
||||
-----------------
|
||||
|
||||
function Entity_Hash (E : Entity_Id) return Num_Primitives is
|
||||
begin
|
||||
return Num_Primitives (E mod 511);
|
||||
end Entity_Hash;
|
||||
|
||||
--------------------------
|
||||
-- Find_Related_Context --
|
||||
--------------------------
|
||||
@ -27848,15 +27856,6 @@ package body Sem_Prag is
|
||||
return Result;
|
||||
end Get_Base_Subprogram;
|
||||
|
||||
-----------------
|
||||
-- Entity_Hash --
|
||||
-----------------
|
||||
|
||||
function Entity_Hash (E : Entity_Id) return Num_Primitives is
|
||||
begin
|
||||
return Num_Primitives (E mod 511);
|
||||
end Entity_Hash;
|
||||
|
||||
-----------------------
|
||||
-- Get_SPARK_Mode_Type --
|
||||
-----------------------
|
||||
@ -29104,148 +29103,6 @@ package body Sem_Prag is
|
||||
Generate_Reference (Entity (With_Item), N, Set_Ref => False);
|
||||
end Set_Elab_Unit_Name;
|
||||
|
||||
-------------------------------
|
||||
-- Update_Primitives_Mapping --
|
||||
-------------------------------
|
||||
|
||||
procedure Update_Primitives_Mapping
|
||||
(Inher_Id : Entity_Id;
|
||||
Subp_Id : Entity_Id)
|
||||
is
|
||||
function Overridden_Ancestor (S : Entity_Id) return Entity_Id;
|
||||
|
||||
-------------------------
|
||||
-- Overridden_Ancestor --
|
||||
-------------------------
|
||||
|
||||
function Overridden_Ancestor (S : Entity_Id) return Entity_Id is
|
||||
Par : constant Entity_Id := Find_Dispatching_Type (Inher_Id);
|
||||
Anc : Entity_Id;
|
||||
|
||||
begin
|
||||
Anc := S;
|
||||
|
||||
-- Locate the ancestor subprogram with the proper controlling
|
||||
-- type.
|
||||
|
||||
while Present (Overridden_Operation (Anc)) loop
|
||||
Anc := Overridden_Operation (Anc);
|
||||
exit when Find_Dispatching_Type (Anc) = Par;
|
||||
end loop;
|
||||
|
||||
return Anc;
|
||||
end Overridden_Ancestor;
|
||||
|
||||
-- Local variables
|
||||
|
||||
Old_Typ : constant Entity_Id := Find_Dispatching_Type (Inher_Id);
|
||||
Typ : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
|
||||
Decl : Node_Id;
|
||||
Old_Elmt : Elmt_Id;
|
||||
Old_Prim : Entity_Id;
|
||||
Prim : Entity_Id;
|
||||
|
||||
-- Start of processing for Primitive_Mapping
|
||||
|
||||
begin
|
||||
-- if the types are already in the map, it has been previously built
|
||||
-- for some other overriding primitive.
|
||||
|
||||
if Primitives_Mapping.Get (Old_Typ) = Typ then
|
||||
return;
|
||||
|
||||
else
|
||||
|
||||
-- initialize new mapping with the primitive operations.
|
||||
|
||||
Decl := First (List_Containing (Unit_Declaration_Node (Subp_Id)));
|
||||
|
||||
-- look for primitive operations of the current type that have
|
||||
-- overridden an operation of the type related to the original
|
||||
-- class-wide precondition. there may be several intermediate
|
||||
-- overridings between them.
|
||||
|
||||
while Present (Decl) loop
|
||||
if Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
|
||||
N_Subprogram_Declaration)
|
||||
then
|
||||
Prim := Defining_Entity (Decl);
|
||||
|
||||
if Is_Subprogram (Prim)
|
||||
and then Present (Overridden_Operation (Prim))
|
||||
and then Find_Dispatching_Type (Prim) = Typ
|
||||
then
|
||||
Old_Prim := Overridden_Ancestor (Prim);
|
||||
|
||||
Primitives_Mapping.Set (Old_Prim, Prim);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
Next (Decl);
|
||||
end loop;
|
||||
|
||||
-- now examine inherited operations. these do not override, but have
|
||||
-- an alias, which is the entity used in a call. that alias may be
|
||||
-- inherited or come from source, in which case it may override an
|
||||
-- earlier operation. we only need to examine inherited functions,
|
||||
-- that can appear within the inherited expression.
|
||||
|
||||
Prim := First_Entity (Scope (Subp_Id));
|
||||
while Present (Prim) loop
|
||||
if not Comes_From_Source (Prim)
|
||||
and then Ekind (Prim) = E_Function
|
||||
and then Present (Alias (Prim))
|
||||
then
|
||||
Old_Prim := Alias (Prim);
|
||||
|
||||
if Comes_From_Source (Old_Prim) then
|
||||
Old_Prim := Overridden_Ancestor (Old_Prim);
|
||||
|
||||
else
|
||||
while Present (Alias (Old_Prim))
|
||||
and then Scope (Old_Prim) /= Scope (Inher_Id)
|
||||
loop
|
||||
Old_Prim := Alias (Old_Prim);
|
||||
|
||||
if Comes_From_Source (Old_Prim) then
|
||||
Old_Prim := Overridden_Ancestor (Old_Prim);
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
Primitives_Mapping.Set (Old_Prim, Prim);
|
||||
end if;
|
||||
|
||||
Next_Entity (Prim);
|
||||
end loop;
|
||||
|
||||
-- if the parent operation is an interface operation, the
|
||||
-- overriding indicator is not present. instead, we get from
|
||||
-- the interface operation the primitive of the current type
|
||||
-- that implements it.
|
||||
|
||||
if Is_Interface (Old_Typ) then
|
||||
Old_Elmt := First_Elmt (Collect_Primitive_Operations (Old_Typ));
|
||||
while Present (Old_Elmt) loop
|
||||
Old_Prim := Node (Old_Elmt);
|
||||
Prim := Find_Primitive_Covering_Interface (Typ, Old_Prim);
|
||||
|
||||
if Present (Prim) then
|
||||
Primitives_Mapping.Set (Old_Prim, Prim);
|
||||
end if;
|
||||
|
||||
Next_Elmt (Old_Elmt);
|
||||
end loop;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- map the types themselves, so that the process is not repeated for
|
||||
-- other overriding primitives.
|
||||
|
||||
Primitives_Mapping.Set (Old_Typ, Typ);
|
||||
end Update_Primitives_Mapping;
|
||||
|
||||
-------------------
|
||||
-- Test_Case_Arg --
|
||||
-------------------
|
||||
@ -29342,4 +29199,144 @@ package body Sem_Prag is
|
||||
return Empty;
|
||||
end Test_Case_Arg;
|
||||
|
||||
-------------------------------
|
||||
-- Update_Primitives_Mapping --
|
||||
-------------------------------
|
||||
|
||||
procedure Update_Primitives_Mapping
|
||||
(Inher_Id : Entity_Id;
|
||||
Subp_Id : Entity_Id)
|
||||
is
|
||||
function Overridden_Ancestor (S : Entity_Id) return Entity_Id;
|
||||
-- ??? what does this routine do?
|
||||
|
||||
-------------------------
|
||||
-- Overridden_Ancestor --
|
||||
-------------------------
|
||||
|
||||
function Overridden_Ancestor (S : Entity_Id) return Entity_Id is
|
||||
Par : constant Entity_Id := Find_Dispatching_Type (Inher_Id);
|
||||
Anc : Entity_Id;
|
||||
|
||||
begin
|
||||
Anc := S;
|
||||
|
||||
-- Locate the ancestor subprogram with the proper controlling type
|
||||
|
||||
while Present (Overridden_Operation (Anc)) loop
|
||||
Anc := Overridden_Operation (Anc);
|
||||
exit when Find_Dispatching_Type (Anc) = Par;
|
||||
end loop;
|
||||
|
||||
return Anc;
|
||||
end Overridden_Ancestor;
|
||||
|
||||
-- Local variables
|
||||
|
||||
Old_Typ : constant Entity_Id := Find_Dispatching_Type (Inher_Id);
|
||||
Typ : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
|
||||
Decl : Node_Id;
|
||||
Old_Elmt : Elmt_Id;
|
||||
Old_Prim : Entity_Id;
|
||||
Prim : Entity_Id;
|
||||
|
||||
-- Start of processing for Primitive_Mapping
|
||||
|
||||
begin
|
||||
-- If the types are already in the map, it has been previously built for
|
||||
-- some other overriding primitive.
|
||||
|
||||
if Primitives_Mapping.Get (Old_Typ) = Typ then
|
||||
return;
|
||||
|
||||
else
|
||||
-- Initialize new mapping with the primitive operations
|
||||
|
||||
Decl := First (List_Containing (Unit_Declaration_Node (Subp_Id)));
|
||||
|
||||
-- Look for primitive operations of the current type that have
|
||||
-- overridden an operation of the type related to the original
|
||||
-- class-wide precondition. There may be several intermediate
|
||||
-- overridings between them.
|
||||
|
||||
while Present (Decl) loop
|
||||
if Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
|
||||
N_Subprogram_Declaration)
|
||||
then
|
||||
Prim := Defining_Entity (Decl);
|
||||
|
||||
if Is_Subprogram (Prim)
|
||||
and then Present (Overridden_Operation (Prim))
|
||||
and then Find_Dispatching_Type (Prim) = Typ
|
||||
then
|
||||
Old_Prim := Overridden_Ancestor (Prim);
|
||||
|
||||
Primitives_Mapping.Set (Old_Prim, Prim);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
Next (Decl);
|
||||
end loop;
|
||||
|
||||
-- Now examine inherited operations. these do not override, but have
|
||||
-- an alias, which is the entity used in a call. That alias may be
|
||||
-- inherited or come from source, in which case it may override an
|
||||
-- earlier operation. We only need to examine inherited functions,
|
||||
-- that can appear within the inherited expression.
|
||||
|
||||
Prim := First_Entity (Scope (Subp_Id));
|
||||
while Present (Prim) loop
|
||||
if not Comes_From_Source (Prim)
|
||||
and then Ekind (Prim) = E_Function
|
||||
and then Present (Alias (Prim))
|
||||
then
|
||||
Old_Prim := Alias (Prim);
|
||||
|
||||
if Comes_From_Source (Old_Prim) then
|
||||
Old_Prim := Overridden_Ancestor (Old_Prim);
|
||||
|
||||
else
|
||||
while Present (Alias (Old_Prim))
|
||||
and then Scope (Old_Prim) /= Scope (Inher_Id)
|
||||
loop
|
||||
Old_Prim := Alias (Old_Prim);
|
||||
|
||||
if Comes_From_Source (Old_Prim) then
|
||||
Old_Prim := Overridden_Ancestor (Old_Prim);
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
Primitives_Mapping.Set (Old_Prim, Prim);
|
||||
end if;
|
||||
|
||||
Next_Entity (Prim);
|
||||
end loop;
|
||||
|
||||
-- If the parent operation is an interface operation, the overriding
|
||||
-- indicator is not present. Instead, we get from the interface
|
||||
-- operation the primitive of the current type that implements it.
|
||||
|
||||
if Is_Interface (Old_Typ) then
|
||||
Old_Elmt := First_Elmt (Collect_Primitive_Operations (Old_Typ));
|
||||
while Present (Old_Elmt) loop
|
||||
Old_Prim := Node (Old_Elmt);
|
||||
Prim := Find_Primitive_Covering_Interface (Typ, Old_Prim);
|
||||
|
||||
if Present (Prim) then
|
||||
Primitives_Mapping.Set (Old_Prim, Prim);
|
||||
end if;
|
||||
|
||||
Next_Elmt (Old_Elmt);
|
||||
end loop;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Map the types themselves, so that the process is not repeated for
|
||||
-- other overriding primitives.
|
||||
|
||||
Primitives_Mapping.Set (Old_Typ, Typ);
|
||||
end Update_Primitives_Mapping;
|
||||
|
||||
end Sem_Prag;
|
||||
|
Loading…
Reference in New Issue
Block a user