diff options
author | Ed Schonberg <schonberg@adacore.com> | 2018-07-31 09:56:36 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2018-07-31 09:56:36 +0000 |
commit | 948071faa6c0c6566056e0cb7b0a41c6c4b0ae79 (patch) | |
tree | 4b8b435d7b8c68e167d1c201cb17bac9e4f6b1be /gcc | |
parent | 51d4bdfb567c86de722ac5a72b79c8f51209228c (diff) | |
download | gcc-948071faa6c0c6566056e0cb7b0a41c6c4b0ae79.zip gcc-948071faa6c0c6566056e0cb7b0a41c6c4b0ae79.tar.gz gcc-948071faa6c0c6566056e0cb7b0a41c6c4b0ae79.tar.bz2 |
[Ada] Refine generation of range checks to happen in front end
2018-07-31 Ed Schonberg <schonberg@adacore.com>
gcc/ada/
* exp_attr.adb (Expand_Attribute, case Fixed_Value): Set the
base type of the result to ensure that proper overflow and range
checks are generated. If the target is a fixed-point tyoe,
generate the required overflow and range checks explicitly,
rather than relying on Apply_Type_Conversion_Checks, which might
simply set the Do_Range_Check flag and rely on the backend to
add the check.
From-SVN: r263104
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/ada/exp_attr.adb | 48 |
2 files changed, 55 insertions, 3 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 43d837b..b7987f1 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2018-07-31 Ed Schonberg <schonberg@adacore.com> + + * exp_attr.adb (Expand_Attribute, case Fixed_Value): Set the + base type of the result to ensure that proper overflow and range + checks are generated. If the target is a fixed-point tyoe, + generate the required overflow and range checks explicitly, + rather than relying on Apply_Type_Conversion_Checks, which might + simply set the Do_Range_Check flag and rely on the backend to + add the check. + 2018-07-31 Hristian Kirtchev <kirtchev@adacore.com> * sem_res.adb (Resolve_Call): Establish a transient scope to diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 77e706a..469a90e 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -3639,6 +3639,10 @@ package body Exp_Attr is -- not want this to go through the fixed-point conversion circuits. Note -- that the back end always treats fixed-point as equivalent to the -- corresponding integer type anyway. + -- However, in order to remove the handling of Do_Range_Check from the + -- backend, we force the generation of a check on the result by + -- setting the result type appropriately. Apply_Conversion_Checks + -- will generate the required expansion. when Attribute_Fixed_Value | Attribute_Integer_Value @@ -3647,15 +3651,53 @@ package body Exp_Attr is Make_Type_Conversion (Loc, Subtype_Mark => New_Occurrence_Of (Entity (Pref), Loc), Expression => Relocate_Node (First (Exprs)))); - Set_Etype (N, Entity (Pref)); + + -- Indicate that the result of the conversion may require a + -- range check (see below); + + Set_Etype (N, Base_Type (Entity (Pref))); Set_Analyzed (N); -- Note: it might appear that a properly analyzed unchecked -- conversion would be just fine here, but that's not the case, - -- since the full range checks performed by the following call + -- since the full range checks performed by the following code -- are critical. + -- Given that Fixed-point conversions are not further expanded + -- to prevent the involvement of real type operations we have to + -- construct two checks explicitly: one on the operand, and one + -- on the result. This used to be done in part in the back-end, + -- but for other targets (E.g. LLVM) it is preferable to create + -- the tests in full in the front-end. + + if Is_Fixed_Point_Type (Etype (N)) then + declare + Loc : constant Source_Ptr := Sloc (N); + Equiv_T : constant Entity_Id := Make_Temporary (Loc, 'T', N); + Expr : constant Node_Id := Expression (N); + Fst : constant Entity_Id := Root_Type (Etype (N)); + Decl : Node_Id; - Apply_Type_Conversion_Checks (N); + begin + Decl := Make_Full_Type_Declaration (Sloc (N), + Equiv_T, + Type_Definition => + Make_Signed_Integer_Type_Definition (Loc, + Low_Bound => Make_Integer_Literal (Loc, + Intval => Corresponding_Integer_Value + (Type_Low_Bound (Fst))), + High_Bound => Make_Integer_Literal (Loc, + Intval => Corresponding_Integer_Value + (Type_High_Bound (Fst))))); + Insert_Action (N, Decl); + + -- Verify that the conversion is possible. + Generate_Range_Check + (Expr, Equiv_T, CE_Overflow_Check_Failed); + + -- and verify that the result is in range. + Generate_Range_Check (N, Etype (N), CE_Range_Check_Failed); + end; + end if; ----------- -- Floor -- |