Commit 20b5d666 by Javier Miranda Committed by Arnaud Charlet

exp_ch4.adb (Expand_N_Type_Conversion): Handle missing interface type conversion.

2006-10-31  Javier Miranda  <miranda@adacore.com>
	    Ed Schonberg  <schonberg@adacore.com>
	    Bob Duff  <duff@adacore.com>
	    Gary Dismukes  <dismukes@adacore.com>
	    Robert Dewar  <dewar@adacore.com>
        
        * exp_ch4.adb (Expand_N_Type_Conversion): Handle missing interface type
	conversion.
        (Expand_N_In): Do validity checks on range
	(Expand_Selected_Component): Use updated for of Denotes_Discriminant.
	(Expand_N_Allocator): For "new T", if the object is constrained by
	discriminant defaults, allocate the right amount of memory, rather than
	the maximum for type T.
	(Expand_Allocator_Expression): Suppress the call to Remove_Side_Effects
	when the allocator is initialized by a build-in-place call, since the
	allocator is already rewritten as a reference to the function result,
	and this prevents an unwanted duplication of the function call.
	Add with and use of Exp_Ch6.
	(Expand_Allocator_Expresssion): Check for an allocator whose expression
	is a call to build-in-place function and apply
	Make_Build_In_Place_Call_In_Allocator to the call (for both tagged and
	untagged designated types).
	(Expand_N_Unchecked_Type_Conversion): Do not do integer literal
	optimization if source or target is biased.
	(Expand_N_Allocator): Add comments for case of an allocator within a
	function that returns an anonymous access type designating tasks.
	(Expand_N_Allocator): apply discriminant checks for access
	discriminants of anonymous access types (AI-402, AI-416)

From-SVN: r118257
parent 3476f949
...@@ -31,8 +31,10 @@ with Elists; use Elists; ...@@ -31,8 +31,10 @@ with Elists; use Elists;
with Errout; use Errout; with Errout; use Errout;
with Exp_Aggr; use Exp_Aggr; with Exp_Aggr; use Exp_Aggr;
with Exp_Ch3; use Exp_Ch3; with Exp_Ch3; use Exp_Ch3;
with Exp_Ch6; use Exp_Ch6;
with Exp_Ch7; use Exp_Ch7; with Exp_Ch7; use Exp_Ch7;
with Exp_Ch9; use Exp_Ch9; with Exp_Ch9; use Exp_Ch9;
with Exp_Disp; use Exp_Disp;
with Exp_Fixd; use Exp_Fixd; with Exp_Fixd; use Exp_Fixd;
with Exp_Pakd; use Exp_Pakd; with Exp_Pakd; use Exp_Pakd;
with Exp_Tss; use Exp_Tss; with Exp_Tss; use Exp_Tss;
...@@ -192,7 +194,7 @@ package body Exp_Ch4 is ...@@ -192,7 +194,7 @@ package body Exp_Ch4 is
-- this by using Convert_To_Actual_Subtype if necessary). -- this by using Convert_To_Actual_Subtype if necessary).
procedure Rewrite_Comparison (N : Node_Id); procedure Rewrite_Comparison (N : Node_Id);
-- if N is the node for a comparison whose outcome can be determined at -- If N is the node for a comparison whose outcome can be determined at
-- compile time, then the node N can be rewritten with True or False. If -- compile time, then the node N can be rewritten with True or False. If
-- the outcome cannot be determined at compile time, the call has no -- the outcome cannot be determined at compile time, the call has no
-- effect. If N is a type conversion, then this processing is applied to -- effect. If N is a type conversion, then this processing is applied to
...@@ -382,12 +384,28 @@ package body Exp_Ch4 is ...@@ -382,12 +384,28 @@ package body Exp_Ch4 is
Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp); Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp);
Call_In_Place : Boolean := False;
Tag_Assign : Node_Id; Tag_Assign : Node_Id;
Tmp_Node : Node_Id; Tmp_Node : Node_Id;
begin begin
if Is_Tagged_Type (T) or else Controlled_Type (T) then if Is_Tagged_Type (T) or else Controlled_Type (T) then
-- Ada 2005 (AI-318-02): If the initialization expression is a
-- call to a build-in-place function, then access to the allocated
-- object must be passed to the function. Currently we limit such
-- functions to those with constrained limited result subtypes,
-- but eventually we plan to expand the allowed forms of funtions
-- that are treated as build-in-place.
if Ada_Version >= Ada_05
and then Is_Build_In_Place_Function_Call (Exp)
then
Make_Build_In_Place_Call_In_Allocator (N, Exp);
Call_In_Place := True;
end if;
-- Actions inserted before: -- Actions inserted before:
-- Temp : constant ptr_T := new T'(Expression); -- Temp : constant ptr_T := new T'(Expression);
-- <no CW> Temp._tag := T'tag; -- <no CW> Temp._tag := T'tag;
...@@ -397,7 +415,12 @@ package body Exp_Ch4 is ...@@ -397,7 +415,12 @@ package body Exp_Ch4 is
-- We analyze by hand the new internal allocator to avoid -- We analyze by hand the new internal allocator to avoid
-- any recursion and inappropriate call to Initialize -- any recursion and inappropriate call to Initialize
if not Aggr_In_Place then -- We don't want to remove side effects when the expression must be
-- built in place. In the case of a build-in-place function call,
-- that could lead to a duplication of the call, which was already
-- substituted for the allocator.
if not Aggr_In_Place and then not Call_In_Place then
Remove_Side_Effects (Exp); Remove_Side_Effects (Exp);
end if; end if;
...@@ -700,6 +723,18 @@ package body Exp_Ch4 is ...@@ -700,6 +723,18 @@ package body Exp_Ch4 is
end; end;
end if; end if;
-- Ada 2005 (AI-318-02): If the initialization expression is a
-- call to a build-in-place function, then access to the allocated
-- object must be passed to the function. Currently we limit such
-- functions to those with constrained limited result subtypes,
-- but eventually we plan to expand the allowed forms of funtions
-- that are treated as build-in-place.
if Ada_Version >= Ada_05
and then Is_Build_In_Place_Function_Call (Exp)
then
Make_Build_In_Place_Call_In_Allocator (N, Exp);
end if;
end if; end if;
exception exception
...@@ -2630,21 +2665,21 @@ package body Exp_Ch4 is ...@@ -2630,21 +2665,21 @@ package body Exp_Ch4 is
Set_Assignment_OK (Arg1); Set_Assignment_OK (Arg1);
Temp_Type := PtrT; Temp_Type := PtrT;
-- The initialization procedure expects a specific type. -- The initialization procedure expects a specific type. if
-- if the context is access to class wide, indicate that -- the context is access to class wide, indicate that the
-- the object being allocated has the right specific type. -- object being allocated has the right specific type.
if Is_Class_Wide_Type (Dtyp) then if Is_Class_Wide_Type (Dtyp) then
Arg1 := Unchecked_Convert_To (T, Arg1); Arg1 := Unchecked_Convert_To (T, Arg1);
end if; end if;
end if; end if;
-- If designated type is a concurrent type or if it is a -- If designated type is a concurrent type or if it is private
-- private type whose definition is a concurrent type, -- type whose definition is a concurrent type, the first
-- the first argument in the Init routine has to be -- argument in the Init routine has to be unchecked conversion
-- unchecked conversion to the corresponding record type. -- to the corresponding record type. If the designated type is
-- If the designated type is a derived type, we also -- a derived type, we also convert the argument to its root
-- convert the argument to its root type. -- type.
if Is_Concurrent_Type (T) then if Is_Concurrent_Type (T) then
Arg1 := Arg1 :=
...@@ -2671,29 +2706,31 @@ package body Exp_Ch4 is ...@@ -2671,29 +2706,31 @@ package body Exp_Ch4 is
Args := New_List (Arg1); Args := New_List (Arg1);
-- For the task case, pass the Master_Id of the access type -- For the task case, pass the Master_Id of the access type as
-- as the value of the _Master parameter, and _Chain as the -- the value of the _Master parameter, and _Chain as the value
-- value of the _Chain parameter (_Chain will be defined as -- of the _Chain parameter (_Chain will be defined as part of
-- part of the generated code for the allocator). -- the generated code for the allocator).
-- In Ada 2005, the context may be a function that returns an
-- anonymous access type. In that case the Master_Id has been
-- created when expanding the function declaration.
if Has_Task (T) then if Has_Task (T) then
if No (Master_Id (Base_Type (PtrT))) then if No (Master_Id (Base_Type (PtrT))) then
-- The designated type was an incomplete type, and -- The designated type was an incomplete type, and the
-- the access type did not get expanded. Salvage -- access type did not get expanded. Salvage it now.
-- it now.
Expand_N_Full_Type_Declaration Expand_N_Full_Type_Declaration
(Parent (Base_Type (PtrT))); (Parent (Base_Type (PtrT)));
end if; end if;
-- If the context of the allocator is a declaration or -- If the context of the allocator is a declaration or an
-- an assignment, we can generate a meaningful image for -- assignment, we can generate a meaningful image for it,
-- it, even though subsequent assignments might remove -- even though subsequent assignments might remove the
-- the connection between task and entity. We build this -- connection between task and entity. We build this image
-- image when the left-hand side is a simple variable, -- when the left-hand side is a simple variable, a simple
-- a simple indexed assignment or a simple selected -- indexed assignment or a simple selected component.
-- component.
if Nkind (Parent (N)) = N_Assignment_Statement then if Nkind (Parent (N)) = N_Assignment_Statement then
declare declare
...@@ -2745,26 +2782,60 @@ package body Exp_Ch4 is ...@@ -2745,26 +2782,60 @@ package body Exp_Ch4 is
-- Add discriminants if discriminated type -- Add discriminants if discriminated type
if Has_Discriminants (T) then declare
Discr := First_Elmt (Discriminant_Constraint (T)); Dis : Boolean := False;
Typ : Entity_Id;
while Present (Discr) loop begin
Append (New_Copy_Tree (Elists.Node (Discr)), Args); if Has_Discriminants (T) then
Next_Elmt (Discr); Dis := True;
end loop; Typ := T;
elsif Is_Private_Type (T) elsif Is_Private_Type (T)
and then Present (Full_View (T)) and then Present (Full_View (T))
and then Has_Discriminants (Full_View (T)) and then Has_Discriminants (Full_View (T))
then then
Discr := Dis := True;
First_Elmt (Discriminant_Constraint (Full_View (T))); Typ := Full_View (T);
end if;
while Present (Discr) loop if Dis then
Append (New_Copy_Tree (Elists.Node (Discr)), Args); -- If the allocated object will be constrained by the
Next_Elmt (Discr); -- default values for discriminants, then build a
end loop; -- subtype with those defaults, and change the allocated
end if; -- subtype to that. Note that this happens in fewer
-- cases in Ada 2005 (AI-363).
if not Is_Constrained (Typ)
and then Present (Discriminant_Default_Value
(First_Discriminant (Typ)))
and then (Ada_Version < Ada_05
or else not Has_Constrained_Partial_View (Typ))
then
Typ := Build_Default_Subtype (Typ, N);
Set_Expression (N, New_Reference_To (Typ, Loc));
end if;
Discr := First_Elmt (Discriminant_Constraint (Typ));
while Present (Discr) loop
Node := Elists.Node (Discr);
Append (New_Copy_Tree (Elists.Node (Discr)), Args);
-- AI-416: when the discriminant constraint is an
-- anonymous access type make sure an accessibility
-- check is inserted if necessary (3.10.2(22.q/2))
if Ada_Version >= Ada_05
and then
Ekind (Etype (Node)) = E_Anonymous_Access_Type
then
Apply_Accessibility_Check (Node, Typ);
end if;
Next_Elmt (Discr);
end loop;
end if;
end;
-- We set the allocator as analyzed so that when we analyze the -- We set the allocator as analyzed so that when we analyze the
-- expression actions node, we do not get an unwanted recursive -- expression actions node, we do not get an unwanted recursive
...@@ -2780,8 +2851,8 @@ package body Exp_Ch4 is ...@@ -2780,8 +2851,8 @@ package body Exp_Ch4 is
-- <CTRL> Attach_To_Final_List (Finalizable (Temp.all)); -- <CTRL> Attach_To_Final_List (Finalizable (Temp.all));
-- <CTRL> Initialize (Finalizable (Temp.all)); -- <CTRL> Initialize (Finalizable (Temp.all));
-- Here ptr_T is the pointer type for the allocator, and T -- Here ptr_T is the pointer type for the allocator, and is the
-- is the subtype of the allocator. -- subtype of the allocator.
Temp_Decl := Temp_Decl :=
Make_Object_Declaration (Loc, Make_Object_Declaration (Loc,
...@@ -2798,8 +2869,8 @@ package body Exp_Ch4 is ...@@ -2798,8 +2869,8 @@ package body Exp_Ch4 is
Insert_Action (N, Temp_Decl, Suppress => All_Checks); Insert_Action (N, Temp_Decl, Suppress => All_Checks);
-- If the designated type is task type or contains tasks, -- If the designated type is a task type or contains tasks,
-- Create block to activate created tasks, and insert -- create block to activate created tasks, and insert
-- declaration for Task_Image variable ahead of call. -- declaration for Task_Image variable ahead of call.
if Has_Task (T) then if Has_Task (T) then
...@@ -2899,8 +2970,8 @@ package body Exp_Ch4 is ...@@ -2899,8 +2970,8 @@ package body Exp_Ch4 is
-- Expand_N_And_Then -- -- Expand_N_And_Then --
----------------------- -----------------------
-- Expand into conditional expression if Actions present, and also -- Expand into conditional expression if Actions present, and also deal
-- deal with optimizing case of arguments being True or False. -- with optimizing case of arguments being True or False.
procedure Expand_N_And_Then (N : Node_Id) is procedure Expand_N_And_Then (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N); Loc : constant Source_Ptr := Sloc (N);
...@@ -2935,9 +3006,9 @@ package body Exp_Ch4 is ...@@ -2935,9 +3006,9 @@ package body Exp_Ch4 is
Adjust_Result_Type (N, Typ); Adjust_Result_Type (N, Typ);
return; return;
-- If left argument is False, change (False and then Right) to -- If left argument is False, change (False and then Right) to False.
-- False. In this case we can forget the actions associated with -- In this case we can forget the actions associated with Right,
-- Right, since they will never be executed. -- since they will never be executed.
elsif Entity (Left) = Standard_False then elsif Entity (Left) = Standard_False then
Kill_Dead_Code (Right); Kill_Dead_Code (Right);
...@@ -3134,6 +3205,13 @@ package body Exp_Ch4 is ...@@ -3134,6 +3205,13 @@ package body Exp_Ch4 is
return; return;
end if; end if;
-- Do validity check on operands
if Validity_Checks_On and Validity_Check_Operands then
Ensure_Valid (Left_Opnd (N));
Validity_Check_Range (Right_Opnd (N));
end if;
-- Case of explicit range -- Case of explicit range
if Nkind (Rop) = N_Range then if Nkind (Rop) = N_Range then
...@@ -3235,11 +3313,10 @@ package body Exp_Ch4 is ...@@ -3235,11 +3313,10 @@ package body Exp_Ch4 is
if Is_Tagged_Type (Typ) then if Is_Tagged_Type (Typ) then
-- No expansion will be performed when Java_VM, as the -- No expansion will be performed when Java_VM, as the JVM back
-- JVM back end will handle the membership tests directly -- end will handle the membership tests directly (tags are not
-- (tags are not explicitly represented in Java objects, -- explicitly represented in Java objects, so the normal tagged
-- so the normal tagged membership expansion is not what -- membership expansion is not what we want).
-- we want).
if not Java_VM then if not Java_VM then
Rewrite (N, Tagged_Membership (N)); Rewrite (N, Tagged_Membership (N));
...@@ -3248,7 +3325,7 @@ package body Exp_Ch4 is ...@@ -3248,7 +3325,7 @@ package body Exp_Ch4 is
return; return;
-- If type is scalar type, rewrite as x in t'first .. t'last -- If type is scalar type, rewrite as x in t'first .. t'last.
-- This reason we do this is that the bounds may have the wrong -- This reason we do this is that the bounds may have the wrong
-- type if they come from the original type definition. -- type if they come from the original type definition.
...@@ -6149,7 +6226,7 @@ package body Exp_Ch4 is ...@@ -6149,7 +6226,7 @@ package body Exp_Ch4 is
if if
Denotes_Discriminant Denotes_Discriminant
(Node (Dcon), Check_Protected => True) (Node (Dcon), Check_Concurrent => True)
then then
exit Discr_Loop; exit Discr_Loop;
...@@ -6847,6 +6924,13 @@ package body Exp_Ch4 is ...@@ -6847,6 +6924,13 @@ package body Exp_Ch4 is
Actual_Target_Type := Target_Type; Actual_Target_Type := Target_Type;
end if; end if;
-- Ada 2005 (AI-251): Handle interface type conversion
if Is_Interface (Actual_Operand_Type) then
Expand_Interface_Conversion (N, Is_Static => False);
return;
end if;
if Is_Class_Wide_Type (Actual_Operand_Type) if Is_Class_Wide_Type (Actual_Operand_Type)
and then Root_Type (Actual_Operand_Type) /= Actual_Target_Type and then Root_Type (Actual_Operand_Type) /= Actual_Target_Type
and then Is_Ancestor and then Is_Ancestor
...@@ -7242,8 +7326,14 @@ package body Exp_Ch4 is ...@@ -7242,8 +7326,14 @@ package body Exp_Ch4 is
-- flag is set, since then the value may be outside the expected range. -- flag is set, since then the value may be outside the expected range.
-- This happens in the Normalize_Scalars case. -- This happens in the Normalize_Scalars case.
-- We also skip this if either the target or operand type is biased
-- because in this case, the unchecked conversion is supposed to
-- preserve the bit pattern, not the integer value.
if Is_Integer_Type (Target_Type) if Is_Integer_Type (Target_Type)
and then not Has_Biased_Representation (Target_Type)
and then Is_Integer_Type (Operand_Type) and then Is_Integer_Type (Operand_Type)
and then not Has_Biased_Representation (Operand_Type)
and then Compile_Time_Known_Value (Operand) and then Compile_Time_Known_Value (Operand)
and then not Kill_Range_Check (N) and then not Kill_Range_Check (N)
then then
...@@ -7692,17 +7782,17 @@ package body Exp_Ch4 is ...@@ -7692,17 +7782,17 @@ package body Exp_Ch4 is
-- type elem is (<>); -- type elem is (<>);
-- type index is (<>); -- type index is (<>);
-- type a is array (index range <>) of elem; -- type a is array (index range <>) of elem;
--
-- function Gnnn (X : a; Y: a) return boolean is -- function Gnnn (X : a; Y: a) return boolean is
-- J : index := Y'first; -- J : index := Y'first;
--
-- begin -- begin
-- if X'length = 0 then -- if X'length = 0 then
-- return false; -- return false;
--
-- elsif Y'length = 0 then -- elsif Y'length = 0 then
-- return true; -- return true;
--
-- else -- else
-- for I in X'range loop -- for I in X'range loop
-- if X (I) = Y (J) then -- if X (I) = Y (J) then
...@@ -7711,12 +7801,12 @@ package body Exp_Ch4 is ...@@ -7711,12 +7801,12 @@ package body Exp_Ch4 is
-- else -- else
-- J := index'succ (J); -- J := index'succ (J);
-- end if; -- end if;
--
-- else -- else
-- return X (I) > Y (J); -- return X (I) > Y (J);
-- end if; -- end if;
-- end loop; -- end loop;
--
-- return X'length > Y'length; -- return X'length > Y'length;
-- end if; -- end if;
-- end Gnnn; -- end Gnnn;
...@@ -8077,24 +8167,25 @@ package body Exp_Ch4 is ...@@ -8077,24 +8167,25 @@ package body Exp_Ch4 is
begin begin
if Nkind (N) = N_Type_Conversion then if Nkind (N) = N_Type_Conversion then
Rewrite_Comparison (Expression (N)); Rewrite_Comparison (Expression (N));
return;
elsif Nkind (N) not in N_Op_Compare then elsif Nkind (N) not in N_Op_Compare then
null; return;
end if;
else declare
declare Typ : constant Entity_Id := Etype (N);
Typ : constant Entity_Id := Etype (N); Op1 : constant Node_Id := Left_Opnd (N);
Op1 : constant Node_Id := Left_Opnd (N); Op2 : constant Node_Id := Right_Opnd (N);
Op2 : constant Node_Id := Right_Opnd (N);
Res : constant Compare_Result := Compile_Time_Compare (Op1, Op2); Res : constant Compare_Result := Compile_Time_Compare (Op1, Op2);
-- Res indicates if compare outcome can be compile time determined -- Res indicates if compare outcome can be compile time determined
True_Result : Boolean; True_Result : Boolean;
False_Result : Boolean; False_Result : Boolean;
begin begin
case N_Op_Compare (Nkind (N)) is case N_Op_Compare (Nkind (N)) is
when N_Op_Eq => when N_Op_Eq =>
True_Result := Res = EQ; True_Result := Res = EQ;
False_Result := Res = LT or else Res = GT or else Res = NE; False_Result := Res = LT or else Res = GT or else Res = NE;
...@@ -8142,24 +8233,23 @@ package body Exp_Ch4 is ...@@ -8142,24 +8233,23 @@ package body Exp_Ch4 is
when N_Op_Ne => when N_Op_Ne =>
True_Result := Res = NE or else Res = GT or else Res = LT; True_Result := Res = NE or else Res = GT or else Res = LT;
False_Result := Res = EQ; False_Result := Res = EQ;
end case; end case;
if True_Result then if True_Result then
Rewrite (N, Rewrite (N,
Convert_To (Typ, Convert_To (Typ,
New_Occurrence_Of (Standard_True, Sloc (N)))); New_Occurrence_Of (Standard_True, Sloc (N))));
Analyze_And_Resolve (N, Typ); Analyze_And_Resolve (N, Typ);
Warn_On_Known_Condition (N); Warn_On_Known_Condition (N);
elsif False_Result then elsif False_Result then
Rewrite (N, Rewrite (N,
Convert_To (Typ, Convert_To (Typ,
New_Occurrence_Of (Standard_False, Sloc (N)))); New_Occurrence_Of (Standard_False, Sloc (N))));
Analyze_And_Resolve (N, Typ); Analyze_And_Resolve (N, Typ);
Warn_On_Known_Condition (N); Warn_On_Known_Condition (N);
end if; end if;
end; end;
end if;
end Rewrite_Comparison; end Rewrite_Comparison;
---------------------------- ----------------------------
......
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