diff options
author | Arnaud Charlet <charlet@gcc.gnu.org> | 2012-10-05 16:26:27 +0200 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2012-10-05 16:26:27 +0200 |
commit | 967fb65e809daa9c8d5a233dab77dd5e61d8effc (patch) | |
tree | 2c59e16f45cb06bdd0078f6acdcad19653f91c17 /gcc/ada | |
parent | 60b68e56cecc0af3e14698ba66e620c2eb76705c (diff) | |
download | gcc-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/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/ada/checks.adb | 203 | ||||
-rw-r--r-- | gcc/ada/sem_util.adb | 15 |
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 |