aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch5.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_ch5.adb')
-rw-r--r--gcc/ada/exp_ch5.adb180
1 files changed, 88 insertions, 92 deletions
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index b30171e..309297b 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2019, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2020, 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- --
@@ -29,7 +29,6 @@ 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;
@@ -279,8 +278,9 @@ package body Exp_Ch5 is
begin
return
Nkind (Rhs) = N_Type_Conversion
- and then
- not Same_Representation (Etype (Rhs), Etype (Expression (Rhs)));
+ and then not Has_Compatible_Representation
+ (Target_Type => Etype (Rhs),
+ Operand_Type => Etype (Expression (Rhs)));
end Change_Of_Representation;
------------------------------
@@ -442,7 +442,7 @@ package body Exp_Ch5 is
-- respect to the right-hand side as given, not a possible underlying
-- renamed object, since this would generate incorrect extra checks.
- Apply_Length_Check (Rhs, L_Type);
+ Apply_Length_Check_On_Assignment (Rhs, L_Type, Lhs);
-- We start by assuming that the move can be done in either direction,
-- i.e. that the two sides are completely disjoint.
@@ -1452,17 +1452,14 @@ package body Exp_Ch5 is
L_Prefix_Comp : constant Boolean :=
-- True if the left-hand side is a slice of a component or slice
Nkind (Name (N)) = N_Slice
- and then Nkind_In (Prefix (Name (N)),
- N_Selected_Component,
- N_Indexed_Component,
- N_Slice);
+ and then Nkind (Prefix (Name (N))) in
+ N_Selected_Component | N_Indexed_Component | N_Slice;
R_Prefix_Comp : constant Boolean :=
-- Likewise for the right-hand side
Nkind (Expression (N)) = N_Slice
- and then Nkind_In (Prefix (Expression (N)),
- N_Selected_Component,
- N_Indexed_Component,
- N_Slice);
+ and then Nkind (Prefix (Expression (N))) in
+ N_Selected_Component | N_Indexed_Component | N_Slice;
+
begin
-- Determine whether Copy_Bitfield is appropriate (will work, and will
-- be more efficient than component-by-component copy). Copy_Bitfield
@@ -1522,7 +1519,7 @@ package body Exp_Ch5 is
-- be assigned.
elsif Possible_Bit_Aligned_Component (Lhs)
- or
+ or else
Possible_Bit_Aligned_Component (Rhs)
then
null;
@@ -1595,6 +1592,18 @@ package body Exp_Ch5 is
while Present (C) loop
if Chars (C) = Chars (Comp) then
return C;
+
+ -- The component may be a renamed discriminant, in
+ -- which case check against the name of the original
+ -- discriminant of the parent type.
+
+ elsif Is_Derived_Type (Scope (Comp))
+ and then Ekind (Comp) = E_Discriminant
+ and then Present (Corresponding_Discriminant (Comp))
+ and then
+ Chars (C) = Chars (Corresponding_Discriminant (Comp))
+ then
+ return C;
end if;
Next_Entity (C);
@@ -1887,8 +1896,8 @@ package body Exp_Ch5 is
-- We know the underlying type is a record, but its current view
-- may be private. We must retrieve the usable record declaration.
- if Nkind_In (Decl, N_Private_Type_Declaration,
- N_Private_Extension_Declaration)
+ if Nkind (Decl) in N_Private_Type_Declaration
+ | N_Private_Extension_Declaration
and then Present (Full_View (R_Typ))
then
RDef := Type_Definition (Declaration_Node (Full_View (R_Typ)));
@@ -2248,7 +2257,7 @@ package body Exp_Ch5 is
-- Since P is going to be evaluated more than once, any subscripts
-- in P must have their evaluation forced.
- if Nkind_In (Lhs, N_Indexed_Component, N_Selected_Component)
+ if Nkind (Lhs) in N_Indexed_Component | N_Selected_Component
and then Is_Ref_To_Bit_Packed_Array (Prefix (Lhs))
then
declare
@@ -2284,8 +2293,7 @@ package body Exp_Ch5 is
loop
Set_Analyzed (Exp, False);
- if Nkind_In (Exp, N_Indexed_Component,
- N_Selected_Component)
+ if Nkind (Exp) in N_Indexed_Component | N_Selected_Component
then
Exp := Prefix (Exp);
else
@@ -2448,38 +2456,7 @@ package body Exp_Ch5 is
if Is_Constrained (Etype (Lhs)) then
Apply_Length_Check (Rhs, Etype (Lhs));
end if;
-
- if Nkind (Rhs) = N_Allocator then
- declare
- Target_Typ : constant Entity_Id := Etype (Expression (Rhs));
- C_Es : Check_Result;
-
- begin
- C_Es :=
- Get_Range_Checks
- (Lhs,
- Target_Typ,
- Etype (Designated_Type (Etype (Lhs))));
-
- Insert_Range_Checks
- (C_Es,
- N,
- Target_Typ,
- Sloc (Lhs),
- Lhs);
- end;
- end if;
end if;
-
- -- Apply range check for access type case
-
- elsif Is_Access_Type (Etype (Lhs))
- and then Nkind (Rhs) = N_Allocator
- and then Nkind (Expression (Rhs)) = N_Qualified_Expression
- then
- Analyze_And_Resolve (Expression (Rhs));
- Apply_Range_Check
- (Expression (Rhs), Designated_Type (Etype (Lhs)));
end if;
-- Ada 2005 (AI-231): Generate the run-time check
@@ -2665,25 +2642,13 @@ package body Exp_Ch5 is
and then
not Restriction_Active (No_Dispatching_Calls))
then
- if Is_Limited_Type (Typ) then
-
- -- This can happen in an instance when the formal is an
- -- extension of a limited interface, and the actual is
- -- limited. This is an error according to AI05-0087, but
- -- is not caught at the point of instantiation in earlier
- -- versions. We also must verify that the limited type does
- -- not come from source as corner cases may exist where
- -- an assignment was not intended like the pathological case
- -- of a raise expression within a return statement.
-
- -- This is wrong, error messages cannot be issued during
- -- expansion, since they would be missed in -gnatc mode ???
-
- if Comes_From_Source (N) then
- Error_Msg_N
- ("assignment not available on limited type", N);
- end if;
+ -- We should normally not encounter any limited type here,
+ -- except in the corner case where an assignment was not
+ -- intended like the pathological case of a raise expression
+ -- within a return statement.
+ if Is_Limited_Type (Typ) then
+ pragma Assert (not Comes_From_Source (N));
return;
end if;
@@ -2896,8 +2861,8 @@ package body Exp_Ch5 is
Actual_Rhs : Node_Id := Rhs;
begin
- while Nkind_In (Actual_Rhs, N_Type_Conversion,
- N_Qualified_Expression)
+ while Nkind (Actual_Rhs) in
+ N_Type_Conversion | N_Qualified_Expression
loop
Actual_Rhs := Expression (Actual_Rhs);
end loop;
@@ -2971,7 +2936,7 @@ package body Exp_Ch5 is
-- Skip this if left-hand side is an array or record component
-- and elementary component validity checks are suppressed.
- if Nkind_In (Lhs, N_Selected_Component, N_Indexed_Component)
+ if Nkind (Lhs) in N_Selected_Component | N_Indexed_Component
and then not Validity_Check_Components
then
null;
@@ -3755,7 +3720,7 @@ package body Exp_Ch5 is
-- specific to pure if statements, however (see
-- Sem_Ch5.Analyze_If_Statement).
- Set_Comes_From_Source (New_If, Comes_From_Source (N));
+ Preserve_Comes_From_Source (New_If, N);
return;
-- No special processing for that elsif part, move to next
@@ -3775,9 +3740,9 @@ package body Exp_Ch5 is
-- Another optimization, special cases that can be simplified
-- if expression then
- -- return true;
+ -- return [standard.]true;
-- else
- -- return false;
+ -- return [standard.]false;
-- end if;
-- can be changed to:
@@ -3787,9 +3752,9 @@ package body Exp_Ch5 is
-- and
-- if expression then
- -- return false;
+ -- return [standard.]false;
-- else
- -- return true;
+ -- return [standard.]true;
-- end if;
-- can be changed to:
@@ -3822,9 +3787,9 @@ package body Exp_Ch5 is
Else_Expr : constant Node_Id := Expression (Else_Stm);
begin
- if Nkind (Then_Expr) = N_Identifier
+ if Nkind (Then_Expr) in N_Expanded_Name | N_Identifier
and then
- Nkind (Else_Expr) = N_Identifier
+ Nkind (Else_Expr) in N_Expanded_Name | N_Identifier
then
if Entity (Then_Expr) = Standard_True
and then Entity (Else_Expr) = Standard_False
@@ -3900,15 +3865,20 @@ package body Exp_Ch5 is
Array_Dim : constant Pos := Number_Dimensions (Array_Typ);
Id : constant Entity_Id := Defining_Identifier (I_Spec);
Loc : constant Source_Ptr := Sloc (Isc);
- Stats : constant List_Id := Statements (N);
+ Stats : List_Id := Statements (N);
Core_Loop : Node_Id;
Dim1 : Int;
Ind_Comp : Node_Id;
Iterator : Entity_Id;
- -- Start of processing for Expand_Iterator_Loop_Over_Array
-
begin
+ if Present (Iterator_Filter (I_Spec)) then
+ pragma Assert (Ada_Version >= Ada_2020);
+ Stats := New_List (Make_If_Statement (Loc,
+ Condition => Iterator_Filter (I_Spec),
+ Then_Statements => Stats));
+ end if;
+
-- for Element of Array loop
-- It requires an internally generated cursor to iterate over the array
@@ -4179,7 +4149,9 @@ package body Exp_Ch5 is
Elem_Typ : constant Entity_Id := Etype (Id);
Id_Kind : constant Entity_Kind := Ekind (Id);
Loc : constant Source_Ptr := Sloc (N);
- Stats : constant List_Id := Statements (N);
+
+ Stats : List_Id := Statements (N);
+ -- Maybe wrapped in a conditional if a filter is present
Cursor : Entity_Id;
Decl : Node_Id;
@@ -4201,6 +4173,13 @@ package body Exp_Ch5 is
-- The package in which the container type is declared
begin
+ if Present (Iterator_Filter (I_Spec)) then
+ pragma Assert (Ada_Version >= Ada_2020);
+ Stats := New_List (Make_If_Statement (Loc,
+ Condition => Iterator_Filter (I_Spec),
+ Then_Statements => Stats));
+ end if;
+
-- Determine the advancement and initialization steps for the cursor.
-- Analysis of the expanded loop will verify that the container has a
-- reverse iterator.
@@ -4674,11 +4653,20 @@ package body Exp_Ch5 is
Loop_Id : constant Entity_Id := Defining_Identifier (LPS);
Ltype : constant Entity_Id := Etype (Loop_Id);
Btype : constant Entity_Id := Base_Type (Ltype);
+ Stats : constant List_Id := Statements (N);
Expr : Node_Id;
Decls : List_Id;
New_Id : Entity_Id;
begin
+ if Present (Iterator_Filter (LPS)) then
+ pragma Assert (Ada_Version >= Ada_2020);
+ Set_Statements (N,
+ New_List (Make_If_Statement (Loc,
+ Condition => Iterator_Filter (LPS),
+ Then_Statements => Stats)));
+ end if;
+
-- Deal with loop over predicates
if Is_Discrete_Type (Ltype)
@@ -4795,7 +4783,7 @@ package body Exp_Ch5 is
Declarations => Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Statements (N)))),
+ Statements => Stats))),
End_Label => End_Label (N)));
@@ -4897,7 +4885,7 @@ package body Exp_Ch5 is
end if;
end if;
- -- When the iteration scheme mentiones attribute 'Loop_Entry, the loop
+ -- When the iteration scheme mentions attribute 'Loop_Entry, the loop
-- is transformed into a conditional block where the original loop is
-- the sole statement. Inspect the statements of the nested loop for
-- controlled objects.
@@ -4921,13 +4909,14 @@ package body Exp_Ch5 is
-- mode, the semantic analyzer may disallow one or both forms.
procedure Expand_Predicated_Loop (N : Node_Id) is
- Loc : constant Source_Ptr := Sloc (N);
- Isc : constant Node_Id := Iteration_Scheme (N);
- LPS : constant Node_Id := Loop_Parameter_Specification (Isc);
- Loop_Id : constant Entity_Id := Defining_Identifier (LPS);
- Ltype : constant Entity_Id := Etype (Loop_Id);
- Stat : constant List_Id := Static_Discrete_Predicate (Ltype);
- Stmts : constant List_Id := Statements (N);
+ Orig_Loop_Id : Node_Id := Empty;
+ Loc : constant Source_Ptr := Sloc (N);
+ Isc : constant Node_Id := Iteration_Scheme (N);
+ LPS : constant Node_Id := Loop_Parameter_Specification (Isc);
+ Loop_Id : constant Entity_Id := Defining_Identifier (LPS);
+ Ltype : constant Entity_Id := Etype (Loop_Id);
+ Stat : constant List_Id := Static_Discrete_Predicate (Ltype);
+ Stmts : constant List_Id := Statements (N);
begin
-- Case of iteration over non-static predicate, should not be possible
@@ -5206,7 +5195,13 @@ package body Exp_Ch5 is
Alternatives => Alts);
Append_To (Stmts, Cstm);
- -- Rewrite the loop
+ -- Rewrite the loop preserving the loop identifier in case there
+ -- are exit statements referencing it.
+
+ if Present (Identifier (N)) then
+ Orig_Loop_Id := New_Occurrence_Of
+ (Entity (Identifier (N)), Loc);
+ end if;
Set_Suppress_Assignment_Checks (D);
@@ -5218,6 +5213,7 @@ package body Exp_Ch5 is
Statements => New_List (
Make_Loop_Statement (Loc,
Statements => Stmts,
+ Identifier => Orig_Loop_Id,
End_Label => Empty)))));
Analyze (N);