Source_Base_Type : constant Entity_Id := Base_Type (Source_Type);
Target_Base_Type : constant Entity_Id := Base_Type (Target_Type);
- procedure Convert_And_Check_Range;
- -- Convert the conversion operand to the target base type and save in
- -- a temporary. Then check the converted value against the range of the
- -- target subtype.
+ procedure Convert_And_Check_Range (Suppress : Check_Id);
+ -- Convert N to the target base type and save the result in a temporary.
+ -- The action is analyzed using the default checks as modified by the
+ -- given Suppress argument. Then check the converted value against the
+ -- range of the target subtype.
-----------------------------
-- Convert_And_Check_Range --
-----------------------------
- procedure Convert_And_Check_Range is
- Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N);
- Conv_Node : Node_Id;
+ procedure Convert_And_Check_Range (Suppress : Check_Id) is
+ Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N);
+ Conv_N : Node_Id;
begin
-- For enumeration types with non-standard representation this is a
and then Present (Enum_Pos_To_Rep (Source_Base_Type))
and then Is_Integer_Type (Target_Base_Type)
then
- Conv_Node :=
- OK_Convert_To
- (Typ => Target_Base_Type,
- Expr => Duplicate_Subexpr (N));
-
- -- Common case
-
+ Conv_N := OK_Convert_To (Target_Base_Type, Duplicate_Subexpr (N));
else
- Conv_Node :=
- Make_Type_Conversion (Loc,
- Subtype_Mark => New_Occurrence_Of (Target_Base_Type, Loc),
- Expression => Duplicate_Subexpr (N));
+ Conv_N := Convert_To (Target_Base_Type, Duplicate_Subexpr (N));
end if;
- -- We make a temporary to hold the value of the converted value
- -- (converted to the base type), and then do the test against this
- -- temporary. The conversion itself is replaced by an occurrence of
- -- Tnn and followed by the explicit range check. Note that checks
- -- are suppressed for this code, since we don't want a recursive
- -- range check popping up.
+ -- We make a temporary to hold the value of the conversion to the
+ -- target base type, and then do the test against this temporary.
+ -- N itself is replaced by an occurrence of Tnn and followed by
+ -- the explicit range check.
-- Tnn : constant Target_Base_Type := Target_Base_Type (N);
-- [constraint_error when Tnn not in Target_Type]
+ -- Tnn
Insert_Actions (N, New_List (
Make_Object_Declaration (Loc,
Defining_Identifier => Tnn,
Object_Definition => New_Occurrence_Of (Target_Base_Type, Loc),
Constant_Present => True,
- Expression => Conv_Node),
+ Expression => Conv_N),
Make_Raise_Constraint_Error (Loc,
Condition =>
Left_Opnd => New_Occurrence_Of (Tnn, Loc),
Right_Opnd => New_Occurrence_Of (Target_Type, Loc)),
Reason => Reason)),
- Suppress => All_Checks);
+ Suppress => Suppress);
Rewrite (N, New_Occurrence_Of (Tnn, Loc));
-- First special case, if the source type is already within the range
-- of the target type, then no check is needed (probably we should have
-- stopped Do_Range_Check from being set in the first place, but better
- -- late than never in preventing junk code and junk flag settings.
+ -- late than never in preventing junk code and junk flag settings).
if In_Subrange_Of (Source_Type, Target_Type)
-- Next test for the case where the target type is within the bounds
-- of the base type of the source type, since in this case we can
- -- simply convert these bounds to the base type of T to do the test.
+ -- simply convert the bounds of the target type to this base bype
+ -- to do the test.
-- [constraint_error when N not in
-- Source_Base_Type (Target_Type'First)
Suppress => All_Checks);
-- For conversions involving at least one type that is not discrete,
- -- first convert to target type and then generate the range check.
- -- This avoids problems with values that are close to a bound of the
- -- target type that would fail a range check when done in a larger
- -- source type before converting but would pass if converted with
+ -- first convert to the target base type and then generate the range
+ -- check. This avoids problems with values that are close to a bound
+ -- of the target type that would fail a range check when done in a
+ -- larger source type before converting but pass if converted with
-- rounding and then checked (such as in float-to-float conversions).
+ -- Note that overflow checks are not suppressed for this code because
+ -- we do not know whether the source type is in range of the target
+ -- base type (unlike in the next case below).
+
else
- Convert_And_Check_Range;
+ Convert_And_Check_Range (Suppress => Range_Check);
end if;
-- Note that at this stage we know that the Target_Base_Type is not in
-- in range of the target base type since we have not checked that case.
-- If that is the case, we can freely convert the source to the target,
- -- and then test the target result against the bounds.
+ -- and then test the target result against the bounds. Note that checks
+ -- are suppressed for this code, since we don't want a recursive range
+ -- check popping up.
elsif In_Subrange_Of (Source_Type, Target_Base_Type) then
- Convert_And_Check_Range;
+ Convert_And_Check_Range (Suppress => All_Checks);
-- At this stage, we know that we have two scalar types, which are
-- directly convertible, and where neither scalar type has a base