aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_case.adb
diff options
context:
space:
mode:
authorSteve Baird <baird@adacore.com>2021-10-15 15:23:34 -0700
committerPierre-Marie de Rodat <derodat@adacore.com>2021-10-25 15:07:21 +0000
commit1ddc39479b999841e0b0e994a47bf3cec8a4e54e (patch)
treef5241de8be61a6b3038b7123cd9a077ae642b99a /gcc/ada/sem_case.adb
parent8bada6e9751abd00fe9b1bd1d7fcfa073042e4dd (diff)
downloadgcc-1ddc39479b999841e0b0e994a47bf3cec8a4e54e.zip
gcc-1ddc39479b999841e0b0e994a47bf3cec8a4e54e.tar.gz
gcc-1ddc39479b999841e0b0e994a47bf3cec8a4e54e.tar.bz2
[Ada] Relax INOX restrictions when casing on composite value.
gcc/ada/ * sem_case.adb (Composite_Case_Ops.Box_Value_Required): A new function which takes a component type and returns a Boolean. Returns True for the cases which were formerly forbidden as components (these checks were formerly performed in the now-deleted procedure Check_Composite_Case_Selector.Check_Component_Subtype). (Composite_Case_Ops.Normalized_Case_Expr_Type): Hoist this function out of the Array_Case_Ops package because it has been generalized to also do the analogous thing in the case of a discriminated type. (Composite_Case_Ops.Scalar_Part_Count): Return 0 if Box_Value_Required returns True for the given type/subtype. (Composite_Case_Ops.Choice_Analysis.Choice_Analysis.Component_Bounds_Info. Traverse_Discrete_Parts): Return without doing anything if Box_Value_Required returns True for the given type/subtype. (Composite_Case_Ops.Choice_Analysis.Parse_Choice.Traverse_Choice): If Box_Value_Required yields True for a given component type, then check that the value of that component in a choice expression is indeed a box (in which case the component is ignored). * doc/gnat_rm/implementation_defined_pragmas.rst: Update documentation. * gnat_rm.texi: Regenerate.
Diffstat (limited to 'gcc/ada/sem_case.adb')
-rw-r--r--gcc/ada/sem_case.adb280
1 files changed, 144 insertions, 136 deletions
diff --git a/gcc/ada/sem_case.adb b/gcc/ada/sem_case.adb
index 31f14d5..1bd2670 100644
--- a/gcc/ada/sem_case.adb
+++ b/gcc/ada/sem_case.adb
@@ -106,10 +106,26 @@ package body Sem_Case is
package Composite_Case_Ops is
+ function Box_Value_Required (Subtyp : Entity_Id) return Boolean;
+ -- If result is True, then the only allowed value (in a choice
+ -- aggregate) for a component of this (sub)type is a box. This rule
+ -- means that such a component can be ignored in case alternative
+ -- selection. This in turn implies that it is ok if the component
+ -- type doesn't meet the usual restrictions, such as not being an
+ -- access/task/protected type, since nobody is going to look
+ -- at it.
+
function Choice_Count (Alternatives : List_Id) return Nat;
-- The sum of the number of choices for each alternative in the given
-- list.
+ function Normalized_Case_Expr_Type
+ (Case_Statement : Node_Id) return Entity_Id;
+ -- Usually returns the Etype of the selector expression of the
+ -- case statement. However, in the case of a constrained composite
+ -- subtype with a nonstatic constraint, returns the unconstrained
+ -- base type.
+
function Scalar_Part_Count (Subtyp : Entity_Id) return Nat;
-- Given the composite type Subtyp of a case selector, returns the
-- number of scalar parts in an object of this type. This is the
@@ -119,13 +135,6 @@ package body Sem_Case is
function Array_Choice_Length (Choice : Node_Id) return Nat;
-- Given a choice expression of an array type, returns its length.
- function Normalized_Case_Expr_Type
- (Case_Statement : Node_Id) return Entity_Id;
- -- Usually returns the Etype of the selector expression of the
- -- case statement. However, in the case of a constrained array
- -- subtype with a nonstatic constraint, returns the unconstrained
- -- array base type.
-
function Unconstrained_Array_Effective_Length
(Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat;
-- If the nominal subtype of the case selector is unconstrained,
@@ -1164,6 +1173,54 @@ package body Sem_Case is
return UI_To_Int (Len);
end Static_Array_Length;
+ ------------------------
+ -- Box_Value_Required --
+ ------------------------
+
+ function Box_Value_Required (Subtyp : Entity_Id) return Boolean is
+ -- Some of these restrictions will be relaxed eventually, but best
+ -- to initially err in the direction of being too restrictive.
+ begin
+ if Has_Predicates (Subtyp) then
+ return True;
+ elsif Is_Discrete_Type (Subtyp) then
+ if not Is_Static_Subtype (Subtyp) then
+ return True;
+ elsif Is_Enumeration_Type (Subtyp)
+ and then Has_Enumeration_Rep_Clause (Subtyp)
+ -- Maybe enumeration rep clauses can be ignored here?
+ then
+ return True;
+ end if;
+ elsif Is_Array_Type (Subtyp) then
+ if Number_Dimensions (Subtyp) /= 1 then
+ return True;
+ elsif not Is_Constrained (Subtyp) then
+ if not Is_Static_Subtype (Etype (First_Index (Subtyp))) then
+ return True;
+ end if;
+ elsif not Is_OK_Static_Range (First_Index (Subtyp)) then
+ return True;
+ end if;
+ elsif Is_Record_Type (Subtyp) then
+ if Has_Discriminants (Subtyp)
+ and then Is_Constrained (Subtyp)
+ and then not Has_Static_Discriminant_Constraint (Subtyp)
+ then
+ -- Perhaps treat differently the case where Subtyp is the
+ -- subtype of the top-level selector expression, as opposed
+ -- to the subtype of some subcomponent thereof.
+ return True;
+ end if;
+ else
+ -- Return True for any type that is not a discrete type,
+ -- a record type, or an array type.
+ return True;
+ end if;
+
+ return False;
+ end Box_Value_Required;
+
------------------
-- Choice_Count --
------------------
@@ -1179,13 +1236,45 @@ package body Sem_Case is
return Result;
end Choice_Count;
+ -------------------------------
+ -- Normalized_Case_Expr_Type --
+ -------------------------------
+
+ function Normalized_Case_Expr_Type
+ (Case_Statement : Node_Id) return Entity_Id
+ is
+ Unnormalized : constant Entity_Id :=
+ Etype (Expression (Case_Statement));
+
+ Is_Dynamically_Constrained_Array : constant Boolean :=
+ Is_Array_Type (Unnormalized)
+ and then Is_Constrained (Unnormalized)
+ and then not Has_Static_Array_Bounds (Unnormalized);
+
+ Is_Dynamically_Constrained_Record : constant Boolean :=
+ Is_Record_Type (Unnormalized)
+ and then Has_Discriminants (Unnormalized)
+ and then Is_Constrained (Unnormalized)
+ and then not Has_Static_Discriminant_Constraint (Unnormalized);
+ begin
+ if Is_Dynamically_Constrained_Array
+ or Is_Dynamically_Constrained_Record
+ then
+ return Base_Type (Unnormalized);
+ else
+ return Unnormalized;
+ end if;
+ end Normalized_Case_Expr_Type;
+
-----------------------
-- Scalar_Part_Count --
-----------------------
function Scalar_Part_Count (Subtyp : Entity_Id) return Nat is
begin
- if Is_Scalar_Type (Subtyp) then
+ if Box_Value_Required (Subtyp) then
+ return 0; -- component does not participate in case selection
+ elsif Is_Scalar_Type (Subtyp) then
return 1;
elsif Is_Array_Type (Subtyp) then
return Static_Array_Length (Subtyp)
@@ -1203,8 +1292,8 @@ package body Sem_Case is
return Result;
end;
else
- pragma Assert (False);
- raise Program_Error;
+ pragma Assert (Serious_Errors_Detected > 0);
+ return 0;
end if;
end Scalar_Part_Count;
@@ -1255,29 +1344,9 @@ package body Sem_Case is
return 0;
end Array_Choice_Length;
- -------------------------------
- -- Normalized_Case_Expr_Type --
- -------------------------------
-
- function Normalized_Case_Expr_Type
- (Case_Statement : Node_Id) return Entity_Id
- is
- Unnormalized : constant Entity_Id :=
- Etype (Expression (Case_Statement));
- begin
- if Is_Array_Type (Unnormalized)
- and then Is_Constrained (Unnormalized)
- and then not Has_Static_Array_Bounds (Unnormalized)
- then
- return Base_Type (Unnormalized);
- else
- return Unnormalized;
- end if;
- end Normalized_Case_Expr_Type;
-
- ------------------------------------------
+ ------------------------------------------
-- Unconstrained_Array_Effective_Length --
- ------------------------------------------
+ ------------------------------------------
function Unconstrained_Array_Effective_Length
(Array_Type : Entity_Id; Case_Statement : Node_Id) return Nat
@@ -1374,6 +1443,10 @@ package body Sem_Case is
procedure Traverse_Discrete_Parts (Subtyp : Entity_Id) is
begin
+ if Box_Value_Required (Subtyp) then
+ return;
+ end if;
+
if Is_Discrete_Type (Subtyp) then
Update_Result
((Low => Expr_Value (Type_Low_Bound (Subtyp)),
@@ -1668,13 +1741,32 @@ package body Sem_Case is
end loop;
end;
- if Box_Present (Comp_Assoc) then
- -- Box matches all values
- Update_Result_For_Full_Coverage
- (Etype (First (Choices (Comp_Assoc))));
- else
- Traverse_Choice (Expression (Comp_Assoc));
- end if;
+ declare
+ Comp_Type : constant Entity_Id :=
+ Etype (First (Choices (Comp_Assoc)));
+ begin
+ if Box_Value_Required (Comp_Type) then
+ -- This component is not allowed to
+ -- influence which alternative is
+ -- chosen; case choice must be box.
+ --
+ -- For example, component might be
+ -- of a real type or of an access type
+ -- or of a non-static discrete subtype.
+ if not Box_Present (Comp_Assoc) then
+ Error_Msg_N
+ ("Non-box case choice component value" &
+ " of unsupported type/subtype",
+ Expression (Comp_Assoc));
+ end if;
+ elsif Box_Present (Comp_Assoc) then
+ -- Box matches all values
+ Update_Result_For_Full_Coverage
+ (Etype (First (Choices (Comp_Assoc))));
+ else
+ Traverse_Choice (Expression (Comp_Assoc));
+ end if;
+ end;
if Binding_Chars (Comp_Assoc) /= No_Name
then
@@ -1702,9 +1794,19 @@ package body Sem_Case is
Next_Component_Or_Discriminant (Comp_From_Type);
end loop;
- pragma Assert
- (Nat (Next_Part - Saved_Next_Part)
- = Scalar_Part_Count (Etype (Expr)));
+ declare
+ Expr_Type : Entity_Id := Etype (Expr);
+ begin
+ if Has_Discriminants (Expr_Type) then
+ -- Avoid nonstatic choice expr types,
+ -- for which Scalar_Part_Count returns 0.
+ Expr_Type := Base_Type (Expr_Type);
+ end if;
+
+ pragma Assert
+ (Nat (Next_Part - Saved_Next_Part)
+ = Scalar_Part_Count (Expr_Type));
+ end;
end;
elsif Is_Array_Type (Etype (Expr)) then
if Is_Non_Empty_List (Component_Associations (Expr)) then
@@ -3256,108 +3358,14 @@ package body Sem_Case is
-----------------------------------
procedure Check_Composite_Case_Selector is
- -- Some of these restrictions will be relaxed eventually, but best
- -- to initially err in the direction of being too restrictive.
-
- procedure Check_Component_Subtype (Subtyp : Entity_Id);
- -- Recursively traverse subcomponent types to perform checks.
-
- -----------------------------
- -- Check_Component_Subtype --
- -----------------------------
-
- procedure Check_Component_Subtype (Subtyp : Entity_Id) is
- begin
- if Has_Predicates (Subtyp) then
- Error_Msg_N
- ("subtype of case selector (or subcomponent thereof) " &
- "has predicate", N);
- elsif Is_Discrete_Type (Subtyp) then
- if not Is_Static_Subtype (Subtyp) then
- Error_Msg_N
- ("discrete subtype of selector subcomponent is not " &
- "a static subtype", N);
- elsif Is_Enumeration_Type (Subtyp)
- and then Has_Enumeration_Rep_Clause (Subtyp)
- then
- Error_Msg_N
- ("enumeration type of selector subcomponent has " &
- "an enumeration representation clause", N);
- end if;
- elsif Is_Array_Type (Subtyp) then
- if Number_Dimensions (Subtyp) /= 1 then
- Error_Msg_N
- ("dimensionality of array type of case selector (or " &
- "subcomponent thereof) is greater than 1", N);
-
- elsif not Is_Constrained (Subtyp) then
- if not Is_Static_Subtype
- (Etype (First_Index (Subtyp)))
- then
- Error_Msg_N
- ("Unconstrained array subtype of case selector" &
- " has nonstatic index subtype", N);
- end if;
-
- elsif not Is_OK_Static_Range (First_Index (Subtyp)) then
- Error_Msg_N
- ("array subtype of case selector (or " &
- "subcomponent thereof) has nonstatic constraint", N);
- end if;
- Check_Component_Subtype (Component_Type (Subtyp));
- elsif Is_Record_Type (Subtyp) then
-
- if Has_Discriminants (Subtyp)
- and then Is_Constrained (Subtyp)
- and then not Has_Static_Discriminant_Constraint (Subtyp)
- then
- -- We are only disallowing nonstatic constraints for
- -- subcomponent subtypes, not for the subtype of the
- -- expression we are casing on. This test could be
- -- implemented via an Is_Recursive_Call parameter if
- -- that seems preferable.
-
- if Subtyp /= Check_Choices.Subtyp then
- Error_Msg_N
- ("constrained discriminated subtype of case " &
- "selector subcomponent has nonstatic " &
- "constraint", N);
- end if;
- end if;
-
- declare
- Comp : Entity_Id :=
- First_Component_Or_Discriminant (Base_Type (Subtyp));
- begin
- while Present (Comp) loop
- Check_Component_Subtype (Etype (Comp));
- Next_Component_Or_Discriminant (Comp);
- end loop;
- end;
- else
- Error_Msg_N
- ("type of case selector (or subcomponent thereof) is " &
- "not a discrete type, a record type, or an array type",
- N);
- end if;
- end Check_Component_Subtype;
-
begin
if not Is_Composite_Type (Subtyp) then
Error_Msg_N
("case selector type neither discrete nor composite", N);
-
elsif Is_Limited_Type (Subtyp) then
Error_Msg_N ("case selector type is limited", N);
-
elsif Is_Class_Wide_Type (Subtyp) then
Error_Msg_N ("case selector type is class-wide", N);
-
- elsif Needs_Finalization (Subtyp) then
- Error_Msg_N ("case selector type requires finalization", N);
-
- else
- Check_Component_Subtype (Subtyp);
end if;
end Check_Composite_Case_Selector;