summaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch6.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_ch6.adb')
-rw-r--r--gcc/ada/exp_ch6.adb58
1 files changed, 45 insertions, 13 deletions
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index edb31846708..951d272f54a 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -529,12 +529,13 @@ package body Exp_Ch6 is
---------------------------
procedure Add_Call_By_Copy_Code is
- Expr : Node_Id;
- Init : Node_Id;
- Temp : Entity_Id;
- Var : Entity_Id;
- V_Typ : Entity_Id;
- Crep : Boolean;
+ Expr : Node_Id;
+ Init : Node_Id;
+ Temp : Entity_Id;
+ Indic : Node_Id := New_Occurrence_Of (Etype (Formal), Loc);
+ Var : Entity_Id;
+ V_Typ : Entity_Id;
+ Crep : Boolean;
begin
Temp := Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
@@ -560,10 +561,14 @@ package body Exp_Ch6 is
-- parameter where the formal is an unconstrained array (in the
-- latter case, we have to pass in an object with bounds).
+ -- If this is an out parameter, the initial copy is wasteful, so as
+ -- an optimization for the one-dimensional case we extract the
+ -- bounds of the actual and build an uninitialized temporary of the
+ -- right size.
+
if Ekind (Formal) = E_In_Out_Parameter
or else (Is_Array_Type (Etype (Formal))
- and then
- not Is_Constrained (Etype (Formal)))
+ and then not Is_Constrained (Etype (Formal)))
then
if Nkind (Actual) = N_Type_Conversion then
if Conversion_OK (Actual) then
@@ -573,6 +578,33 @@ package body Exp_Ch6 is
Init := Convert_To
(Etype (Formal), New_Occurrence_Of (Var, Loc));
end if;
+
+ elsif Ekind (Formal) = E_Out_Parameter
+ and then Number_Dimensions (Etype (Formal)) = 1
+ and then not Has_Non_Null_Base_Init_Proc (Etype (Formal))
+ then
+ -- Actual is a one-dimensional array or slice, and the type
+ -- requires no initialization. Create a temporary of the
+ -- right size, but do copy actual into it (optimization).
+
+ Init := Empty;
+ Indic :=
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Etype (Formal), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => New_List (
+ Make_Range (Loc,
+ Low_Bound =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Var, Loc),
+ Attribute_name => Name_First),
+ High_Bound =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Var, Loc),
+ Attribute_Name => Name_Last)))));
+
else
Init := New_Occurrence_Of (Var, Loc);
end if;
@@ -607,8 +639,7 @@ package body Exp_Ch6 is
N_Node :=
Make_Object_Declaration (Loc,
Defining_Identifier => Temp,
- Object_Definition =>
- New_Occurrence_Of (Etype (Formal), Loc),
+ Object_Definition => Indic,
Expression => Init);
Set_Assignment_OK (N_Node);
Insert_Action (N, N_Node);
@@ -2527,9 +2558,12 @@ package body Exp_Ch6 is
-- In this case, for optimization purposes, we do not need to
-- continue the traversal once more than one use is encountered.
+ ----------------
+ -- Count_Uses --
+ ----------------
+
function Count_Uses (N : Node_Id) return Traverse_Result is
begin
-
-- The original node is an identifier
if Nkind (N) = N_Identifier
@@ -2565,10 +2599,8 @@ package body Exp_Ch6 is
-- Start of processing for Formal_Is_Used_Once
begin
-
Count_Formal_Uses (Orig_Bod);
return Use_Counter = 1;
-
end Formal_Is_Used_Once;
-- Start of processing for Expand_Inlined_Call