aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch4.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_ch4.adb')
-rw-r--r--gcc/ada/exp_ch4.adb727
1 files changed, 331 insertions, 396 deletions
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 04bd1fe..16f513e 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.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,55 +23,59 @@
-- --
------------------------------------------------------------------------------
-with Atree; use Atree;
-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_Atag; use Exp_Atag;
-with Exp_Ch3; use Exp_Ch3;
-with Exp_Ch6; use Exp_Ch6;
-with Exp_Ch7; use Exp_Ch7;
-with Exp_Ch9; use Exp_Ch9;
-with Exp_Disp; use Exp_Disp;
-with Exp_Fixd; use Exp_Fixd;
-with Exp_Intr; use Exp_Intr;
-with Exp_Pakd; use Exp_Pakd;
-with Exp_Tss; use Exp_Tss;
-with Exp_Util; use Exp_Util;
-with Freeze; use Freeze;
-with Inline; use Inline;
-with Namet; use Namet;
-with Nlists; use Nlists;
-with Nmake; use Nmake;
-with Opt; use Opt;
-with Par_SCO; use Par_SCO;
-with Restrict; use Restrict;
-with Rident; use Rident;
-with Rtsfind; use Rtsfind;
-with Sem; use Sem;
-with Sem_Aux; use Sem_Aux;
-with Sem_Cat; use Sem_Cat;
-with Sem_Ch3; use Sem_Ch3;
-with Sem_Ch13; use Sem_Ch13;
-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 Sem_Warn; use Sem_Warn;
-with Sinfo; use Sinfo;
-with Snames; use Snames;
-with Stand; use Stand;
-with SCIL_LL; use SCIL_LL;
-with Targparm; use Targparm;
-with Tbuild; use Tbuild;
-with Ttypes; use Ttypes;
-with Uintp; use Uintp;
-with Urealp; use Urealp;
-with Validsw; use Validsw;
-with Warnsw; use Warnsw;
+with Atree; use Atree;
+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_Atag; use Exp_Atag;
+with Exp_Ch3; use Exp_Ch3;
+with Exp_Ch6; use Exp_Ch6;
+with Exp_Ch7; use Exp_Ch7;
+with Exp_Ch9; use Exp_Ch9;
+with Exp_Disp; use Exp_Disp;
+with Exp_Fixd; use Exp_Fixd;
+with Exp_Intr; use Exp_Intr;
+with Exp_Pakd; use Exp_Pakd;
+with Exp_Tss; use Exp_Tss;
+with Exp_Util; use Exp_Util;
+with Freeze; use Freeze;
+with Inline; use Inline;
+with Namet; use Namet;
+with Nlists; use Nlists;
+with Nmake; use Nmake;
+with Opt; use Opt;
+with Par_SCO; use Par_SCO;
+with Restrict; use Restrict;
+with Rident; use Rident;
+with Rtsfind; use Rtsfind;
+with Sem; use Sem;
+with Sem_Aux; use Sem_Aux;
+with Sem_Cat; use Sem_Cat;
+with Sem_Ch3; use Sem_Ch3;
+with Sem_Ch13; use Sem_Ch13;
+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 Sem_Warn; use Sem_Warn;
+with Sinfo; use Sinfo;
+with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo.Utils; use Sinfo.Utils;
+with Snames; use Snames;
+with Stand; use Stand;
+with SCIL_LL; use SCIL_LL;
+with Targparm; use Targparm;
+with Tbuild; use Tbuild;
+with Ttypes; use Ttypes;
+with Uintp; use Uintp;
+with Urealp; use Urealp;
+with Validsw; use Validsw;
+with Warnsw; use Warnsw;
package body Exp_Ch4 is
@@ -172,16 +176,9 @@ package body Exp_Ch4 is
-- routine is to find the real type by looking up the tree. We also
-- determine if the operation must be rounded.
- function Has_Inferable_Discriminants (N : Node_Id) return Boolean;
- -- Ada 2005 (AI-216): A view of an Unchecked_Union object has inferable
- -- discriminants if it has a constrained nominal type, unless the object
- -- is a component of an enclosing Unchecked_Union object that is subject
- -- to a per-object constraint and the enclosing object lacks inferable
- -- discriminants.
- --
- -- An expression of an Unchecked_Union type has inferable discriminants
- -- if it is either a name of an object with inferable discriminants or a
- -- qualified expression whose subtype mark denotes a constrained subtype.
+ function Get_Size_For_Range (Lo, Hi : Uint) return Uint;
+ -- Return the size of a small signed integer type covering Lo .. Hi, the
+ -- main goal being to return a size lower than that of standard types.
procedure Insert_Dereference_Action (N : Node_Id);
-- N is an expression whose type is an access. When the type of the
@@ -618,6 +615,7 @@ package body Exp_Ch4 is
and then Is_Class_Wide_Type (DesigT)
and then Tagged_Type_Expansion
and then not Scope_Suppress.Suppress (Accessibility_Check)
+ and then not No_Dynamic_Accessibility_Checks_Enabled (Ref)
and then
(Type_Access_Level (Etype (Exp)) > Type_Access_Level (PtrT)
or else
@@ -733,8 +731,7 @@ package body Exp_Ch4 is
Append_To (Stmts,
Make_Raise_Program_Error (Loc,
- Condition => New_Occurrence_Of (Standard_True, Loc),
- Reason => PE_Accessibility_Check_Failed));
+ Reason => PE_Accessibility_Check_Failed));
-- Step 2: Create the accessibility comparison
@@ -1169,6 +1166,9 @@ package body Exp_Ch4 is
-- secondary stack). In that case, the object will be moved, so we do
-- want to Adjust. However, if it's a nonlimited build-in-place
-- function call, Adjust is not wanted.
+ --
+ -- Needs_Finalization (DesigT) can differ from Needs_Finalization (T)
+ -- if one of the two types is class-wide, and the other is not.
if Needs_Finalization (DesigT)
and then Needs_Finalization (T)
@@ -2253,9 +2253,6 @@ package body Exp_Ch4 is
LLIB : constant Entity_Id := Base_Type (Standard_Long_Long_Integer);
-- Entity for Long_Long_Integer'Base
- Check : constant Overflow_Mode_Type := Overflow_Check_Mode;
- -- Current overflow checking mode
-
procedure Set_True;
procedure Set_False;
-- These procedures rewrite N with an occurrence of Standard_True or
@@ -2284,17 +2281,6 @@ package body Exp_Ch4 is
-- Start of processing for Expand_Compare_Minimize_Eliminate_Overflow
begin
- -- Nothing to do unless we have a comparison operator with operands
- -- that are signed integer types, and we are operating in either
- -- MINIMIZED or ELIMINATED overflow checking mode.
-
- if Nkind (N) not in N_Op_Compare
- or else Check not in Minimized_Or_Eliminated
- or else not Is_Signed_Integer_Type (Etype (Left_Opnd (N)))
- then
- return;
- end if;
-
-- OK, this is the case we are interested in. First step is to process
-- our operands using the Minimize_Eliminate circuitry which applies
-- this processing to the two operand subtrees.
@@ -3035,16 +3021,6 @@ package body Exp_Ch4 is
if Is_Enumeration_Type (Ityp) then
Artyp := Standard_Integer;
- -- If index type is Positive, we use the standard unsigned type, to give
- -- more room on the top of the range, obviating the need for an overflow
- -- check when creating the upper bound. This is needed to avoid junk
- -- overflow checks in the common case of String types.
-
- -- ??? Disabled for now
-
- -- elsif Istyp = Standard_Positive then
- -- Artyp := Standard_Unsigned;
-
-- For modular types, we use a 32-bit modular type for types whose size
-- is in the range 1-31 bits. For 32-bit unsigned types, we use the
-- identity type, and for larger unsigned types we use a 64-bit type.
@@ -3803,7 +3779,7 @@ package body Exp_Ch4 is
-- Bounds in Minimize calls, not used currently
LLIB : constant Entity_Id := Base_Type (Standard_Long_Long_Integer);
- -- Entity for Long_Long_Integer'Base (Standard should export this???)
+ -- Entity for Long_Long_Integer'Base
begin
Minimize_Eliminate_Overflows (Lop, Lo, Hi, Top_Level => False);
@@ -4282,7 +4258,7 @@ package body Exp_Ch4 is
-- larger type for the operands, to prevent spurious constraint
-- errors on large legal literals of the type.
- if Modulus (Etype (N)) > UI_From_Int (Int (Integer'Last)) then
+ if Modulus (Etype (N)) > Int (Integer'Last) then
Target_Type := Standard_Long_Long_Integer;
else
Target_Type := Standard_Integer;
@@ -4499,10 +4475,6 @@ package body Exp_Ch4 is
-- are too large, and which in the absence of a check results in
-- undetected chaos ???
- -- Note in particular that this is a pessimistic estimate in the
- -- case of packed array types, where an array element might occupy
- -- just a fraction of a storage element???
-
declare
Idx : Node_Id := First_Index (E);
Len : Node_Id;
@@ -4624,9 +4596,10 @@ package body Exp_Ch4 is
end if;
-- RM E.2.2(17). We enforce that the expected type of an allocator
- -- shall not be a remote access-to-class-wide-limited-private type
-
- -- Why is this being done at expansion time, seems clearly wrong ???
+ -- shall not be a remote access-to-class-wide-limited-private type.
+ -- We probably shouldn't be doing this legality check during expansion,
+ -- but this is only an issue for Annex E users, and is unlikely to be a
+ -- problem in practice.
Validate_Remote_Access_To_Class_Wide_Type (N);
@@ -5224,8 +5197,8 @@ package body Exp_Ch4 is
end if;
if Restriction_Active (No_Task_Hierarchy) then
- Append_To (Args,
- New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc));
+ Append_To
+ (Args, Make_Integer_Literal (Loc, Library_Task_Level));
else
Append_To (Args,
New_Occurrence_Of
@@ -5308,6 +5281,8 @@ package body Exp_Ch4 is
if Ada_Version >= Ada_2005
and then
Ekind (Etype (Nod)) = E_Anonymous_Access_Type
+ and then not
+ No_Dynamic_Accessibility_Checks_Enabled (Nod)
then
Apply_Accessibility_Check
(Nod, Typ, Insert_Node => Nod);
@@ -5568,10 +5543,8 @@ package body Exp_Ch4 is
if Is_Copy_Type (Typ) then
Target_Typ := Typ;
- -- ??? Do not perform the optimization when the return statement is
- -- within a predicate function, as this causes spurious errors. Could
- -- this be a possible mismatch in handling this case somewhere else
- -- in semantic analysis?
+ -- Do not perform the optimization when the return statement is
+ -- within a predicate function, as this causes spurious errors.
Optimize_Return_Stmt :=
Nkind (Par) = N_Simple_Return_Statement and then not In_Predicate;
@@ -5813,15 +5786,14 @@ package body Exp_Ch4 is
-- Avoid processing temporary function results multiple times when
-- dealing with nested expression_with_actions.
+ -- Similarly, do not process temporary function results in loops.
+ -- This is done by Expand_N_Loop_Statement and Build_Finalizer.
+ -- Note that we used to wrongly return Abandon instead of Skip here:
+ -- this is wrong since it means that we were ignoring lots of
+ -- relevant subsequent statements.
- elsif Nkind (Act) = N_Expression_With_Actions then
- return Abandon;
-
- -- Do not process temporary function results in loops. This is done
- -- by Expand_N_Loop_Statement and Build_Finalizer.
-
- elsif Nkind (Act) = N_Loop_Statement then
- return Abandon;
+ elsif Nkind (Act) in N_Expression_With_Actions | N_Loop_Statement then
+ return Skip;
end if;
return OK;
@@ -5941,9 +5913,14 @@ package body Exp_Ch4 is
-- Start of processing for Expand_N_If_Expression
begin
- -- Check for MINIMIZED/ELIMINATED overflow mode
+ -- Check for MINIMIZED/ELIMINATED overflow mode.
+ -- Apply_Arithmetic_Overflow_Check will not deal with Then/Else_Actions
+ -- so skip this step if any actions are present.
- if Minimized_Eliminated_Overflow_Check (N) then
+ if Minimized_Eliminated_Overflow_Check (N)
+ and then No (Then_Actions (N))
+ and then No (Else_Actions (N))
+ then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
@@ -6355,13 +6332,11 @@ package body Exp_Ch4 is
-- perspective.
if Comes_From_Source (Obj_Ref) then
-
- -- Recover the actual object reference. There may be more cases
- -- to consider???
-
loop
if Nkind (Obj_Ref) in
- N_Type_Conversion | N_Unchecked_Type_Conversion
+ N_Type_Conversion |
+ N_Unchecked_Type_Conversion |
+ N_Qualified_Expression
then
Obj_Ref := Expression (Obj_Ref);
else
@@ -6425,8 +6400,7 @@ package body Exp_Ch4 is
-- type, then expand with a separate procedure. Note the use of the
-- flag No_Minimize_Eliminate to prevent infinite recursion.
- if Overflow_Check_Mode in Minimized_Or_Eliminated
- and then Is_Signed_Integer_Type (Ltyp)
+ if Minimized_Eliminated_Overflow_Check (Left_Opnd (N))
and then not No_Minimize_Eliminate (N)
then
Expand_Membership_Minimize_Eliminate_Overflow (N);
@@ -6507,8 +6481,6 @@ package body Exp_Ch4 is
begin
-- If test is explicit x'First .. x'Last, replace by valid check
- -- Could use some individual comments for this complex test ???
-
if Is_Scalar_Type (Ltyp)
-- And left operand is X'First where X matches left operand
@@ -6899,6 +6871,7 @@ package body Exp_Ch4 is
if Ada_Version >= Ada_2012
and then Is_Acc
and then Ekind (Ltyp) = E_Anonymous_Access_Type
+ and then not No_Dynamic_Accessibility_Checks_Enabled (Lop)
then
declare
Expr_Entity : Entity_Id := Empty;
@@ -8113,13 +8086,9 @@ package body Exp_Ch4 is
function User_Defined_Primitive_Equality_Op
(Typ : Entity_Id) return Entity_Id
is
- Enclosing_Scope : constant Node_Id := Scope (Typ);
+ Enclosing_Scope : constant Entity_Id := Scope (Typ);
E : Entity_Id;
begin
- -- Prune this search by somehow not looking at decls that precede
- -- the declaration of the first view of Typ (which might be a partial
- -- view)???
-
for Private_Entities in Boolean loop
if Private_Entities then
if Ekind (Enclosing_Scope) /= E_Package then
@@ -8154,138 +8123,129 @@ package body Exp_Ch4 is
function Has_Unconstrained_UU_Component
(Typ : Entity_Id) return Boolean
is
- Tdef : constant Node_Id :=
- Type_Definition (Declaration_Node (Base_Type (Typ)));
- Clist : Node_Id;
- Vpart : Node_Id;
-
- function Component_Is_Unconstrained_UU
- (Comp : Node_Id) return Boolean;
- -- Determines whether the subtype of the component is an
- -- unconstrained Unchecked_Union.
-
- function Variant_Is_Unconstrained_UU
- (Variant : Node_Id) return Boolean;
- -- Determines whether a component of the variant has an unconstrained
- -- Unchecked_Union subtype.
-
- -----------------------------------
- -- Component_Is_Unconstrained_UU --
- -----------------------------------
-
- function Component_Is_Unconstrained_UU
- (Comp : Node_Id) return Boolean
- is
- begin
- if Nkind (Comp) /= N_Component_Declaration then
- return False;
- end if;
-
- declare
- Sindic : constant Node_Id :=
- Subtype_Indication (Component_Definition (Comp));
+ function Unconstrained_UU_In_Component_Declaration
+ (N : Node_Id) return Boolean;
- begin
- -- Unconstrained nominal type. In the case of a constraint
- -- present, the node kind would have been N_Subtype_Indication.
+ function Unconstrained_UU_In_Component_Items
+ (L : List_Id) return Boolean;
- if Nkind (Sindic) = N_Identifier then
- return Is_Unchecked_Union (Base_Type (Etype (Sindic)));
- end if;
+ function Unconstrained_UU_In_Component_List
+ (N : Node_Id) return Boolean;
- return False;
- end;
- end Component_Is_Unconstrained_UU;
+ function Unconstrained_UU_In_Variant_Part
+ (N : Node_Id) return Boolean;
+ -- A family of routines that determine whether a particular construct
+ -- of a record type definition contains a subcomponent of an
+ -- unchecked union type whose nominal subtype is unconstrained.
+ --
+ -- Individual routines correspond to the production rules of the Ada
+ -- grammar, as described in the Ada RM (P).
- ---------------------------------
- -- Variant_Is_Unconstrained_UU --
- ---------------------------------
+ -----------------------------------------------
+ -- Unconstrained_UU_In_Component_Declaration --
+ -----------------------------------------------
- function Variant_Is_Unconstrained_UU
- (Variant : Node_Id) return Boolean
+ function Unconstrained_UU_In_Component_Declaration
+ (N : Node_Id) return Boolean
is
- Clist : constant Node_Id := Component_List (Variant);
+ pragma Assert (Nkind (N) = N_Component_Declaration);
+ Sindic : constant Node_Id :=
+ Subtype_Indication (Component_Definition (N));
begin
- if Is_Empty_List (Component_Items (Clist)) then
- return False;
- end if;
-
- -- We only need to test one component
-
- declare
- Comp : Node_Id := First (Component_Items (Clist));
-
- begin
- while Present (Comp) loop
- if Component_Is_Unconstrained_UU (Comp) then
- return True;
- end if;
-
- Next (Comp);
- end loop;
- end;
-
- -- None of the components withing the variant were of
- -- unconstrained Unchecked_Union type.
-
- return False;
- end Variant_Is_Unconstrained_UU;
+ -- If the component declaration includes a subtype indication
+ -- it is not an unchecked_union. Otherwise verify that it carries
+ -- the Unchecked_Union flag and is either a record or a private
+ -- type. A Record_Subtype declared elsewhere does not qualify,
+ -- even if its parent type carries the flag.
+
+ return Nkind (Sindic) in N_Expanded_Name | N_Identifier
+ and then Is_Unchecked_Union (Base_Type (Etype (Sindic)))
+ and then (Ekind (Entity (Sindic)) in
+ E_Private_Type | E_Record_Type);
+ end Unconstrained_UU_In_Component_Declaration;
+
+ -----------------------------------------
+ -- Unconstrained_UU_In_Component_Items --
+ -----------------------------------------
+
+ function Unconstrained_UU_In_Component_Items
+ (L : List_Id) return Boolean
+ is
+ N : Node_Id := First (L);
+ begin
+ while Present (N) loop
+ if Nkind (N) = N_Component_Declaration
+ and then Unconstrained_UU_In_Component_Declaration (N)
+ then
+ return True;
+ end if;
- -- Start of processing for Has_Unconstrained_UU_Component
+ Next (N);
+ end loop;
- begin
- if Null_Present (Tdef) then
return False;
- end if;
-
- Clist := Component_List (Tdef);
- Vpart := Variant_Part (Clist);
+ end Unconstrained_UU_In_Component_Items;
- -- Inspect available components
+ ----------------------------------------
+ -- Unconstrained_UU_In_Component_List --
+ ----------------------------------------
- if Present (Component_Items (Clist)) then
- declare
- Comp : Node_Id := First (Component_Items (Clist));
+ function Unconstrained_UU_In_Component_List
+ (N : Node_Id) return Boolean
+ is
+ pragma Assert (Nkind (N) = N_Component_List);
- begin
- while Present (Comp) loop
+ Optional_Variant_Part : Node_Id;
+ begin
+ if Unconstrained_UU_In_Component_Items (Component_Items (N)) then
+ return True;
+ end if;
- -- One component is sufficient
+ Optional_Variant_Part := Variant_Part (N);
- if Component_Is_Unconstrained_UU (Comp) then
- return True;
- end if;
+ return
+ Present (Optional_Variant_Part)
+ and then
+ Unconstrained_UU_In_Variant_Part (Optional_Variant_Part);
+ end Unconstrained_UU_In_Component_List;
- Next (Comp);
- end loop;
- end;
- end if;
+ --------------------------------------
+ -- Unconstrained_UU_In_Variant_Part --
+ --------------------------------------
- -- Inspect available components withing variants
+ function Unconstrained_UU_In_Variant_Part
+ (N : Node_Id) return Boolean
+ is
+ pragma Assert (Nkind (N) = N_Variant_Part);
- if Present (Vpart) then
- declare
- Variant : Node_Id := First (Variants (Vpart));
+ Variant : Node_Id := First (Variants (N));
+ begin
+ loop
+ if Unconstrained_UU_In_Component_List (Component_List (Variant))
+ then
+ return True;
+ end if;
- begin
- while Present (Variant) loop
+ Next (Variant);
+ exit when No (Variant);
+ end loop;
- -- One component within a variant is sufficient
+ return False;
+ end Unconstrained_UU_In_Variant_Part;
- if Variant_Is_Unconstrained_UU (Variant) then
- return True;
- end if;
+ Typ_Def : constant Node_Id :=
+ Type_Definition (Declaration_Node (Base_Type (Typ)));
- Next (Variant);
- end loop;
- end;
- end if;
+ Optional_Component_List : constant Node_Id :=
+ Component_List (Typ_Def);
- -- Neither the available components, nor the components inside the
- -- variant parts were of an unconstrained Unchecked_Union subtype.
+ -- Start of processing for Has_Unconstrained_UU_Component
- return False;
+ begin
+ return Present (Optional_Component_List)
+ and then
+ Unconstrained_UU_In_Component_List (Optional_Component_List);
end Has_Unconstrained_UU_Component;
-- Local variables
@@ -8343,7 +8303,9 @@ package body Exp_Ch4 is
-- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
-- means we no longer have a comparison operation, we are all done.
- Expand_Compare_Minimize_Eliminate_Overflow (N);
+ if Minimized_Eliminated_Overflow_Check (Left_Opnd (N)) then
+ Expand_Compare_Minimize_Eliminate_Overflow (N);
+ end if;
if Nkind (N) /= N_Op_Eq then
return;
@@ -9128,15 +9090,12 @@ package body Exp_Ch4 is
-- overflow), and if there is an infinity generated and a range check
-- is required, the check will fail anyway.
- -- Historical note: we used to convert everything to Long_Long_Float
- -- and call a single common routine, but this had the undesirable effect
- -- of giving different results for small static exponent values and the
- -- same dynamic values.
-
else
pragma Assert (Is_Floating_Point_Type (Rtyp));
- if Rtyp = Standard_Float then
+ -- Short_Float and Float are the same type for GNAT
+
+ if Rtyp = Standard_Short_Float or else Rtyp = Standard_Float then
Etyp := Standard_Float;
Rent := RE_Exn_Float;
@@ -9154,8 +9113,7 @@ package body Exp_Ch4 is
-- If we are in the right type, we can call runtime routine directly
if Typ = Etyp
- and then Rtyp /= Universal_Integer
- and then Rtyp /= Universal_Real
+ and then not Is_Universal_Numeric_Type (Rtyp)
then
Rewrite (N,
Wrap_MA (
@@ -9201,7 +9159,9 @@ package body Exp_Ch4 is
-- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
-- means we no longer have a comparison operation, we are all done.
- Expand_Compare_Minimize_Eliminate_Overflow (N);
+ if Minimized_Eliminated_Overflow_Check (Op1) then
+ Expand_Compare_Minimize_Eliminate_Overflow (N);
+ end if;
if Nkind (N) /= N_Op_Ge then
return;
@@ -9250,7 +9210,9 @@ package body Exp_Ch4 is
-- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
-- means we no longer have a comparison operation, we are all done.
- Expand_Compare_Minimize_Eliminate_Overflow (N);
+ if Minimized_Eliminated_Overflow_Check (Op1) then
+ Expand_Compare_Minimize_Eliminate_Overflow (N);
+ end if;
if Nkind (N) /= N_Op_Gt then
return;
@@ -9299,7 +9261,9 @@ package body Exp_Ch4 is
-- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
-- means we no longer have a comparison operation, we are all done.
- Expand_Compare_Minimize_Eliminate_Overflow (N);
+ if Minimized_Eliminated_Overflow_Check (Op1) then
+ Expand_Compare_Minimize_Eliminate_Overflow (N);
+ end if;
if Nkind (N) /= N_Op_Le then
return;
@@ -9348,7 +9312,9 @@ package body Exp_Ch4 is
-- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
-- means we no longer have a comparison operation, we are all done.
- Expand_Compare_Minimize_Eliminate_Overflow (N);
+ if Minimized_Eliminated_Overflow_Check (Op1) then
+ Expand_Compare_Minimize_Eliminate_Overflow (N);
+ end if;
if Nkind (N) /= N_Op_Lt then
return;
@@ -9667,6 +9633,7 @@ package body Exp_Ch4 is
if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
and then ((not LOK) or else (Llo = LLB))
+ and then not CodePeer_Mode
then
Rewrite (N,
Make_If_Expression (Loc,
@@ -9942,7 +9909,9 @@ package body Exp_Ch4 is
-- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if
-- means we no longer have a /= operation, we are all done.
- Expand_Compare_Minimize_Eliminate_Overflow (N);
+ if Minimized_Eliminated_Overflow_Check (Left_Opnd (N)) then
+ Expand_Compare_Minimize_Eliminate_Overflow (N);
+ end if;
if Nkind (N) /= N_Op_Ne then
return;
@@ -10431,7 +10400,9 @@ package body Exp_Ch4 is
-- types and this is really marginal). We will just assume that we need
-- the test if the left operand can be negative at all.
- if Lneg and Rneg then
+ if (Lneg and Rneg)
+ and then not CodePeer_Mode
+ then
Rewrite (N,
Make_If_Expression (Loc,
Expressions => New_List (
@@ -10890,10 +10861,11 @@ package body Exp_Ch4 is
Var : Entity_Id;
begin
- -- Ensure that the bound variable is properly frozen. We must do
- -- this before expansion because the expression is about to be
- -- converted into a loop, and resulting freeze nodes may end up
- -- in the wrong place in the tree.
+ -- Ensure that the bound variable as well as the type of Name of the
+ -- Iter_Spec if present are properly frozen. We must do this before
+ -- expansion because the expression is about to be converted into a
+ -- loop, and resulting freeze nodes may end up in the wrong place in the
+ -- tree.
if Present (Iter_Spec) then
Var := Defining_Identifier (Iter_Spec);
@@ -10908,6 +10880,10 @@ package body Exp_Ch4 is
P := Parent (P);
end loop;
+ if Present (Iter_Spec) then
+ Freeze_Before (P, Etype (Name (Iter_Spec)));
+ end if;
+
Freeze_Before (P, Etype (Var));
end;
@@ -12019,9 +11995,8 @@ package body Exp_Ch4 is
-- unchecked conversion to the target fixed-point type.
Conv :=
- Make_Unchecked_Type_Conversion (Loc,
- Subtype_Mark => New_Occurrence_Of (Target_Type, Loc),
- Expression => New_Occurrence_Of (Expr_Id, Loc));
+ Unchecked_Convert_To
+ (Target_Type, New_Occurrence_Of (Expr_Id, Loc));
end;
-- All other conversions
@@ -12273,6 +12248,41 @@ package body Exp_Ch4 is
end;
end if;
+ -- If the conversion is from Universal_Integer and requires an overflow
+ -- check, try to do an intermediate conversion to a narrower type first
+ -- without overflow check, in order to avoid doing the overflow check
+ -- in Universal_Integer, which can be a very large type.
+
+ if Operand_Type = Universal_Integer and then Do_Overflow_Check (N) then
+ declare
+ Lo, Hi, Siz : Uint;
+ OK : Boolean;
+ Typ : Entity_Id;
+
+ begin
+ Determine_Range (Operand, OK, Lo, Hi, Assume_Valid => True);
+
+ if OK then
+ Siz := Get_Size_For_Range (Lo, Hi);
+
+ -- We use the base type instead of the first subtype because
+ -- overflow checks are done in the base type, so this avoids
+ -- the need for useless conversions.
+
+ if Siz < System_Max_Integer_Size then
+ Typ := Etype (Integer_Type_For (Siz, Uns => False));
+
+ Convert_To_And_Rewrite (Typ, Operand);
+ Analyze_And_Resolve
+ (Operand, Typ, Suppress => Overflow_Check);
+
+ Analyze_And_Resolve (N, Target_Type);
+ goto Done;
+ end if;
+ end if;
+ end;
+ end if;
+
-- Do validity check if validity checking operands
if Validity_Checks_On and Validity_Check_Operands then
@@ -12329,6 +12339,7 @@ package body Exp_Ch4 is
and then Ekind (Etype (Operand_Acc)) = E_Anonymous_Access_Type
and then (Nkind (Original_Node (N)) /= N_Attribute_Reference
or else Attribute_Name (Original_Node (N)) = Name_Access)
+ and then not No_Dynamic_Accessibility_Checks_Enabled (N)
then
if not Comes_From_Source (N)
and then Nkind (Parent (N)) in N_Function_Call
@@ -12506,10 +12517,7 @@ package body Exp_Ch4 is
Conv : Node_Id;
begin
Make_Tag_Check (Class_Wide_Type (Actual_Targ_Typ));
- Conv :=
- Make_Unchecked_Type_Conversion (Loc,
- Subtype_Mark => New_Occurrence_Of (Target_Type, Loc),
- Expression => Relocate_Node (Expression (N)));
+ Conv := Unchecked_Convert_To (Target_Type, Expression (N));
Rewrite (N, Conv);
Analyze_And_Resolve (N, Target_Type);
end;
@@ -12589,6 +12597,13 @@ package body Exp_Ch4 is
if Is_Constrained (Target_Type) then
Apply_Length_Check (Operand, Target_Type);
else
+ -- If the object has an unconstrained array subtype with fixed
+ -- lower bound, then sliding to that bound may be needed.
+
+ if Is_Fixed_Lower_Bound_Array_Subtype (Target_Type) then
+ Expand_Sliding_Conversion (Operand, Target_Type);
+ end if;
+
Apply_Range_Check (Operand, Target_Type);
end if;
@@ -12667,17 +12682,7 @@ package body Exp_Ch4 is
-- At this stage, either the conversion node has been transformed into
-- some other equivalent expression, or left as a conversion that can be
- -- handled by Gigi, in the following cases:
-
- -- Conversions with no change of representation or type
-
- -- Numeric conversions involving integer, floating- and fixed-point
- -- values. Fixed-point values are allowed only if Conversion_OK is
- -- set, i.e. if the fixed-point values are to be treated as integers.
-
- -- No other conversions should be passed to Gigi
-
- -- Check: are these rules stated in sinfo??? if so, why restate here???
+ -- handled by Gigi.
-- The only remaining step is to generate a range check if we still have
-- a type conversion at this stage and Do_Range_Check is set. Note that
@@ -12742,7 +12747,16 @@ package body Exp_Ch4 is
-- guard is necessary to prevent infinite recursions when we generate
-- internal conversions for the purpose of checking predicates.
- if Predicate_Enabled (Target_Type)
+ -- A view conversion of a tagged object is an object and can appear
+ -- in an assignment context, in which case no predicate check applies
+ -- to the now-dead value.
+
+ if Nkind (Parent (N)) = N_Assignment_Statement
+ and then N = Name (Parent (N))
+ then
+ null;
+
+ elsif Predicate_Enabled (Target_Type)
and then Target_Type /= Operand_Type
and then Comes_From_Source (N)
then
@@ -12796,14 +12810,7 @@ package body Exp_Ch4 is
-- an Assignment_OK indication which must be propagated to the operand.
if Operand_Type = Target_Type then
-
- -- Code duplicates Expand_N_Unchecked_Expression above, factor???
-
- if Assignment_OK (N) then
- Set_Assignment_OK (Operand);
- end if;
-
- Rewrite (N, Relocate_Node (Operand));
+ Expand_N_Unchecked_Expression (N);
return;
end if;
@@ -12834,9 +12841,6 @@ package body Exp_Ch4 is
return;
end if;
- -- Otherwise force evaluation unless Assignment_OK flag is set (this
- -- flag indicates ??? More comments needed here)
-
if Assignment_OK (N) then
null;
else
@@ -13331,83 +13335,53 @@ package body Exp_Ch4 is
end if;
end Fixup_Universal_Fixed_Operation;
- ---------------------------------
- -- Has_Inferable_Discriminants --
- ---------------------------------
+ ------------------------
+ -- Get_Size_For_Range --
+ ------------------------
- function Has_Inferable_Discriminants (N : Node_Id) return Boolean is
+ function Get_Size_For_Range (Lo, Hi : Uint) return Uint is
- function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean;
- -- Determines whether the left-most prefix of a selected component is a
- -- formal parameter in a subprogram. Assumes N is a selected component.
+ function Is_OK_For_Range (Siz : Uint) return Boolean;
+ -- Return True if a signed integer with given size can cover Lo .. Hi
- --------------------------------
- -- Prefix_Is_Formal_Parameter --
- --------------------------------
+ --------------------------
+ -- Is_OK_For_Range --
+ --------------------------
- function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean is
- Sel_Comp : Node_Id;
+ function Is_OK_For_Range (Siz : Uint) return Boolean is
+ B : constant Uint := Uint_2 ** (Siz - 1);
begin
- -- Move to the left-most prefix by climbing up the tree
-
- Sel_Comp := N;
- while Present (Parent (Sel_Comp))
- and then Nkind (Parent (Sel_Comp)) = N_Selected_Component
- loop
- Sel_Comp := Parent (Sel_Comp);
- end loop;
-
- return Is_Formal (Entity (Prefix (Sel_Comp)));
- end Prefix_Is_Formal_Parameter;
+ -- Test B = 2 ** (size - 1) (can accommodate -B .. +(B - 1))
- -- Start of processing for Has_Inferable_Discriminants
+ return Lo >= -B and then Hi >= -B and then Lo < B and then Hi < B;
+ end Is_OK_For_Range;
begin
- -- For selected components, the subtype of the selector must be a
- -- constrained Unchecked_Union. If the component is subject to a
- -- per-object constraint, then the enclosing object must have inferable
- -- discriminants.
-
- if Nkind (N) = N_Selected_Component then
- if Has_Per_Object_Constraint (Entity (Selector_Name (N))) then
-
- -- A small hack. If we have a per-object constrained selected
- -- component of a formal parameter, return True since we do not
- -- know the actual parameter association yet.
+ -- This is (almost always) the size of Integer
- if Prefix_Is_Formal_Parameter (N) then
- return True;
-
- -- Otherwise, check the enclosing object and the selector
+ if Is_OK_For_Range (Uint_32) then
+ return Uint_32;
- else
- return Has_Inferable_Discriminants (Prefix (N))
- and then Has_Inferable_Discriminants (Selector_Name (N));
- end if;
+ -- Check 63
- -- The call to Has_Inferable_Discriminants will determine whether
- -- the selector has a constrained Unchecked_Union nominal type.
+ elsif Is_OK_For_Range (Uint_63) then
+ return Uint_63;
- else
- return Has_Inferable_Discriminants (Selector_Name (N));
- end if;
+ -- This is (almost always) the size of Long_Long_Integer
- -- A qualified expression has inferable discriminants if its subtype
- -- mark is a constrained Unchecked_Union subtype.
+ elsif Is_OK_For_Range (Uint_64) then
+ return Uint_64;
- elsif Nkind (N) = N_Qualified_Expression then
- return Is_Unchecked_Union (Etype (Subtype_Mark (N)))
- and then Is_Constrained (Etype (Subtype_Mark (N)));
+ -- Check 127
- -- For all other names, it is sufficient to have a constrained
- -- Unchecked_Union nominal subtype.
+ elsif Is_OK_For_Range (Uint_127) then
+ return Uint_127;
else
- return Is_Unchecked_Union (Base_Type (Etype (N)))
- and then Is_Constrained (Etype (N));
+ return Uint_128;
end if;
- end Has_Inferable_Discriminants;
+ end Get_Size_For_Range;
-------------------------------
-- Insert_Dereference_Action --
@@ -13722,9 +13696,6 @@ package body Exp_Ch4 is
-- do not need to generate an actual or formal generic part, just the
-- instantiated function itself.
- -- Perhaps we could have the actual generic available in the run-time,
- -- obtained by rtsfind, and actually expand a real instantiation ???
-
function Make_Array_Comparison_Op
(Typ : Entity_Id;
Nod : Node_Id) return Node_Id
@@ -14114,9 +14085,15 @@ package body Exp_Ch4 is
function Minimized_Eliminated_Overflow_Check (N : Node_Id) return Boolean is
begin
+ -- The MINIMIZED mode operates in Long_Long_Integer so we cannot use it
+ -- if the type of the expression is already larger.
+
return
Is_Signed_Integer_Type (Etype (N))
- and then Overflow_Check_Mode in Minimized_Or_Eliminated;
+ and then Overflow_Check_Mode in Minimized_Or_Eliminated
+ and then not (Overflow_Check_Mode = Minimized
+ and then
+ Esize (Etype (N)) > Standard_Long_Long_Integer_Size);
end Minimized_Eliminated_Overflow_Check;
----------------------------
@@ -14132,58 +14109,6 @@ package body Exp_Ch4 is
Typ : constant Entity_Id := Etype (R);
Tsiz : constant Uint := RM_Size (Typ);
- function Get_Size_For_Range (Lo, Hi : Uint) return Uint;
- -- Return the size of a small signed integer type covering Lo .. Hi.
- -- The important thing is to return a size lower than that of Typ.
-
- ------------------------
- -- Get_Size_For_Range --
- ------------------------
-
- function Get_Size_For_Range (Lo, Hi : Uint) return Uint is
-
- function Is_OK_For_Range (Siz : Uint) return Boolean;
- -- Return True if a signed integer with given size can cover Lo .. Hi
-
- --------------------------
- -- Is_OK_For_Range --
- --------------------------
-
- function Is_OK_For_Range (Siz : Uint) return Boolean is
- B : constant Uint := Uint_2 ** (Siz - 1);
-
- begin
- -- Test B = 2 ** (size - 1) (can accommodate -B .. +(B - 1))
-
- return Lo >= -B and then Hi >= -B and then Lo < B and then Hi < B;
- end Is_OK_For_Range;
-
- begin
- -- This is (almost always) the size of Integer
-
- if Is_OK_For_Range (Uint_32) then
- return Uint_32;
-
- -- If the size of Typ is 64 then check 63
-
- elsif Tsiz = Uint_64 and then Is_OK_For_Range (Uint_63) then
- return Uint_63;
-
- -- This is (almost always) the size of Long_Long_Integer
-
- elsif Is_OK_For_Range (Uint_64) then
- return Uint_64;
-
- -- If the size of Typ is 128 then check 127
-
- elsif Tsiz = Uint_128 and then Is_OK_For_Range (Uint_127) then
- return Uint_127;
-
- else
- return Uint_128;
- end if;
- end Get_Size_For_Range;
-
-- Local variables
L : Node_Id;
@@ -15026,7 +14951,17 @@ package body Exp_Ch4 is
-- Hook := null;
-- end if;
+ -- Note that the value returned by Find_Hook_Context may be an operator
+ -- node, which is not a list member. We must locate the proper node in
+ -- in the tree after which to insert the finalization code.
+
else
+ while not Is_List_Member (Fin_Context) loop
+ Fin_Context := Parent (Fin_Context);
+ end loop;
+
+ pragma Assert (Present (Fin_Context));
+
Insert_Action_After (Fin_Context,
Make_Implicit_If_Statement (Obj_Decl,
Condition =>
@@ -15247,7 +15182,7 @@ package body Exp_Ch4 is
Selector_Name =>
New_Occurrence_Of (First_Tag_Component (Left_Type), Loc));
- if Is_Class_Wide_Type (Right_Type) or else Is_Interface (Left_Type) then
+ if Is_Class_Wide_Type (Right_Type) then
-- No need to issue a run-time check if we statically know that the
-- result of this membership test is always true. For example,