aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/a-reatim.adb
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2015-01-07 10:52:50 +0100
committerArnaud Charlet <charlet@gcc.gnu.org>2015-01-07 10:52:50 +0100
commitc3831524bc0bf8d15bc95e26832a2a5e0752f9cc (patch)
tree24a17934b629bb46778ca5d90adbe1188eb86824 /gcc/ada/a-reatim.adb
parent1a9ee22281e0902c673d3c2e4cb5b83e07786569 (diff)
downloadgcc-c3831524bc0bf8d15bc95e26832a2a5e0752f9cc.zip
gcc-c3831524bc0bf8d15bc95e26832a2a5e0752f9cc.tar.gz
gcc-c3831524bc0bf8d15bc95e26832a2a5e0752f9cc.tar.bz2
[multiple changes]
2015-01-07 Tristan Gingold <gingold@adacore.com> * i-cpoint.adb (Copy_Terminated_Array): Use Copy_Array to handle overlap. 2015-01-07 Eric Botcazou <ebotcazou@adacore.com> * sem_ch3.adb (Analyze_Full_Type_Declaration): Do not automatically set No_Strict_Aliasing on access types. * fe.h (No_Strict_Aliasing_CP): Declare. * gcc-interface/trans.c (gigi): Force flag_strict_aliasing to 0 if No_Strict_Aliasing_CP is set. 2015-01-07 Johannes Kanig <kanig@adacore.com> * sem_ch8.adb (Analyze_Subprogram_Renaming) do not build function wrapper in gnatprove mode when the package is externally axiomatized. 2015-01-07 Jose Ruiz <ruiz@adacore.com> * a-reatim.adb (Time_Of): Reduce the number of spurious overflows in intermediate computations when the parameters have different signs. 2015-01-07 Javier Miranda <miranda@adacore.com> * exp_ch3.adb (Build_Init_Procedure): For derived types, improve the code which takes care of identifying and moving to the beginning of the init-proc the call to the init-proc of the parent type. From-SVN: r219287
Diffstat (limited to 'gcc/ada/a-reatim.adb')
-rw-r--r--gcc/ada/a-reatim.adb53
1 files changed, 52 insertions, 1 deletions
diff --git a/gcc/ada/a-reatim.adb b/gcc/ada/a-reatim.adb
index f59d083..1a233c4 100644
--- a/gcc/ada/a-reatim.adb
+++ b/gcc/ada/a-reatim.adb
@@ -218,7 +218,58 @@ package body Ada.Real_Time is
function Time_Of (SC : Seconds_Count; TS : Time_Span) return Time is
begin
- return Time (SC) + TS;
+ -- We want to return Time (SC) + TS. To avoid spurious overflows in
+ -- the intermediate result Time (SC) we take advantage of the different
+ -- signs in SC and TS (when that is the case).
+
+ -- If signs of SC and TS are different then we avoid converting SC to
+ -- Time (as we do in the else part). The reason for that is that SC
+ -- converted to Time may overflow the range of Time, while the addition
+ -- of SC plus TS does not overflow (because of their different signs).
+ -- The approach is to add and remove the greatest value of time
+ -- (greatest absolute value) to both SC and TS. SC and TS have different
+ -- signs, so we add the positive constant to the negative value, and the
+ -- negative constant to the positive value, to prevent overflows.
+
+ if (SC > 0 and then TS < 0.0)
+ or else (SC < 0 and then TS > 0.0)
+ then
+ declare
+ Closest_Boundary : constant Seconds_Count :=
+ (if TS >= 0.0 then
+ Seconds_Count (Time_Span_Last - Time_Span (0.5))
+ else
+ Seconds_Count (Time_Span_First + Time_Span (0.5)));
+ -- Value representing the integer part of the Time_Span boundary
+ -- closest to TS (its number of seconds). Truncate towards zero
+ -- to be sure that transforming this value back into Time cannot
+ -- overflow (when SC is equal to 0). The sign of Closest_Boundary
+ -- is always different from the sign of SC, hence avoiding
+ -- overflow in the expression Time (SC + Closest_Boundary)
+ -- which is part of the return statement.
+
+ Dist_To_Boundary : constant Time_Span :=
+ TS - Time_Span (Closest_Boundary);
+ -- Distance between TS and Closest_Boundary expressed in Time_Span
+ -- Both operands in the substraction have the same sign, hence
+ -- avoiding overflow.
+
+ begin
+ -- Both operands in the inner addition have different signs,
+ -- hence avoiding overflow. The Time () conversion and the outer
+ -- addition can overflow only if SC + TC is not within Time'Range.
+
+ return Time (SC + Closest_Boundary) + Dist_To_Boundary;
+ end;
+
+ -- Both operands have the same sign, so we can convert SC into Time
+ -- right away; if this conversion overflows then the result of adding SC
+ -- and TS would overflow anyway (so we would just be detecting the
+ -- overflow a bit earlier).
+
+ else
+ return Time (SC) + TS;
+ end if;
end Time_Of;
-----------------