aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_util.adb
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
committerIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
commite252b51ccde010cbd2a146485d8045103cd99533 (patch)
treee060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/ada/exp_util.adb
parentf10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff)
parent104c05c5284b7822d770ee51a7d91946c7e56d50 (diff)
downloadgcc-e252b51ccde010cbd2a146485d8045103cd99533.zip
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/ada/exp_util.adb')
-rw-r--r--gcc/ada/exp_util.adb487
1 files changed, 362 insertions, 125 deletions
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index cf4059a..2584041 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2021, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -23,46 +23,50 @@
-- --
------------------------------------------------------------------------------
-with Aspects; use Aspects;
-with Atree; use Atree;
-with Casing; use Casing;
-with Checks; use Checks;
-with Debug; use Debug;
-with Einfo; use Einfo;
-with Elists; use Elists;
-with Errout; use Errout;
-with Exp_Aggr; use Exp_Aggr;
-with Exp_Ch6; use Exp_Ch6;
-with Exp_Ch7; use Exp_Ch7;
-with Exp_Ch11; use Exp_Ch11;
-with Ghost; use Ghost;
-with Inline; use Inline;
-with Itypes; use Itypes;
-with Lib; use Lib;
-with Nlists; use Nlists;
-with Nmake; use Nmake;
-with Opt; use Opt;
-with Restrict; use Restrict;
-with Rident; use Rident;
-with Sem; use Sem;
-with Sem_Aux; use Sem_Aux;
-with Sem_Ch3; use Sem_Ch3;
-with Sem_Ch6; use Sem_Ch6;
-with Sem_Ch8; use Sem_Ch8;
-with Sem_Ch12; use Sem_Ch12;
-with Sem_Ch13; use Sem_Ch13;
-with Sem_Disp; use Sem_Disp;
-with Sem_Elab; use Sem_Elab;
-with Sem_Eval; use Sem_Eval;
-with Sem_Res; use Sem_Res;
-with Sem_Type; use Sem_Type;
-with Sem_Util; use Sem_Util;
-with Snames; use Snames;
-with Stand; use Stand;
-with Stringt; use Stringt;
-with Tbuild; use Tbuild;
-with Ttypes; use Ttypes;
-with Validsw; use Validsw;
+with Aspects; use Aspects;
+with Atree; use Atree;
+with Casing; use Casing;
+with Checks; use Checks;
+with Debug; use Debug;
+with Einfo; use Einfo;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils; use Einfo.Utils;
+with Elists; use Elists;
+with Errout; use Errout;
+with Exp_Aggr; use Exp_Aggr;
+with Exp_Ch6; use Exp_Ch6;
+with Exp_Ch7; use Exp_Ch7;
+with Exp_Ch11; use Exp_Ch11;
+with Freeze; use Freeze;
+with Ghost; use Ghost;
+with Inline; use Inline;
+with Itypes; use Itypes;
+with Lib; use Lib;
+with Nlists; use Nlists;
+with Nmake; use Nmake;
+with Opt; use Opt;
+with Restrict; use Restrict;
+with Rident; use Rident;
+with Sem; use Sem;
+with Sem_Aux; use Sem_Aux;
+with Sem_Ch3; use Sem_Ch3;
+with Sem_Ch6; use Sem_Ch6;
+with Sem_Ch8; use Sem_Ch8;
+with Sem_Ch12; use Sem_Ch12;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Disp; use Sem_Disp;
+with Sem_Elab; use Sem_Elab;
+with Sem_Eval; use Sem_Eval;
+with Sem_Res; use Sem_Res;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Sinfo.Utils; use Sinfo.Utils;
+with Snames; use Snames;
+with Stand; use Stand;
+with Stringt; use Stringt;
+with Tbuild; use Tbuild;
+with Ttypes; use Ttypes;
+with Validsw; use Validsw;
with GNAT.HTable;
package body Exp_Util is
@@ -834,7 +838,7 @@ package body Exp_Util is
-- Optimize the case where we are using the default Global_Pool_Object,
-- and we don't need the heavy finalization machinery.
- elsif Pool_Id = RTE (RE_Global_Pool_Object)
+ elsif Is_RTE (Pool_Id, RE_Global_Pool_Object)
and then not Needs_Finalization (Desig_Typ)
then
return;
@@ -1327,6 +1331,7 @@ package body Exp_Util is
and then Is_Primitive_Wrapper (New_E)
and then Is_Primitive_Wrapper (Subp)
and then Scope (Subp) = Scope (New_E)
+ and then Chars (Pragma_Identifier (Prag)) = Name_Precondition
then
Error_Msg_Node_2 := Wrapped_Entity (Subp);
Error_Msg_NE
@@ -1462,9 +1467,7 @@ package body Exp_Util is
Make_Procedure_Call_Statement (Loc,
Name => New_Occurrence_Of (Proc_Id, Loc),
Parameter_Associations => New_List (
- Make_Unchecked_Type_Conversion (Loc,
- Subtype_Mark => New_Occurrence_Of (Formal_Typ, Loc),
- Expression => Obj_Name)));
+ Unchecked_Convert_To (Formal_Typ, Obj_Name)));
end Build_DIC_Call;
------------------------------
@@ -1854,12 +1857,18 @@ package body Exp_Util is
end if;
-- Once the DIC assertion expression is fully processed, add a check
- -- to the statements of the DIC procedure.
-
- Add_DIC_Check
- (DIC_Prag => DIC_Prag,
- DIC_Expr => Expr,
- Stmts => Stmts);
+ -- to the statements of the DIC procedure (unless the type is an
+ -- abstract type, in which case we don't want the possibility of
+ -- generating a call to an abstract function of the type; such DIC
+ -- procedures can never be called in any case, so not generating the
+ -- check at all is OK).
+
+ if not Is_Abstract_Type (DIC_Typ) or else GNATprove_Mode then
+ Add_DIC_Check
+ (DIC_Prag => DIC_Prag,
+ DIC_Expr => Expr,
+ Stmts => Stmts);
+ end if;
end Add_Own_DIC;
---------------------
@@ -2180,7 +2189,7 @@ package body Exp_Util is
-- Perform minor decoration in case the body is not analyzed
- Set_Ekind (Proc_Body_Id, E_Subprogram_Body);
+ Mutate_Ekind (Proc_Body_Id, E_Subprogram_Body);
Set_Etype (Proc_Body_Id, Standard_Void_Type);
Set_Scope (Proc_Body_Id, Current_Scope);
Set_SPARK_Pragma (Proc_Body_Id, SPARK_Pragma (Proc_Id));
@@ -2347,7 +2356,7 @@ package body Exp_Util is
-- Perform minor decoration in case the declaration is not analyzed
- Set_Ekind (Proc_Id, E_Procedure);
+ Mutate_Ekind (Proc_Id, E_Procedure);
Set_Etype (Proc_Id, Standard_Void_Type);
Set_Is_DIC_Procedure (Proc_Id);
Set_Scope (Proc_Id, Current_Scope);
@@ -2399,7 +2408,7 @@ package body Exp_Util is
-- Perform minor decoration in case the declaration is not analyzed
- Set_Ekind (Obj_Id, E_In_Parameter);
+ Mutate_Ekind (Obj_Id, E_In_Parameter);
Set_Etype (Obj_Id, Work_Typ);
Set_Scope (Obj_Id, Proc_Id);
@@ -3669,7 +3678,7 @@ package body Exp_Util is
-- Perform minor decoration in case the body is not analyzed
- Set_Ekind (Proc_Body_Id, E_Subprogram_Body);
+ Mutate_Ekind (Proc_Body_Id, E_Subprogram_Body);
Set_Etype (Proc_Body_Id, Standard_Void_Type);
Set_Scope (Proc_Body_Id, Current_Scope);
@@ -3807,7 +3816,7 @@ package body Exp_Util is
-- Perform minor decoration in case the declaration is not analyzed
- Set_Ekind (Proc_Id, E_Procedure);
+ Mutate_Ekind (Proc_Id, E_Procedure);
Set_Etype (Proc_Id, Standard_Void_Type);
Set_Scope (Proc_Id, Current_Scope);
@@ -3893,7 +3902,7 @@ package body Exp_Util is
-- Perform minor decoration in case the declaration is not analyzed
- Set_Ekind (Obj_Id, E_In_Parameter);
+ Mutate_Ekind (Obj_Id, E_In_Parameter);
Set_Etype (Obj_Id, Obj_Typ);
Set_Scope (Obj_Id, Proc_Id);
@@ -4697,7 +4706,7 @@ package body Exp_Util is
-- type Ptr_Typ is access all Desig_Typ;
Ptr_Typ := Make_Temporary (Loc, 'A');
- Set_Ekind (Ptr_Typ, E_General_Access_Type);
+ Mutate_Ekind (Ptr_Typ, E_General_Access_Type);
Set_Directly_Designated_Type (Ptr_Typ, Desig_Typ);
Ptr_Decl :=
@@ -4714,7 +4723,7 @@ package body Exp_Util is
-- Hook : Ptr_Typ := null;
Hook_Id := Make_Temporary (Loc, 'T');
- Set_Ekind (Hook_Id, E_Variable);
+ Mutate_Ekind (Hook_Id, E_Variable);
Set_Etype (Hook_Id, Ptr_Typ);
Hook_Decl :=
@@ -5305,6 +5314,195 @@ package body Exp_Util is
end if;
end Evolve_Or_Else;
+ -------------------------------
+ -- Expand_Sliding_Conversion --
+ -------------------------------
+
+ procedure Expand_Sliding_Conversion (N : Node_Id; Arr_Typ : Entity_Id) is
+
+ pragma Assert (Is_Array_Type (Arr_Typ)
+ and then not Is_Constrained (Arr_Typ)
+ and then Is_Fixed_Lower_Bound_Array_Subtype (Arr_Typ));
+
+ Constraints : List_Id;
+ Index : Node_Id := First_Index (Arr_Typ);
+ Loc : constant Source_Ptr := Sloc (N);
+ Subt_Decl : Node_Id;
+ Subt : Entity_Id;
+ Subt_Low : Node_Id;
+ Subt_High : Node_Id;
+
+ Act_Subt : Entity_Id;
+ Act_Index : Node_Id;
+ Act_Low : Node_Id;
+ Act_High : Node_Id;
+ Adjust_Incr : Node_Id;
+ Dimension : Int := 0;
+ All_FLBs_Match : Boolean := True;
+
+ begin
+ -- This procedure is called during semantic analysis, and we only expand
+ -- a sliding conversion when Expander_Active, to avoid doing it during
+ -- preanalysis (which can lead to problems with the target subtype not
+ -- getting properly expanded during later full analysis). Also, sliding
+ -- should never be needed for string literals, because their bounds are
+ -- determined directly based on the fixed lower bound of Arr_Typ and
+ -- their length.
+
+ if Expander_Active and then Nkind (N) /= N_String_Literal then
+ Constraints := New_List;
+
+ Act_Subt := Get_Actual_Subtype (N);
+ Act_Index := First_Index (Act_Subt);
+
+ -- Loop over the indexes of the fixed-lower-bound array type or
+ -- subtype to build up an index constraint for constructing the
+ -- subtype that will be the target of a conversion of the array
+ -- object that may need a sliding conversion.
+
+ while Present (Index) loop
+ pragma Assert (Present (Act_Index));
+
+ Dimension := Dimension + 1;
+
+ Get_Index_Bounds (Act_Index, Act_Low, Act_High);
+
+ -- If Index defines a normal unconstrained range (range <>),
+ -- then we will simply use the bounds of the actual subtype's
+ -- corresponding index range.
+
+ if not Is_Fixed_Lower_Bound_Index_Subtype (Etype (Index)) then
+ Subt_Low := Act_Low;
+ Subt_High := Act_High;
+
+ -- Otherwise, a range will be created with a low bound given by
+ -- the fixed lower bound of the array subtype's index, and with
+ -- high bound given by (Actual'Length + fixed lower bound - 1).
+
+ else
+ if Nkind (Index) = N_Subtype_Indication then
+ Subt_Low :=
+ New_Copy_Tree
+ (Low_Bound (Range_Expression (Constraint (Index))));
+ else
+ pragma Assert (Nkind (Index) = N_Range);
+
+ Subt_Low := New_Copy_Tree (Low_Bound (Index));
+ end if;
+
+ -- If either we have a nonstatic lower bound, or the target and
+ -- source subtypes are statically known to have unequal lower
+ -- bounds, then we will need to make a subtype conversion to
+ -- slide the bounds. However, if all of the indexes' lower
+ -- bounds are static and known to be equal (the common case),
+ -- then no conversion will be needed, and we'll end up not
+ -- creating the subtype or the conversion (though we still
+ -- build up the index constraint, which will simply be unused).
+
+ if not (Compile_Time_Known_Value (Subt_Low)
+ and then Compile_Time_Known_Value (Act_Low))
+ or else Expr_Value (Subt_Low) /= Expr_Value (Act_Low)
+ then
+ All_FLBs_Match := False;
+ end if;
+
+ -- Apply 'Pos to lower bound, which may be of an enumeration
+ -- type, before subtracting.
+
+ Adjust_Incr :=
+ Make_Op_Subtract (Loc,
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Etype (Act_Index), Loc),
+ Attribute_Name =>
+ Name_Pos,
+ Expressions =>
+ New_List (New_Copy_Tree (Subt_Low))),
+ Make_Integer_Literal (Loc, 1));
+
+ -- Apply 'Val to the result of adding the increment to the
+ -- length, to handle indexes of enumeration types.
+
+ Subt_High :=
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Etype (Act_Index), Loc),
+ Attribute_Name =>
+ Name_Val,
+ Expressions =>
+ New_List (Make_Op_Add (Loc,
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Act_Subt, Loc),
+ Attribute_Name =>
+ Name_Length,
+ Expressions =>
+ New_List
+ (Make_Integer_Literal
+ (Loc, Dimension))),
+ Adjust_Incr)));
+ end if;
+
+ Append (Make_Range (Loc, Subt_Low, Subt_High), Constraints);
+
+ Next (Index);
+ Next (Act_Index);
+ end loop;
+
+ -- If for each index with a fixed lower bound (FLB), the lower bound
+ -- of the corresponding index of the actual subtype is statically
+ -- known be equal to the FLB, then a sliding conversion isn't needed
+ -- at all, so just return without building a subtype or conversion.
+
+ if All_FLBs_Match then
+ return;
+ end if;
+
+ -- A sliding conversion is needed, so create the target subtype using
+ -- the index constraint created above, and rewrite the expression
+ -- as a conversion to that subtype.
+
+ Subt := Make_Temporary (Loc, 'S', Related_Node => N);
+ Set_Is_Internal (Subt);
+
+ Subt_Decl :=
+ Make_Subtype_Declaration (Loc,
+ Defining_Identifier => Subt,
+ Subtype_Indication =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Arr_Typ, Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => Constraints)));
+
+ Mark_Rewrite_Insertion (Subt_Decl);
+
+ -- The actual subtype is an Itype, so we analyze the declaration,
+ -- but do not attach it to the tree.
+
+ Set_Parent (Subt_Decl, N);
+ Set_Is_Itype (Subt);
+ Analyze (Subt_Decl, Suppress => All_Checks);
+ Set_Associated_Node_For_Itype (Subt, N);
+ Set_Has_Delayed_Freeze (Subt, False);
+
+ -- We need to freeze the actual subtype immediately. This is needed
+ -- because otherwise this Itype will not get frozen at all, and it is
+ -- always safe to freeze on creation because any associated types
+ -- must be frozen at this point.
+
+ Freeze_Itype (Subt, N);
+
+ Rewrite (N,
+ Make_Type_Conversion (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Subt, Loc),
+ Expression => Relocate_Node (N)));
+ Analyze (N);
+ end if;
+ end Expand_Sliding_Conversion;
+
-----------------------------------------
-- Expand_Static_Predicates_In_Choices --
-----------------------------------------
@@ -5312,7 +5510,7 @@ package body Exp_Util is
procedure Expand_Static_Predicates_In_Choices (N : Node_Id) is
pragma Assert (Nkind (N) in N_Case_Statement_Alternative | N_Variant);
- Choices : constant List_Id := Discrete_Choices (N);
+ Choices : List_Id := Discrete_Choices (N);
Choice : Node_Id;
Next_C : Node_Id;
@@ -5320,6 +5518,13 @@ package body Exp_Util is
C : Node_Id;
begin
+ -- If this is an "others" alternative, we need to process any static
+ -- predicates in its Others_Discrete_Choices.
+
+ if Nkind (First (Choices)) = N_Others_Choice then
+ Choices := Others_Discrete_Choices (First (Choices));
+ end if;
+
Choice := First (Choices);
while Present (Choice) loop
Next_C := Next (Choice);
@@ -6203,6 +6408,9 @@ package body Exp_Util is
| N_Discriminant_Association
| N_Parameter_Association
| N_Pragma_Argument_Association
+ | N_Aggregate
+ | N_Delta_Aggregate
+ | N_Extension_Aggregate
and then Nkind (Parent (Par)) not in N_Function_Call
| N_Procedure_Call_Statement
| N_Entry_Call_Statement
@@ -7193,8 +7401,8 @@ package body Exp_Util is
-- Actions belong to the then expression, temporarily place
-- them as Then_Actions of the if expression. They will be
- -- moved to the proper place later when the if expression
- -- is expanded.
+ -- moved to the proper place later when the if expression is
+ -- expanded.
elsif N = ThenX then
if Present (Then_Actions (P)) then
@@ -7207,10 +7415,7 @@ package body Exp_Util is
return;
- -- Actions belong to the else expression, temporarily place
- -- them as Else_Actions of the if expression. They will be
- -- moved to the proper place later when the if expression
- -- is expanded.
+ -- Else_Actions is treated the same as Then_Actions above
elsif N = ElseX then
if Present (Else_Actions (P)) then
@@ -8727,26 +8932,6 @@ package body Exp_Util is
end if;
end if;
- -- The following code is historical, it used to be present but it
- -- is too cautious, because the front-end does not know the proper
- -- default alignments for the target. Also, if the alignment is
- -- not known, the front end can't know in any case. If a copy is
- -- needed, the back-end will take care of it. This whole section
- -- including this comment can be removed later ???
-
- -- If the component reference is for a record that has a specified
- -- alignment, and we either know it is too small, or cannot tell,
- -- then the component may be unaligned.
-
- -- What is the following commented out code ???
-
- -- if Known_Alignment (Etype (P))
- -- and then Alignment (Etype (P)) < Ttypes.Maximum_Alignment
- -- and then M > Alignment (Etype (P))
- -- then
- -- return True;
- -- end if;
-
-- Case of component clause present which may specify an
-- unaligned position.
@@ -8863,7 +9048,7 @@ package body Exp_Util is
if Target_Strict_Alignment
and then Known_Alignment (Ptyp)
- and then (Unknown_Alignment (Styp)
+ and then (not Known_Alignment (Styp)
or else Alignment (Styp) > Alignment (Ptyp))
then
return True;
@@ -8887,7 +9072,7 @@ package body Exp_Util is
begin
if Present (Component_Clause (Field))
and then
- (Unknown_Alignment (Styp)
+ (not Known_Alignment (Styp)
or else
(Component_Bit_Offset (Field) mod
(System_Storage_Unit * Alignment (Styp))) /= 0)
@@ -9075,7 +9260,7 @@ package body Exp_Util is
Is_Class_Wide_Type (Etype (Obj_Id))
and then Present (Expr)
and then Nkind (Expr) = N_Unchecked_Type_Conversion
- and then Etype (Expression (Expr)) = RTE (RE_Tag);
+ and then Is_RTE (Etype (Expression (Expr)), RE_Tag);
end Is_Tag_To_Class_Wide_Conversion;
--------------------------------
@@ -9196,7 +9381,7 @@ package body Exp_Util is
-- True if object reference with volatile type
- elsif Is_Volatile_Object (N) then
+ elsif Is_Volatile_Object_Ref (N) then
return True;
-- True if reference to volatile entity
@@ -9251,28 +9436,33 @@ package body Exp_Util is
if W then
-- We suppress the warning if this code is under control of an
- -- if statement, whose condition is a simple identifier, and
- -- either we are in an instance, or warnings off is set for this
- -- identifier. The reason for killing it in the instance case is
- -- that it is common and reasonable for code to be deleted in
- -- instances for various reasons.
+ -- if/case statement and either
+ -- a) we are in an instance and the condition/selector
+ -- has a statically known value; or
+ -- b) the condition/selector is a simple identifier and
+ -- warnings off is set for this identifier.
+ -- Dead code is common and reasonable in instances, so we don't
+ -- want a warning in that case.
- -- Could we use Is_Statically_Unevaluated here???
+ declare
+ C : Node_Id := Empty;
+ begin
+ if Nkind (Parent (N)) = N_If_Statement then
+ C := Condition (Parent (N));
+ elsif Nkind (Parent (N)) = N_Case_Statement_Alternative then
+ C := Expression (Parent (Parent (N)));
+ end if;
- if Nkind (Parent (N)) = N_If_Statement then
- declare
- C : constant Node_Id := Condition (Parent (N));
- begin
- if Nkind (C) = N_Identifier
- and then
- (In_Instance
- or else (Present (Entity (C))
- and then Has_Warnings_Off (Entity (C))))
+ if Present (C) then
+ if (In_Instance and Compile_Time_Known_Value (C))
+ or else (Nkind (C) = N_Identifier
+ and then Present (Entity (C))
+ and then Has_Warnings_Off (Entity (C)))
then
W := False;
end if;
- end;
- end if;
+ end if;
+ end;
-- Generate warning if not suppressed
@@ -9505,7 +9695,7 @@ package body Exp_Util is
-- end Equiv_T;
Equiv_Type := Make_Temporary (Loc, 'T');
- Set_Ekind (Equiv_Type, E_Record_Type);
+ Mutate_Ekind (Equiv_Type, E_Record_Type);
Set_Parent_Subtype (Equiv_Type, Constr_Root);
-- Set Is_Class_Wide_Equivalent_Type very early to trigger the special
@@ -9997,7 +10187,7 @@ package body Exp_Util is
-- Define the dummy private subtype
- Set_Ekind (Priv_Subtyp, Subtype_Kind (Ekind (Unc_Typ)));
+ Mutate_Ekind (Priv_Subtyp, Subtype_Kind (Ekind (Unc_Typ)));
Set_Etype (Priv_Subtyp, Base_Type (Unc_Typ));
Set_Scope (Priv_Subtyp, Full_Subtyp);
Set_Is_Constrained (Priv_Subtyp);
@@ -10923,7 +11113,7 @@ package body Exp_Util is
Set_Associated_Node_For_Itype (Res, N);
Set_Comes_From_Source (Res, False);
- Set_Ekind (Res, E_Class_Wide_Subtype);
+ Mutate_Ekind (Res, E_Class_Wide_Subtype);
Set_Etype (Res, Base_Type (CW_Typ));
Set_Freeze_Node (Res, Empty);
Set_Is_Frozen (Res, False);
@@ -11343,7 +11533,7 @@ package body Exp_Util is
Init_Call : Node_Id;
- -- Start of processing for Find_Init_Call
+ -- Start of processing for Remove_Init_Call
begin
if Present (Initialization_Statements (Var)) then
@@ -11395,8 +11585,29 @@ package body Exp_Util is
end if;
if Present (Init_Call) then
+ -- If restrictions have forbidden Aborts, the initialization call
+ -- for objects that require deep initialization has not been wrapped
+ -- into the following block (see Exp_Ch3, Default_Initialize_Object)
+ -- so if present remove it as well, and include the IP call in it,
+ -- in the rare case the caller may need to simply displace the
+ -- initialization, as is done for a later address specification.
+
+ if Nkind (Next (Init_Call)) = N_Block_Statement
+ and then Is_Initialization_Block (Next (Init_Call))
+ then
+ declare
+ IP_Call : constant Node_Id := Init_Call;
+ begin
+ Init_Call := Next (IP_Call);
+ Remove (IP_Call);
+ Prepend (IP_Call,
+ Statements (Handled_Statement_Sequence (Init_Call)));
+ end;
+ end if;
+
Remove (Init_Call);
end if;
+
return Init_Call;
end Remove_Init_Call;
@@ -11477,7 +11688,8 @@ package body Exp_Util is
return not Inside_A_Generic
and then Full_Analysis
and then Nkind (Enclosing_Declaration (Exp)) in
- N_Full_Type_Declaration
+ N_Component_Declaration
+ | N_Full_Type_Declaration
| N_Iterator_Specification
| N_Loop_Parameter_Specification
| N_Object_Renaming_Declaration
@@ -12063,7 +12275,9 @@ package body Exp_Util is
-- Local variables
- Context : constant Node_Id := Parent (Ref);
+ Context : constant Node_Id :=
+ (if No (Ref) then Empty else Parent (Ref));
+
Loc : constant Source_Ptr := Sloc (Ref);
Ref_Id : Entity_Id;
Result : Traverse_Result;
@@ -12195,15 +12409,28 @@ package body Exp_Util is
if Nkind (Context) in N_Subprogram_Call
and then No (Type_Map.Get (Entity (Name (Context))))
then
- New_Ref :=
- Convert_To (Type_Of_Formal (Context, Old_Ref), New_Ref);
-
- -- Do not process the generated type conversion because
- -- both the parent type and the derived type are in the
- -- Type_Map table. This will clobber the type conversion
- -- by resetting its subtype mark.
-
- Result := Skip;
+ declare
+ -- We need to use the Original_Node of the callee, in
+ -- case it was already modified. Note that we are using
+ -- Traverse_Proc to walk the tree, and it is defined to
+ -- walk subtrees in an arbitrary order.
+
+ Callee : constant Entity_Id :=
+ Entity (Original_Node (Name (Context)));
+ begin
+ if No (Type_Map.Get (Callee)) then
+ New_Ref :=
+ Convert_To
+ (Type_Of_Formal (Context, Old_Ref), New_Ref);
+
+ -- Do not process the generated type conversion
+ -- because both the parent type and the derived type
+ -- are in the Type_Map table. This will clobber the
+ -- type conversion by resetting its subtype mark.
+
+ Result := Skip;
+ end if;
+ end;
end if;
-- Otherwise there is nothing to replace
@@ -13266,7 +13493,7 @@ package body Exp_Util is
-- modification of that variable within the loop may incorrectly
-- affect the execution of the loop.
- elsif Nkind (Parent (Parent (N))) = N_Loop_Parameter_Specification
+ elsif Parent_Kind (Parent (N)) = N_Loop_Parameter_Specification
and then Within_In_Parameter (Prefix (N))
and then Variable_Ref
then
@@ -13436,16 +13663,26 @@ package body Exp_Util is
-- A binary operator is side effect free if and both operands are
-- side effect free. For this purpose binary operators include
- -- membership tests and short circuit forms.
+ -- short circuit forms.
when N_Binary_Op
- | N_Membership_Test
| N_Short_Circuit
=>
return Side_Effect_Free (Left_Opnd (N), Name_Req, Variable_Ref)
and then
Side_Effect_Free (Right_Opnd (N), Name_Req, Variable_Ref);
+ -- Membership tests may have either Right_Opnd or Alternatives set
+
+ when N_Membership_Test =>
+ return Side_Effect_Free (Left_Opnd (N), Name_Req, Variable_Ref)
+ and then
+ (if Present (Right_Opnd (N))
+ then Side_Effect_Free
+ (Right_Opnd (N), Name_Req, Variable_Ref)
+ else Side_Effect_Free
+ (Alternatives (N), Name_Req, Variable_Ref));
+
-- An explicit dereference is side effect free only if it is
-- a side effect free prefixed reference.