Commit 8cea7b64 by Hristian Kirtchev Committed by Arnaud Charlet

exp_ch4.adb (Expand_N_Type_Conversion): Minor code reformatting.

2008-05-26  Hristian Kirtchev  <kirtchev@adacore.com>

	* exp_ch4.adb (Expand_N_Type_Conversion): Minor code reformatting.
	Generate a tag check when the result subtype of a function, defined by
	an access definition, designates a specific tagged type.
	(Make_Tag_Check): New routine.

From-SVN: r135916
parent 41def521
...@@ -7583,38 +7583,28 @@ package body Exp_Ch4 is ...@@ -7583,38 +7583,28 @@ package body Exp_Ch4 is
-- Otherwise, proceed with processing tagged conversion -- Otherwise, proceed with processing tagged conversion
declare declare
Actual_Operand_Type : Entity_Id; Actual_Op_Typ : Entity_Id;
Actual_Target_Type : Entity_Id; Actual_Targ_Typ : Entity_Id;
Make_Conversion : Boolean := False;
Root_Op_Typ : Entity_Id;
Cond : Node_Id; procedure Make_Tag_Check (Targ_Typ : Entity_Id);
-- Create a membership check to test whether Operand is a member
begin -- of Targ_Typ. If the original Target_Type is an access, include
if Is_Access_Type (Target_Type) then -- a test for null value. The check is inserted at N.
Actual_Operand_Type := Designated_Type (Operand_Type);
Actual_Target_Type := Designated_Type (Target_Type);
else
Actual_Operand_Type := Operand_Type;
Actual_Target_Type := Target_Type;
end if;
-- Ada 2005 (AI-251): Handle interface type conversion
if Is_Interface (Actual_Operand_Type) then --------------------
Expand_Interface_Conversion (N, Is_Static => False); -- Make_Tag_Check --
return; --------------------
end if;
if Is_Class_Wide_Type (Actual_Operand_Type) procedure Make_Tag_Check (Targ_Typ : Entity_Id) is
and then Root_Type (Actual_Operand_Type) /= Actual_Target_Type Cond : Node_Id;
and then Is_Ancestor
(Root_Type (Actual_Operand_Type),
Actual_Target_Type)
and then not Tag_Checks_Suppressed (Actual_Target_Type)
then
-- Conversion is valid for any descendant of the target type
Actual_Target_Type := Class_Wide_Type (Actual_Target_Type); begin
-- Generate:
-- [Constraint_Error
-- when Operand /= null
-- and then Operand.all not in Targ_Typ]
if Is_Access_Type (Target_Type) then if Is_Access_Type (Target_Type) then
Cond := Cond :=
...@@ -7628,24 +7618,105 @@ package body Exp_Ch4 is ...@@ -7628,24 +7618,105 @@ package body Exp_Ch4 is
Make_Not_In (Loc, Make_Not_In (Loc,
Left_Opnd => Left_Opnd =>
Make_Explicit_Dereference (Loc, Make_Explicit_Dereference (Loc,
Prefix => Prefix => Duplicate_Subexpr_No_Checks (Operand)),
Duplicate_Subexpr_No_Checks (Operand)), Right_Opnd => New_Reference_To (Targ_Typ, Loc)));
Right_Opnd =>
New_Reference_To (Actual_Target_Type, Loc))); -- Generate:
-- [Constraint_Error when Operand not in Targ_Typ]
else else
Cond := Cond :=
Make_Not_In (Loc, Make_Not_In (Loc,
Left_Opnd => Duplicate_Subexpr_No_Checks (Operand), Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
Right_Opnd => Right_Opnd => New_Reference_To (Targ_Typ, Loc));
New_Reference_To (Actual_Target_Type, Loc));
end if; end if;
Insert_Action (N, Insert_Action (N,
Make_Raise_Constraint_Error (Loc, Make_Raise_Constraint_Error (Loc,
Condition => Cond, Condition => Cond,
Reason => CE_Tag_Check_Failed)); Reason => CE_Tag_Check_Failed));
end Make_Tag_Check;
-- Start of processing
begin
if Is_Access_Type (Target_Type) then
Actual_Op_Typ := Designated_Type (Operand_Type);
Actual_Targ_Typ := Designated_Type (Target_Type);
else
Actual_Op_Typ := Operand_Type;
Actual_Targ_Typ := Target_Type;
end if;
Root_Op_Typ := Root_Type (Actual_Op_Typ);
-- Ada 2005 (AI-251): Handle interface type conversion
if Is_Interface (Actual_Op_Typ) then
Expand_Interface_Conversion (N, Is_Static => False);
return;
end if;
if not Tag_Checks_Suppressed (Actual_Targ_Typ) then
-- Create a runtime tag check for a downward class-wide type
-- conversion.
if Is_Class_Wide_Type (Actual_Op_Typ)
and then Root_Op_Typ /= Actual_Targ_Typ
and then Is_Ancestor (Root_Op_Typ, Actual_Targ_Typ)
then
Make_Tag_Check (Class_Wide_Type (Actual_Targ_Typ));
Make_Conversion := True;
end if;
-- AI05-0073: If the result subtype of the function is defined
-- by an access_definition designating a specific tagged type
-- T, a check is made that the result value is null or the tag
-- of the object designated by the result value identifies T.
-- Constraint_Error is raised if this check fails.
if Nkind (Parent (N)) = Sinfo.N_Return_Statement then
declare
Func : Entity_Id := Current_Scope;
Func_Typ : Entity_Id;
begin
-- Climb the scope stack looking for the enclosing
-- function.
while Present (Func)
and then Ekind (Func) /= E_Function
loop
Func := Scope (Func);
end loop;
-- The function's return subtype must be defined using
-- an access definition.
if Nkind (Result_Definition (Parent (Func))) =
N_Access_Definition
then
Func_Typ := Directly_Designated_Type (Etype (Func));
-- The return subtype denotes a specific tagged type,
-- in other words, a non class-wide type.
if Is_Tagged_Type (Func_Typ)
and then not Is_Class_Wide_Type (Func_Typ)
then
Make_Tag_Check (Actual_Targ_Typ);
Make_Conversion := True;
end if;
end if;
end;
end if;
-- We have generated a tag check for either a class-wide type
-- conversion or for AI05-0073.
if Make_Conversion then
declare declare
Conv : Node_Id; Conv : Node_Id;
begin begin
...@@ -7657,6 +7728,7 @@ package body Exp_Ch4 is ...@@ -7657,6 +7728,7 @@ package body Exp_Ch4 is
Analyze_And_Resolve (N, Target_Type); Analyze_And_Resolve (N, Target_Type);
end; end;
end if; end if;
end if;
end; end;
-- Case of other access type conversions -- Case of other access type conversions
......
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