aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_ch5.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_ch5.adb')
-rw-r--r--gcc/ada/sem_ch5.adb266
1 files changed, 81 insertions, 185 deletions
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 2342c54..336507a 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_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- --
@@ -26,6 +26,7 @@
with Aspects; use Aspects;
with Atree; use Atree;
with Checks; use Checks;
+with Debug; use Debug;
with Einfo; use Einfo;
with Errout; use Errout;
with Expander; use Expander;
@@ -39,8 +40,6 @@ with Namet; use Namet;
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_Case; use Sem_Case;
@@ -306,9 +305,8 @@ package body Sem_Ch5 is
if Is_Entity_Name (Opnd)
and then (Ekind (Entity (Opnd)) = E_Out_Parameter
- or else Ekind_In (Entity (Opnd),
- E_In_Out_Parameter,
- E_Generic_In_Out_Parameter)
+ or else Ekind (Entity (Opnd)) in
+ E_In_Out_Parameter | E_Generic_In_Out_Parameter
or else
(Ekind (Entity (Opnd)) = E_Variable
and then Nkind (Parent (Entity (Opnd))) =
@@ -321,7 +319,7 @@ package body Sem_Ch5 is
-- If assignment operand is a component reference, then we get the
-- actual subtype of the component for the unconstrained case.
- elsif Nkind_In (Opnd, N_Selected_Component, N_Explicit_Dereference)
+ elsif Nkind (Opnd) in N_Selected_Component | N_Explicit_Dereference
and then not Is_Unchecked_Union (Opnd_Type)
then
Decl := Build_Actual_Subtype_Of_Component (Opnd_Type, Opnd);
@@ -823,12 +821,10 @@ package body Sem_Ch5 is
-- that of the target mutable object.
if Is_Entity_Name (Lhs)
- and then Ekind_In (Entity (Lhs), E_In_Out_Parameter,
- E_Out_Parameter,
- E_Variable)
+ and then Is_Assignable (Entity (Lhs))
and then Is_Composite_Type (T1)
and then not Is_Constrained (Etype (Entity (Lhs)))
- and then Nkind_In (Rhs, N_If_Expression, N_Case_Expression)
+ and then Nkind (Rhs) in N_If_Expression | N_Case_Expression
then
Resolve (Rhs, Base_Type (T1));
@@ -997,7 +993,7 @@ package body Sem_Ch5 is
and then (Nkind (Rhs) /= N_Function_Call
or else Nkind (N) /= N_Block_Statement)
then
- -- Assignment verifies that the length of the Lsh and Rhs are equal,
+ -- Assignment verifies that the length of the Lhs and Rhs are equal,
-- but of course the indexes do not have to match. If the right-hand
-- side is a type conversion to an unconstrained type, a length check
-- is performed on the expression itself during expansion. In rare
@@ -1005,7 +1001,7 @@ package body Sem_Ch5 is
-- with a different representation, triggering incorrect code in the
-- back end.
- Apply_Length_Check (Rhs, Etype (Lhs));
+ Apply_Length_Check_On_Assignment (Rhs, Etype (Lhs), Lhs);
else
-- Discriminant checks are applied in the course of expansion
@@ -1242,7 +1238,7 @@ package body Sem_Ch5 is
-- Do not install the return object
- if not Ekind_In (Id, E_Constant, E_Variable)
+ if Ekind (Id) not in E_Constant | E_Variable
or else not Is_Return_Object (Id)
then
Install_Entity (Id);
@@ -1263,13 +1259,6 @@ package body Sem_Ch5 is
-- Start of processing for Analyze_Block_Statement
begin
- -- In SPARK mode, we reject block statements. Note that the case of
- -- block statements generated by the expander is fine.
-
- if Nkind (Original_Node (N)) = N_Block_Statement then
- Check_SPARK_05_Restriction ("block statement is not allowed", N);
- end if;
-
-- If no handled statement sequence is present, things are really messed
-- up, and we just return immediately (defence against previous errors).
@@ -1483,9 +1472,7 @@ package body Sem_Ch5 is
if Is_Entity_Name (Exp) then
Ent := Entity (Exp);
- if Ekind_In (Ent, E_Variable,
- E_In_Out_Parameter,
- E_Out_Parameter)
+ if Ekind (Ent) in E_Variable | E_In_Out_Parameter | E_Out_Parameter
then
if List_Length (Choices) = 1
and then Nkind (First (Choices)) in N_Subexpr
@@ -1583,13 +1570,6 @@ package body Sem_Ch5 is
Analyze_Choices (Alternatives (N), Exp_Type);
Check_Choices (N, Alternatives (N), Exp_Type, Others_Present);
- -- Case statement with single OTHERS alternative not allowed in SPARK
-
- if Others_Present and then List_Length (Alternatives (N)) = 1 then
- Check_SPARK_05_Restriction
- ("OTHERS as unique case alternative is not allowed", N);
- end if;
-
if Exp_Type = Universal_Integer and then not Others_Present then
Error_Msg_N ("case on universal integer requires OTHERS choice", Exp);
end if;
@@ -1672,11 +1652,6 @@ package body Sem_Ch5 is
return;
else
- if Has_Loop_In_Inner_Open_Scopes (U_Name) then
- Check_SPARK_05_Restriction
- ("exit label must name the closest enclosing loop", N);
- end if;
-
Set_Has_Exit (U_Name);
end if;
@@ -1712,42 +1687,6 @@ package body Sem_Ch5 is
Check_Unset_Reference (Cond);
end if;
- -- In SPARK mode, verify that the exit statement respects the SPARK
- -- restrictions.
-
- if Present (Cond) then
- if Nkind (Parent (N)) /= N_Loop_Statement then
- Check_SPARK_05_Restriction
- ("exit with when clause must be directly in loop", N);
- end if;
-
- else
- if Nkind (Parent (N)) /= N_If_Statement then
- if Nkind (Parent (N)) = N_Elsif_Part then
- Check_SPARK_05_Restriction
- ("exit must be in IF without ELSIF", N);
- else
- Check_SPARK_05_Restriction ("exit must be directly in IF", N);
- end if;
-
- elsif Nkind (Parent (Parent (N))) /= N_Loop_Statement then
- Check_SPARK_05_Restriction
- ("exit must be in IF directly in loop", N);
-
- -- First test the presence of ELSE, so that an exit in an ELSE leads
- -- to an error mentioning the ELSE.
-
- elsif Present (Else_Statements (Parent (N))) then
- Check_SPARK_05_Restriction ("exit must be in IF without ELSE", N);
-
- -- An exit in an ELSIF does not reach here, as it would have been
- -- detected in the case (Nkind (Parent (N)) /= N_If_Statement).
-
- elsif Present (Elsif_Parts (Parent (N))) then
- Check_SPARK_05_Restriction ("exit must be in IF without ELSIF", N);
- end if;
- end if;
-
-- Chain exit statement to associated loop entity
Set_Next_Exit_Statement (N, First_Exit_Statement (Scope_Id));
@@ -1772,8 +1711,6 @@ package body Sem_Ch5 is
Label_Ent : Entity_Id;
begin
- Check_SPARK_05_Restriction ("goto statement is not allowed", N);
-
-- Actual semantic checks
Check_Unreachable_Code (N);
@@ -1812,7 +1749,8 @@ package body Sem_Ch5 is
Scope_Id := Scope_Stack.Table (J).Entity;
if Label_Scope = Scope_Id
- or else not Ekind_In (Scope_Id, E_Block, E_Loop, E_Return_Statement)
+ or else Ekind (Scope_Id) not in
+ E_Block | E_Loop | E_Return_Statement
then
if Scope_Id /= Label_Scope then
Error_Msg_N
@@ -1847,7 +1785,7 @@ package body Sem_Ch5 is
Save_Unblocked_Exit_Count : constant Nat := Unblocked_Exit_Count;
-- Recursively save value of this global, will be restored on exit
- Save_In_Deleted_Code : Boolean;
+ Save_In_Deleted_Code : Boolean := In_Deleted_Code;
Del : Boolean := False;
-- This flag gets set True if a True condition has been found, which
@@ -1893,7 +1831,7 @@ package body Sem_Ch5 is
-- If condition is False, analyze THEN with expansion off
- else -- Is_False (Expr_Value (Cond))
+ else pragma Assert (Is_False (Expr_Value (Cond)));
Expander_Mode_Save_And_Set (False);
In_Deleted_Code := True;
Analyze_Statements (Tstm);
@@ -2273,8 +2211,8 @@ package body Sem_Ch5 is
-- If the domain of iteration is an expression, create a declaration for
-- it, so that finalization actions are introduced outside of the loop.
- -- The declaration must be a renaming because the body of the loop may
- -- assign to elements.
+ -- The declaration must be a renaming (both in GNAT and GNATprove
+ -- modes), because the body of the loop may assign to elements.
if not Is_Entity_Name (Iter_Name)
@@ -2283,14 +2221,15 @@ package body Sem_Ch5 is
-- doing expansion.
and then (Nkind (Parent (N)) /= N_Quantified_Expression
- or else Operating_Mode = Check_Semantics)
+ or else (Operating_Mode = Check_Semantics
+ and then not GNATprove_Mode))
- -- Do not perform this expansion for ASIS and when expansion is
- -- disabled, where the temporary may hide the transformation of a
- -- selected component into a prefixed function call, and references
- -- need to see the original expression.
+ -- Do not perform this expansion when expansion is disabled, where the
+ -- temporary may hide the transformation of a selected component into
+ -- a prefixed function call, and references need to see the original
+ -- expression.
- and then Expander_Active
+ and then (Expander_Active or GNATprove_Mode)
then
declare
Id : constant Entity_Id := Make_Temporary (Loc, 'R', Iter_Name);
@@ -2300,7 +2239,7 @@ package body Sem_Ch5 is
begin
-- If the domain of iteration is an array component that depends
- -- on a discriminant, create actual subtype for it. preanalysis
+ -- on a discriminant, create actual subtype for it. Preanalysis
-- does not generate the actual subtype of a selected component.
if Nkind (Iter_Name) = N_Selected_Component
@@ -2378,6 +2317,7 @@ package body Sem_Ch5 is
Insert_Actions (Parent (Parent (N)), New_List (Decl));
Rewrite (Name (N), New_Occurrence_Of (Id, Loc));
+ Analyze (Name (N));
Set_Etype (Id, Typ);
Set_Etype (Name (N), Typ);
end;
@@ -2449,7 +2389,7 @@ package body Sem_Ch5 is
-- AI12-0047 stipulates that the domain (array or container)
-- cannot be a component that depends on a discriminant if the
-- enclosing object is mutable, to prevent a modification of the
- -- dowmain of iteration in the course of an iteration.
+ -- domain of iteration in the course of an iteration.
-- If the object is an expression it has been captured in a
-- temporary, so examine original node.
@@ -2515,7 +2455,7 @@ package body Sem_Ch5 is
Check_Subtype_Indication (Etype (Def_Id));
- -- For a predefined container, The type of the loop variable is
+ -- For a predefined container, the type of the loop variable is
-- the Iterator_Element aspect of the container type.
else
@@ -2580,10 +2520,9 @@ package body Sem_Ch5 is
if Nkind (Orig_Iter_Name) = N_Selected_Component
and then
Present (Entity (Selector_Name (Orig_Iter_Name)))
- and then Ekind_In
- (Entity (Selector_Name (Orig_Iter_Name)),
- E_Component,
- E_Discriminant)
+ and then
+ Ekind (Entity (Selector_Name (Orig_Iter_Name))) in
+ E_Component | E_Discriminant
and then Is_Dependent_Component_Of_Mutable_Object
(Orig_Iter_Name)
then
@@ -2686,6 +2625,10 @@ package body Sem_Ch5 is
end if;
end if;
+
+ if Present (Iterator_Filter (N)) then
+ Analyze_And_Resolve (Iterator_Filter (N), Standard_Boolean);
+ end if;
end Analyze_Iterator_Specification;
-------------------
@@ -2857,8 +2800,8 @@ package body Sem_Ch5 is
if Analyzed (Original_Bound) then
return Original_Bound;
- elsif Nkind_In (Analyzed_Bound, N_Integer_Literal,
- N_Character_Literal)
+ elsif Nkind (Analyzed_Bound) in
+ N_Integer_Literal | N_Character_Literal
or else Is_Entity_Name (Analyzed_Bound)
then
Analyze_And_Resolve (Original_Bound, Typ);
@@ -3015,13 +2958,6 @@ package body Sem_Ch5 is
end if;
end;
- -- Loop parameter specification must include subtype mark in SPARK
-
- if Nkind (DS) = N_Range then
- Check_SPARK_05_Restriction
- ("loop parameter specification must include subtype mark", N);
- end if;
-
-- Analyze the subtype definition and create temporaries for the bounds.
-- Do not evaluate the range when preanalyzing a quantified expression
-- because bounds expressed as function calls with side effects will be
@@ -3063,8 +2999,8 @@ package body Sem_Ch5 is
and then not Is_Type (Entity (DS_Copy)))
or else (Nkind (DS_Copy) = N_Attribute_Reference
- and then Nam_In (Attribute_Name (DS_Copy),
- Name_Loop_Entry, Name_Old))
+ and then Attribute_Name (DS_Copy) in
+ Name_Loop_Entry | Name_Old)
or else Has_Aspect (Etype (DS_Copy), Aspect_Iterable)
@@ -3160,7 +3096,7 @@ package body Sem_Ch5 is
Check_Predicate_Use (Entity (Subtype_Mark (DS)));
end if;
- Make_Index (DS, N, In_Iter_Schm => True);
+ Make_Index (DS, N);
Set_Ekind (Id, E_Loop_Parameter);
-- A quantified expression which appears in a pre- or post-condition may
@@ -3204,14 +3140,15 @@ package body Sem_Ch5 is
-- Case where we have a range or a subtype, get type bounds
- if Nkind_In (DS, N_Range, N_Subtype_Indication)
+ if Nkind (DS) in N_Range | N_Subtype_Indication
and then not Error_Posted (DS)
and then Etype (DS) /= Any_Type
and then Is_Discrete_Type (Etype (DS))
then
declare
- L : Node_Id;
- H : Node_Id;
+ L : Node_Id;
+ H : Node_Id;
+ Null_Range : Boolean := False;
begin
if Nkind (DS) = N_Range then
@@ -3231,6 +3168,14 @@ package body Sem_Ch5 is
-- null range may be detected statically.
if Compile_Time_Compare (L, H, Assume_Valid => True) = GT then
+ if Compile_Time_Compare (L, H, Assume_Valid => False) = GT then
+ -- Since we know the range of the loop is always null,
+ -- set the appropriate flag to remove the loop entirely
+ -- during expansion.
+
+ Set_Is_Null_Loop (Loop_Nod);
+ Null_Range := True;
+ end if;
-- Suppress the warning if inside a generic template or
-- instance, since in practice they tend to be dubious in these
@@ -3241,24 +3186,14 @@ package body Sem_Ch5 is
-- Specialize msg if invalid values could make the loop
-- non-null after all.
- if Compile_Time_Compare
- (L, H, Assume_Valid => False) = GT
- then
- -- Since we know the range of the loop is null, set the
- -- appropriate flag to remove the loop entirely during
- -- expansion.
-
- Set_Is_Null_Loop (Loop_Nod);
-
+ if Null_Range then
if Comes_From_Source (N) then
Error_Msg_N
("??loop range is null, loop will not execute", DS);
end if;
- -- Here is where the loop could execute because of
- -- invalid values, so issue appropriate message and in
- -- this case we do not set the Is_Null_Loop flag since
- -- the loop may execute.
+ -- Here is where the loop could execute because of
+ -- invalid values, so issue appropriate message.
elsif Comes_From_Source (N) then
Error_Msg_N
@@ -3367,10 +3302,20 @@ package body Sem_Ch5 is
-- the warning is perfectly acceptable.
exception
- when others => null;
+ when others =>
+ -- With debug flag K we will get an exception unless an error
+ -- has already occurred (useful for debugging).
+
+ if Debug_Flag_K then
+ Check_Error_Detected;
+ end if;
end;
end if;
+ if Present (Iterator_Filter (N)) then
+ Analyze_And_Resolve (Iterator_Filter (N), Standard_Boolean);
+ end if;
+
-- A loop parameter cannot be effectively volatile (SPARK RM 7.1.3(4)).
-- This check is relevant only when SPARK_Mode is on as it is not a
-- standard Ada legality check.
@@ -3389,13 +3334,6 @@ package body Sem_Ch5 is
-- The following exception is raised by routine Prepare_Loop_Statement
-- to avoid further analysis of a transformed loop.
- function Disable_Constant (N : Node_Id) return Traverse_Result;
- -- If N represents an E_Variable entity, set Is_True_Constant To False
-
- procedure Disable_Constants is new Traverse_Proc (Disable_Constant);
- -- Helper for Analyze_Loop_Statement, to unset Is_True_Constant on
- -- variables referenced within an OpenACC construct.
-
procedure Prepare_Loop_Statement
(Iter : Node_Id;
Stop_Processing : out Boolean);
@@ -3403,22 +3341,6 @@ package body Sem_Ch5 is
-- transformed prior to analysis, and if so, perform it.
-- If Stop_Processing is set to True, should stop further processing.
- ----------------------
- -- Disable_Constant --
- ----------------------
-
- function Disable_Constant (N : Node_Id) return Traverse_Result is
- begin
- if Is_Entity_Name (N)
- and then Present (Entity (N))
- and then Ekind (Entity (N)) = E_Variable
- then
- Set_Is_True_Constant (Entity (N), False);
- end if;
-
- return OK;
- end Disable_Constant;
-
----------------------------
-- Prepare_Loop_Statement --
----------------------------
@@ -3975,7 +3897,7 @@ package body Sem_Ch5 is
Enter_Name (Id);
end if;
- -- In an element iterator, The loop parameter is a variable if
+ -- In an element iterator, the loop parameter is a variable if
-- the domain of iteration (container or array) is a variable.
if not Of_Present (I_Spec)
@@ -3994,6 +3916,12 @@ package body Sem_Ch5 is
Analyze_Statements (Statements (N));
end if;
+ -- If the loop has no side effects, mark it for removal.
+
+ if Side_Effect_Free_Loop (N) then
+ Set_Is_Null_Loop (N);
+ end if;
+
-- When the iteration scheme of a loop contains attribute 'Loop_Entry,
-- the loop is transformed into a conditional block. Retrieve the loop.
@@ -4030,15 +3958,6 @@ package body Sem_Ch5 is
if No (Iter) and then not Has_Exit (Ent) then
Check_Unreachable_Code (Stmt);
end if;
-
- -- Variables referenced within a loop subject to possible OpenACC
- -- offloading may be implicitly written to as part of the OpenACC
- -- transaction. Clear flags possibly conveying that they are constant,
- -- set for example when the code does not explicitly assign them.
-
- if Is_OpenAcc_Environment (Stmt) then
- Disable_Constants (Stmt);
- end if;
end Analyze_Loop_Statement;
----------------------------
@@ -4166,12 +4085,9 @@ package body Sem_Ch5 is
end loop;
-- If a label follows us, then we never have dead code, since
- -- someone could branch to the label, so we just ignore it, unless
- -- we are in formal mode where goto statements are not allowed.
+ -- someone could branch to the label, so we just ignore it.
- if Nkind (Nxt) = N_Label
- and then not Restriction_Check_Required (SPARK_05)
- then
+ if Nkind (Nxt) = N_Label then
return;
-- Otherwise see if we have a real statement following us
@@ -4204,8 +4120,8 @@ package body Sem_Ch5 is
-- This is the one case where we remove dead code in the
-- semantics as opposed to the expander, and we do not want
-- to remove code if we are not in code generation mode,
- -- since this messes up the ASIS trees or loses useful
- -- information in the CodePeer tree.
+ -- since this messes up the tree or loses useful information
+ -- for CodePeer.
-- Note that one might react by moving the whole circuit to
-- exp_ch5, but then we lose the warning in -gnatc mode.
@@ -4230,15 +4146,8 @@ package body Sem_Ch5 is
end loop;
end if;
- -- Now issue the warning (or error in formal mode)
-
- if Restriction_Check_Required (SPARK_05) then
- Check_SPARK_05_Restriction
- ("unreachable code is not allowed", Error_Node);
- else
- Error_Msg
- ("??unreachable code!", Sloc (Error_Node), Error_Node);
- end if;
+ Error_Msg
+ ("??unreachable code!", Sloc (Error_Node), Error_Node);
end if;
-- If the unconditional transfer of control instruction is the
@@ -4478,21 +4387,8 @@ package body Sem_Ch5 is
-- visible in the loop.
elsif Has_Implicit_Dereference (Etype (R_Copy)) then
- declare
- Disc : Entity_Id;
-
- begin
- Disc := First_Discriminant (Typ);
- while Present (Disc) loop
- if Has_Implicit_Dereference (Disc) then
- Build_Explicit_Dereference (R_Copy, Disc);
- exit;
- end if;
-
- Next_Discriminant (Disc);
- end loop;
- end;
-
+ Build_Explicit_Dereference
+ (R_Copy, Get_Reference_Discriminant (Etype (R_Copy)));
end if;
end if;