aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2012-10-05 16:26:27 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2012-10-05 16:26:27 +0200
commit967fb65e809daa9c8d5a233dab77dd5e61d8effc (patch)
tree2c59e16f45cb06bdd0078f6acdcad19653f91c17 /gcc/ada
parent60b68e56cecc0af3e14698ba66e620c2eb76705c (diff)
downloadgcc-967fb65e809daa9c8d5a233dab77dd5e61d8effc.zip
gcc-967fb65e809daa9c8d5a233dab77dd5e61d8effc.tar.gz
gcc-967fb65e809daa9c8d5a233dab77dd5e61d8effc.tar.bz2
[multiple changes]
2012-10-05 Robert Dewar <dewar@adacore.com> * sem_util.adb (Has_One_Matching_Field): Handle case of lone discriminant. 2012-10-05 Yannick Moy <moy@adacore.com> * checks.adb (Minimize_Eliminate_Overflow_Checks): Correct code for the division operation and exponent operation. Adjust bound for the mod and rem operations. From-SVN: r192126
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/ChangeLog11
-rw-r--r--gcc/ada/checks.adb203
-rw-r--r--gcc/ada/sem_util.adb15
3 files changed, 90 insertions, 139 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index b6e00a1..a17998a 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,16 @@
2012-10-05 Robert Dewar <dewar@adacore.com>
+ * sem_util.adb (Has_One_Matching_Field): Handle case of lone
+ discriminant.
+
+2012-10-05 Yannick Moy <moy@adacore.com>
+
+ * checks.adb (Minimize_Eliminate_Overflow_Checks): Correct code
+ for the division operation and exponent operation. Adjust bound
+ for the mod and rem operations.
+
+2012-10-05 Robert Dewar <dewar@adacore.com>
+
* checks.adb, checks.ads, s-tassta.adb, s-stposu.adb, s-spsufi.adb,
s-spsufi.ads, exp_ch4.adb: Minor reformatting.
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 225c3ee..061f979 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -1209,7 +1209,7 @@ package body Checks is
-- Here we know the result is Long_Long_Integer'Base, of that it has
-- been rewritten because the parent operation is a conversion. See
- -- Conversion_Optimization.Apply_Arithmetic_Overflow_Checked_Suppressed.
+ -- Apply_Arithmetic_Overflow_Checked_Suppressed.Conversion_Optimization.
else
pragma Assert
@@ -7087,147 +7087,80 @@ package body Checks is
when N_Op_Divide =>
- -- Following seems awfully complex, can it be simplified ???
+ -- If the right operand can only be zero, set 0..0
- Hi := No_Uint;
- Lo := No_Uint;
-
- declare
- S : Uint;
-
- begin
- -- First work on finding big absolute result values. These
- -- come from dividing large numbers (which we have in Llo
- -- and Lhi) by small values, which we need to figure out.
-
- -- Case where right operand can be positive
-
- if Rhi > 0 then
-
- -- Find smallest positive divisor
-
- if Rlo > 0 then
- S := Rlo;
- else
- S := Uint_1;
- end if;
-
- -- Big negative value divided by small positive value
- -- generates a candidate for lowest possible result.
-
- if Llo < 0 then
- Min (Lo, Llo / S);
- end if;
-
- -- Big positive value divided by small positive value
- -- generates a candidate for highest possible result.
-
- if Lhi > 0 then
- Max (Hi, Lhi / S);
- end if;
- end if;
-
- -- Case where right operand can be negative
-
- if Rlo < 0 then
-
- -- Find smallest absolute value negative divisor
-
- if Rhi < 0 then
- S := Rhi;
- else
- S := -Uint_1;
- end if;
-
- -- Big negative value divided by small negative value
- -- generates a candidate for largest possible result.
-
- if Llo < 0 then
- Max (Hi, Llo / S);
- end if;
-
- -- Big positive value divided by small negative value
- -- generates a candidate for lowest possible result.
-
- if Lhi > 0 then
- Min (Lo, Lhi / S);
- end if;
- end if;
-
- -- Now work on finding small absolute result values. These
- -- come from dividing small numbers, which we need to figure
- -- out, by large values (which we have in Rlo, Rhi).
-
- -- Case where left operand can be positive
+ if Rlo = 0 and then Rhi = 0 then
+ Lo := Uint_0;
+ Hi := Uint_0;
- if Lhi > 0 then
+ -- Possible bounds of division must come from dividing end
+ -- values of the input ranges (four possibilities), provided
+ -- zero is not included in the possible values of the right
+ -- operand.
+
+ -- Otherwise, we just consider two intervals of values for
+ -- the right operand: the interval of negative values (up to
+ -- -1) and the interval of positive values (starting at 1).
+ -- Since division by 1 is the identity, and division by -1
+ -- is negation, we get all possible bounds of division in that
+ -- case by considering:
+ -- - all values from the division of end values of input
+ -- ranges;
+ -- - the end values of the left operand;
+ -- - the negation of the end values of the left operand.
- -- Find smallest positive dividend
+ else
+ declare
+ Mrk : constant Uintp.Save_Mark := Mark;
+ -- Mark so we can release the RR and Ev values
- if Llo > 0 then
- S := Llo;
- else
- S := Uint_1;
- end if;
+ Ev1 : Uint;
+ Ev2 : Uint;
+ Ev3 : Uint;
+ Ev4 : Uint;
- -- Small positive values divided by large negative values
- -- generate candidates for low results.
+ begin
+ -- Discard extreme values of zero for the divisor, since
+ -- they will simply result in an exception in any case.
- if Rlo < 0 then
- Min (Lo, S / Rlo);
+ if Rlo = 0 then
+ Rlo := Uint_1;
+ elsif Rhi = 0 then
+ Rhi := -Uint_1;
end if;
- -- Small positive values divided by large positive values
- -- generate candidates for high results.
+ -- Compute possible bounds coming from dividing end
+ -- values of the input ranges.
- if Rhi > 0 then
- Max (Hi, S / Rhi);
- end if;
- end if;
+ Ev1 := Llo / Rlo;
+ Ev2 := Llo / Rhi;
+ Ev3 := Lhi / Rlo;
+ Ev4 := Lhi / Rhi;
- -- Case where left operand can be negative
+ Lo := UI_Min (UI_Min (Ev1, Ev2), UI_Min (Ev3, Ev4));
+ Hi := UI_Max (UI_Max (Ev1, Ev2), UI_Max (Ev3, Ev4));
- if Llo < 0 then
+ -- If the right operand can be both negative or positive,
+ -- include the end values of the left operand in the
+ -- extreme values, as well as their negation.
- -- Find smallest absolute value negative dividend
+ if Rlo < 0 and then Rhi > 0 then
+ Ev1 := Llo;
+ Ev2 := -Llo;
+ Ev3 := Lhi;
+ Ev4 := -Lhi;
- if Lhi < 0 then
- S := Lhi;
- else
- S := -Uint_1;
+ Min (Lo,
+ UI_Min (UI_Min (Ev1, Ev2), UI_Min (Ev3, Ev4)));
+ Max (Hi,
+ UI_Max (UI_Max (Ev1, Ev2), UI_Max (Ev3, Ev4)));
end if;
- -- Small negative value divided by large negative value
- -- generates a candidate for highest possible result.
-
- if Rlo < 0 then
- Max (Hi, Rlo / S);
- end if;
+ -- Release the RR and Ev values
- -- Small negative value divided by large positive value
- -- generates a candidate for lowest possible result.
-
- if Rhi > 0 then
- Min (Lo, Rhi / S);
- end if;
- end if;
-
- -- Finally, if neither Lo or Hi set (happens if the right
- -- operand is always zero for example), then set 0 .. 0.
-
- if Lo = No_Uint and then Hi = No_Uint then
- Lo := Uint_0;
- Hi := Uint_0;
-
- -- If one bound set and not the other copy
-
- elsif Lo = No_Uint then
- Lo := Hi;
-
- elsif Hi = No_Uint then
- Hi := Lo;
- end if;
- end;
+ Release_And_Save (Mrk, Lo, Hi);
+ end;
+ end if;
-- Exponentiation
@@ -7264,14 +7197,15 @@ package body Checks is
else
-- High bound comes either from exponentiation of largest
- -- positive value to largest exponent value, or from the
- -- exponentiation of most negative value to an odd exponent.
+ -- positive value to largest exponent value, or from
+ -- the exponentiation of most negative value to an
+ -- even exponent.
declare
Hi1, Hi2 : Uint;
begin
- if Lhi >= 0 then
+ if Lhi > 0 then
Hi1 := Lhi ** Rhi;
else
Hi1 := Uint_0;
@@ -7279,9 +7213,9 @@ package body Checks is
if Llo < 0 then
if Rhi mod 2 = 0 then
- Hi2 := Llo ** (Rhi - 1);
- else
Hi2 := Llo ** Rhi;
+ else
+ Hi2 := Llo ** (Rhi - 1);
end if;
else
Hi2 := Uint_0;
@@ -7316,7 +7250,7 @@ package body Checks is
when N_Op_Mod =>
declare
- Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi);
+ Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi) - 1;
-- This is the maximum absolute value of the result
begin
@@ -7371,9 +7305,10 @@ package body Checks is
when N_Op_Rem =>
declare
- Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi);
+ Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi) - 1;
-- This is the maximum absolute value of the result. Note
- -- that the result range does not depend on the sign of B.
+ -- that the result range does not depend on the sign of the
+ -- right operand.
begin
Lo := Uint_0;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 2202c88..1c9eb64 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -13622,7 +13622,9 @@ package body Sem_Util is
function Has_One_Matching_Field return Boolean;
-- Determines if Expec_Type is a record type with a single component or
-- discriminant whose type matches the found type or is one dimensional
- -- array whose component type matches the found type.
+ -- array whose component type matches the found type. In the case of
+ -- one discriminant, we ignore the variant parts. That's not accurate,
+ -- but good enough for the warning.
----------------------------
-- Has_One_Matching_Field --
@@ -13664,10 +13666,10 @@ package body Sem_Util is
if No (E) then
return False;
- elsif (Ekind (E) /= E_Discriminant
- and then Ekind (E) /= E_Component)
+ elsif not Ekind_In (E, E_Discriminant, E_Component)
or else (Chars (E) = Name_uTag
- or else Chars (E) = Name_uParent)
+ or else
+ Chars (E) = Name_uParent)
then
Next_Entity (E);
@@ -13679,7 +13681,10 @@ package body Sem_Util is
if not Covers (Etype (E), Found_Type) then
return False;
- elsif Present (Next_Entity (E)) then
+ elsif Present (Next_Entity (E))
+ and then (Ekind (E) = E_Component
+ or else Ekind (Next_Entity (E)) = E_Discriminant)
+ then
return False;
else