aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_attr.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_attr.adb')
-rw-r--r--gcc/ada/sem_attr.adb92
1 files changed, 50 insertions, 42 deletions
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index d38e71a..74e9d6f 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -12919,7 +12919,7 @@ package body Sem_Attr is
-- Where the context is augmented with the iteration
-- variable I of the right type, and Init_Var of type
- -- Accum_Subtype. If the Reducer has both procedure and
+ -- Accum_Typ. If the Reducer has both procedure and
-- function interpretations with the proper reducer profile
-- an ambiguity error is emitted. Note that, this could be a
-- false positive as the two may coexist without ambiguity
@@ -13204,33 +13204,7 @@ package body Sem_Attr is
return;
end if;
- -- If the Accum_Typ is an unconstrained array then a
- -- Constraint_Error will be raised at runtime as most
- -- computations will change its length type during the
- -- reduction execution, RM 4.5.10(25/5). For instance, this is
- -- the case with: [...]'Reduce ("&", ...). When the expression
- -- yields non-empty strings, the reduction repeatedly executes
- -- the following assignment:
- -- Acc := Expr (I) & Acc;
- -- which will raise a Constraint_Error since the number of
- -- elements is increasing.
-
- if not Is_Numeric_Type (Base_Type (Accum_Typ))
- and then not Is_Constrained (Accum_Typ)
- then
- declare
- Discard : Node_Id;
- pragma Unreferenced (Discard);
- begin
- Discard := Compile_Time_Constraint_Error
- (Reducer_N,
- "potential length mismatch!!??",
- Accum_Typ);
- return;
- end;
- end if;
-
- -- If no error has been posted and the accumulation type is
+ -- If no error has been posted and the accumulator type is
-- constrained, then the resolution of the reducer can start.
if Nkind (Reducer_N) = N_Attribute_Reference then
@@ -13278,45 +13252,79 @@ package body Sem_Attr is
end if;
end if;
- -- After resolving the reducer, determine the correct
- -- Accum_Subtype: if the reducer is an attribute (Min or Max),
- -- then the prefix type is the accumulation type.
+ -- After resolving the reducer, determine Accum_Typ: if the
+ -- reducer is an attribute (Min or Max), then its prefix is
+ -- the accumulator type.
if Nkind (Reducer_E) = N_Attribute_Reference then
- Accum_Typ := Etype (Prefix (Reducer_E));
+ Accum_Typ := Entity (Prefix (Reducer_E));
- -- If an operator from standard, then the type of its first
- -- formal woudl be Any_Type, in this case we make sure we don't
- -- use an universal type to avoid resolution problems later on.
+ -- If the reducer is an operator from Standard, then the type
+ -- of its first operand would be Any_Type. In this case, make
+ -- sure we do not have an universal type to avoid resolution
+ -- problems later on, and use the base type of numeric types
+ -- to avoid spurious subtype mismatches for the initial value.
- elsif Ekind (Reducer_E) = E_Operator
- or else Scope (Reducer_E) = Standard_Standard
- then
+ elsif Scope (Reducer_E) = Standard_Standard then
if Accum_Typ = Universal_Integer then
Accum_Typ := Standard_Integer;
elsif Accum_Typ = Universal_Real then
Accum_Typ := Standard_Float;
+ elsif Is_Numeric_Type (Accum_Typ) then
+ Accum_Typ := Base_Type (Accum_Typ);
end if;
- -- Otherwise, the Accum_Subtype is the subtype of the first
- -- formal of the reducer subprogram RM 4.5.10(19/5).
+ -- Otherwise, Accum_Typ is the subtype of the first formal
+ -- of the reducer subprogram (RM 4.5.10(19/5)).
+
+ elsif Ekind (Reducer_E) = E_Operator then
+ Accum_Typ := Etype (Left_Opnd (Reducer_E));
else
Accum_Typ := Etype (First_Formal (Reducer_E));
end if;
+
Set_Etype (N, Accum_Typ);
- -- Accumulation type must be nonlimited, RM 4.5.10(8/5)
+ -- The accumulator type must be nonlimited (RM 4.5.10(8/5))
if Is_Limited_Type (Accum_Typ) then
Error_Msg_N
- ("accumulated subtype of Reduce must be nonlimited", N);
+ ("type of reduction expression must be nonlimited", N);
+
+ -- If Accum_Typ is an unconstrained array and the reducer
+ -- subprogram is a function then a Constraint_Error will be
+ -- raised at run time, as most computations will change its
+ -- length during the reduction execution (RM 4.5.10(25/5)).
+ -- For instance, this is the case with:
+ -- [...]'Reduce ("&", ...)
+ -- When the expression yields non-empty strings, the reduction
+ -- repeatedly executes the following assignment:
+ -- Acc := Expr (I) & Acc;
+ -- which will raise a Constraint_Error since the number of
+ -- elements is increasing.
+
+ elsif Nkind (Reducer_E) /= N_Attribute_Reference
+ and then Ekind (Reducer_E) = E_Function
+ and then not Is_Numeric_Type (Accum_Typ)
+ and then not Is_Constrained (Accum_Typ)
+ then
+ declare
+ Discard : Node_Id;
+ pragma Unreferenced (Discard);
+ begin
+ Discard := Compile_Time_Constraint_Error
+ (Reducer_N,
+ "potential length mismatch!!??",
+ Accum_Typ);
+ end;
end if;
-- Complete the resolution of the reduction expression by
-- resolving the initial expression and array aggregate.
Resolve (Init_Value_Expr, Accum_Typ);
+
if Nkind (P) = N_Aggregate then
Resolve_Aggregate (P,
Make_Array_Type (Index => Standard_Positive,