Commit ea985d95 by Robert Dewar Committed by Arnaud Charlet

exp_util.ads, [...] (Is_Ref_To_Bit_Packed_Slice): Handle case of type conversion.

2005-12-05  Robert Dewar  <dewar@adacore.com>
	    Javier Miranda  <miranda@adacore.com>
	    Ed Schonberg  <schonberg@adacore.com>

	* exp_util.ads, exp_util.adb (Is_Ref_To_Bit_Packed_Slice): Handle case
	of type conversion.
	(Find_Interface): New subprogram that given a tagged type and one of its
	component associated with the secondary table of an abstract interface
	type, return the entity associated with such abstract interface type.
	(Make_Subtype_From_Expr): If type has unknown discriminants, always use
	base type to create anonymous subtype, because entity may be a locally
	declared subtype or generic actual.
	(Find_Interface): New subprogram that given a tagged type and one of its
	component associated with the secondary table of an abstract interface
	type, return the entity associated with such abstract interface type.

	* sem_res.adb (Resolve_Type_Conversion): Handle the case in which the
	conversion cannot be handled at compile time. In this case we pass this
	information to the expander to generate the appropriate code.

From-SVN: r108294
parent e6d9df3c
...@@ -1447,7 +1447,7 @@ package body Exp_Util is ...@@ -1447,7 +1447,7 @@ package body Exp_Util is
Iface : Entity_Id) return Entity_Id Iface : Entity_Id) return Entity_Id
is is
ADT : Elmt_Id; ADT : Elmt_Id;
Found : Boolean := False; Found : Boolean := False;
Typ : Entity_Id := T; Typ : Entity_Id := T;
procedure Find_Secondary_Table (Typ : Entity_Id); procedure Find_Secondary_Table (Typ : Entity_Id);
...@@ -1544,9 +1544,9 @@ package body Exp_Util is ...@@ -1544,9 +1544,9 @@ package body Exp_Util is
procedure Find_Tag (Typ : in Entity_Id); procedure Find_Tag (Typ : in Entity_Id);
-- Internal subprogram used to recursively climb to the ancestors -- Internal subprogram used to recursively climb to the ancestors
----------------- --------------
-- Find_AI_Tag -- -- Find_Tag --
----------------- --------------
procedure Find_Tag (Typ : in Entity_Id) is procedure Find_Tag (Typ : in Entity_Id) is
AI_Elmt : Elmt_Id; AI_Elmt : Elmt_Id;
...@@ -1642,6 +1642,101 @@ package body Exp_Util is ...@@ -1642,6 +1642,101 @@ package body Exp_Util is
return AI_Tag; return AI_Tag;
end Find_Interface_Tag; end Find_Interface_Tag;
--------------------
-- Find_Interface --
--------------------
function Find_Interface
(T : Entity_Id;
Comp : Entity_Id) return Entity_Id
is
AI_Tag : Entity_Id;
Found : Boolean := False;
Iface : Entity_Id;
Typ : Entity_Id := T;
procedure Find_Iface (Typ : in Entity_Id);
-- Internal subprogram used to recursively climb to the ancestors
----------------
-- Find_Iface --
----------------
procedure Find_Iface (Typ : in Entity_Id) is
AI_Elmt : Elmt_Id;
begin
-- Climb to the root type
if Etype (Typ) /= Typ then
Find_Iface (Etype (Typ));
end if;
-- Traverse the list of interfaces implemented by the type
if not Found
and then Present (Abstract_Interfaces (Typ))
and then not (Is_Empty_Elmt_List (Abstract_Interfaces (Typ)))
then
-- Skip the tag associated with the primary table
pragma Assert (Etype (First_Tag_Component (Typ)) = RTE (RE_Tag));
AI_Tag := Next_Tag_Component (First_Tag_Component (Typ));
pragma Assert (Present (AI_Tag));
AI_Elmt := First_Elmt (Abstract_Interfaces (Typ));
while Present (AI_Elmt) loop
if AI_Tag = Comp then
Iface := Node (AI_Elmt);
Found := True;
return;
end if;
AI_Tag := Next_Tag_Component (AI_Tag);
Next_Elmt (AI_Elmt);
end loop;
end if;
end Find_Iface;
-- Start of processing for Find_Interface
begin
-- Handle private types
if Has_Private_Declaration (Typ)
and then Present (Full_View (Typ))
then
Typ := Full_View (Typ);
end if;
-- Handle access types
if Is_Access_Type (Typ) then
Typ := Directly_Designated_Type (Typ);
end if;
-- Handle task and protected types implementing interfaces
if Is_Concurrent_Type (Typ) then
Typ := Corresponding_Record_Type (Typ);
end if;
if Is_Class_Wide_Type (Typ) then
Typ := Etype (Typ);
end if;
-- Handle entities from the limited view
if Ekind (Typ) = E_Incomplete_Type then
pragma Assert (Present (Non_Limited_View (Typ)));
Typ := Non_Limited_View (Typ);
end if;
Find_Iface (Typ);
pragma Assert (Found);
return Iface;
end Find_Interface;
------------------ ------------------
-- Find_Prim_Op -- -- Find_Prim_Op --
------------------ ------------------
...@@ -3050,14 +3145,16 @@ package body Exp_Util is ...@@ -3050,14 +3145,16 @@ package body Exp_Util is
function Is_Ref_To_Bit_Packed_Slice (N : Node_Id) return Boolean is function Is_Ref_To_Bit_Packed_Slice (N : Node_Id) return Boolean is
begin begin
if Is_Entity_Name (N) if Nkind (N) = N_Type_Conversion then
return Is_Ref_To_Bit_Packed_Slice (Expression (N));
elsif Is_Entity_Name (N)
and then Is_Object (Entity (N)) and then Is_Object (Entity (N))
and then Present (Renamed_Object (Entity (N))) and then Present (Renamed_Object (Entity (N)))
then then
return Is_Ref_To_Bit_Packed_Slice (Renamed_Object (Entity (N))); return Is_Ref_To_Bit_Packed_Slice (Renamed_Object (Entity (N)));
end if;
if Nkind (N) = N_Slice elsif Nkind (N) = N_Slice
and then Is_Bit_Packed_Array (Etype (Prefix (N))) and then Is_Bit_Packed_Array (Etype (Prefix (N)))
then then
return True; return True;
...@@ -3500,7 +3597,8 @@ package body Exp_Util is ...@@ -3500,7 +3597,8 @@ package body Exp_Util is
and then Has_Unknown_Discriminants (Unc_Typ) and then Has_Unknown_Discriminants (Unc_Typ)
then then
-- Prepare the subtype completion, Go to base type to -- Prepare the subtype completion, Go to base type to
-- find underlying type. -- find underlying type, because the type may be a generic
-- actual or an explicit subtype.
Utyp := Underlying_Type (Base_Type (Unc_Typ)); Utyp := Underlying_Type (Base_Type (Unc_Typ));
Full_Subtyp := Make_Defining_Identifier (Loc, Full_Subtyp := Make_Defining_Identifier (Loc,
...@@ -3521,7 +3619,7 @@ package body Exp_Util is ...@@ -3521,7 +3619,7 @@ package body Exp_Util is
-- Define the dummy private subtype -- Define the dummy private subtype
Set_Ekind (Priv_Subtyp, Subtype_Kind (Ekind (Unc_Typ))); Set_Ekind (Priv_Subtyp, Subtype_Kind (Ekind (Unc_Typ)));
Set_Etype (Priv_Subtyp, Unc_Typ); Set_Etype (Priv_Subtyp, Base_Type (Unc_Typ));
Set_Scope (Priv_Subtyp, Full_Subtyp); Set_Scope (Priv_Subtyp, Full_Subtyp);
Set_Is_Constrained (Priv_Subtyp); Set_Is_Constrained (Priv_Subtyp);
Set_Is_Tagged_Type (Priv_Subtyp, Is_Tagged_Type (Unc_Typ)); Set_Is_Tagged_Type (Priv_Subtyp, Is_Tagged_Type (Unc_Typ));
...@@ -3585,7 +3683,7 @@ package body Exp_Util is ...@@ -3585,7 +3683,7 @@ package body Exp_Util is
return New_Occurrence_Of (CW_Subtype, Loc); return New_Occurrence_Of (CW_Subtype, Loc);
end; end;
-- Indefinite record type with discriminants. -- Indefinite record type with discriminants
else else
D := First_Discriminant (Unc_Typ); D := First_Discriminant (Unc_Typ);
......
...@@ -339,6 +339,13 @@ package Exp_Util is ...@@ -339,6 +339,13 @@ package Exp_Util is
-- declarations and/or allocations when the type is indefinite (including -- declarations and/or allocations when the type is indefinite (including
-- class-wide). -- class-wide).
function Find_Interface
(T : Entity_Id;
Comp : Entity_Id) return Entity_Id;
-- Ada 2005 (AI-251): Given a tagged type and one of its components
-- associated with the secondary dispatch table of an abstract interface
-- type, return the associated abstract interface type.
function Find_Interface_ADT function Find_Interface_ADT
(T : Entity_Id; (T : Entity_Id;
Iface : Entity_Id) return Entity_Id; Iface : Entity_Id) return Entity_Id;
......
...@@ -1559,8 +1559,8 @@ package body Sem_Res is ...@@ -1559,8 +1559,8 @@ package body Sem_Res is
if Nkind (N) = N_Attribute_Reference if Nkind (N) = N_Attribute_Reference
and then (Attribute_Name (N) = Name_Access and then (Attribute_Name (N) = Name_Access
or else Attribute_Name (N) = Name_Unrestricted_Access or else Attribute_Name (N) = Name_Unrestricted_Access
or else Attribute_Name (N) = Name_Unchecked_Access) or else Attribute_Name (N) = Name_Unchecked_Access)
and then Comes_From_Source (N) and then Comes_From_Source (N)
and then Is_Entity_Name (Prefix (N)) and then Is_Entity_Name (Prefix (N))
and then Is_Subprogram (Entity (Prefix (N))) and then Is_Subprogram (Entity (Prefix (N)))
...@@ -2091,11 +2091,9 @@ package body Sem_Res is ...@@ -2091,11 +2091,9 @@ package body Sem_Res is
Get_First_Interp (Name (N), Index, It); Get_First_Interp (Name (N), Index, It);
while Present (It.Nam) loop while Present (It.Nam) loop
Error_Msg_Sloc := Sloc (It.Nam); Error_Msg_Sloc := Sloc (It.Nam);
Error_Msg_Node_2 := It.Typ; Error_Msg_Node_2 := It.Typ;
Error_Msg_NE ("\& declared#, type&", Error_Msg_NE ("\& declared#, type&", N, It.Nam);
N, It.Nam);
Get_Next_Interp (Index, It); Get_Next_Interp (Index, It);
end loop; end loop;
end; end;
...@@ -2591,15 +2589,15 @@ package body Sem_Res is ...@@ -2591,15 +2589,15 @@ package body Sem_Res is
-- If the formal is Out or In_Out, do not resolve and expand the -- If the formal is Out or In_Out, do not resolve and expand the
-- conversion, because it is subsequently expanded into explicit -- conversion, because it is subsequently expanded into explicit
-- temporaries and assignments. However, the object of the -- temporaries and assignments. However, the object of the
-- conversion can be resolved. An exception is the case of a -- conversion can be resolved. An exception is the case of tagged
-- tagged type conversion with a class-wide actual. In that case -- type conversion with a class-wide actual. In that case we want
-- we want the tag check to occur and no temporary will be needed -- the tag check to occur and no temporary will be needed (no
-- (no representation change can occur) and the parameter is -- representation change can occur) and the parameter is passed by
-- passed by reference, so we go ahead and resolve the type -- reference, so we go ahead and resolve the type conversion.
-- conversion. Another excpetion is the case of reference to a -- Another excpetion is the case of reference to component or
-- component or subcomponent of a bit-packed array, in which case -- subcomponent of a bit-packed array, in which case we want to
-- we want to defer expansion to the point the in and out -- defer expansion to the point the in and out assignments are
-- assignments are performed. -- performed.
if Ekind (F) /= E_In_Parameter if Ekind (F) /= E_In_Parameter
and then Nkind (A) = N_Type_Conversion and then Nkind (A) = N_Type_Conversion
...@@ -6660,34 +6658,50 @@ package body Sem_Res is ...@@ -6660,34 +6658,50 @@ package body Sem_Res is
Opnd_Type := Directly_Designated_Type (Opnd_Type); Opnd_Type := Directly_Designated_Type (Opnd_Type);
end if; end if;
if Is_Class_Wide_Type (Opnd_Type) then declare
Opnd_Type := Etype (Opnd_Type); Save_Typ : constant Entity_Id := Opnd_Type;
end if;
if not Interface_Present_In_Ancestor begin
(Typ => Opnd_Type, if Is_Class_Wide_Type (Opnd_Type) then
Iface => Target_Type) Opnd_Type := Etype (Opnd_Type);
then end if;
Error_Msg_NE
("(Ada 2005) does not implement interface }",
Operand, Target_Type);
else if not Interface_Present_In_Ancestor
-- If a conversion to an interface type appears as an actual in (Typ => Opnd_Type,
-- a source call, it will be expanded when the enclosing call Iface => Target_Type)
-- itself is examined in Expand_Interface_Formals. Otherwise,
-- generate the proper conversion code now, using the tag of
-- the interface.
if (Nkind (Parent (N)) = N_Procedure_Call_Statement
or else Nkind (Parent (N)) = N_Function_Call)
and then Comes_From_Source (N)
then then
null; -- The static analysis is not enough to know if the
-- interface is implemented or not. Hence we must pass the
-- work to the expander to generate the required code to
-- evaluate the conversion at run-time.
if Is_Class_Wide_Type (Save_Typ)
and then Is_Interface (Save_Typ)
then
Expand_Interface_Conversion (N, Is_Static => False);
else
Error_Msg_NE
("(Ada 2005) does not implement interface }",
Operand, Target_Type);
end if;
else else
Expand_Interface_Conversion (N); -- If a conversion to an interface type appears as an actual
-- in a source call, it will be expanded when the enclosing
-- call itself is examined in Expand_Interface_Formals.
-- Otherwise, generate the proper conversion code now, using
-- the tag of the interface.
if (Nkind (Parent (N)) = N_Procedure_Call_Statement
or else Nkind (Parent (N)) = N_Function_Call)
and then Comes_From_Source (N)
then
null;
else
Expand_Interface_Conversion (N);
end if;
end if; end if;
end if; end;
end if; end if;
end if; end if;
end Resolve_Type_Conversion; end Resolve_Type_Conversion;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment