summaryrefslogtreecommitdiff
path: root/lib/timespec-add.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2015-11-07 23:36:45 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2015-11-07 23:37:07 -0800
commit6ea4ff5a362a150fb9e22eff1d8f2b87d017b7a4 (patch)
tree0ed8138e49f63f79593d5f5e81a64ef48e01c6ba /lib/timespec-add.c
parentb9acb9502fd7c4d3cd32b1fd46e644acba4bd878 (diff)
downloademacs-6ea4ff5a362a150fb9e22eff1d8f2b87d017b7a4.tar.gz
Merge from gnulib
This incorporates: 2015-11-05 timespec-sub: fix overflow bug; add tests 2015-11-04 intprops: revise _WRAPV macros, revert _OVERFLOW 2015-11-03 intprops: add parentheses * lib/intprops.h, lib/timespec-add.c, lib/timespec-sub.c: Copy from gnulib.
Diffstat (limited to 'lib/timespec-add.c')
-rw-r--r--lib/timespec-add.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/lib/timespec-add.c b/lib/timespec-add.c
index 255489eeb13..e8f6aac29d0 100644
--- a/lib/timespec-add.c
+++ b/lib/timespec-add.c
@@ -33,36 +33,39 @@ timespec_add (struct timespec a, struct timespec b)
int ns = a.tv_nsec + b.tv_nsec;
int nsd = ns - TIMESPEC_RESOLUTION;
int rns = ns;
+ time_t tmin = TYPE_MINIMUM (time_t);
+ time_t tmax = TYPE_MAXIMUM (time_t);
if (0 <= nsd)
{
rns = nsd;
- if (rs == TYPE_MAXIMUM (time_t))
- {
- if (0 <= bs)
- goto high_overflow;
- bs++;
- }
- else
+ if (bs < tmax)
+ bs++;
+ else if (rs < 0)
rs++;
+ else
+ goto high_overflow;
}
- if (INT_ADD_OVERFLOW (rs, bs))
+ /* INT_ADD_WRAPV is not appropriate since time_t might be unsigned.
+ In theory time_t might be narrower than int, so plain
+ INT_ADD_OVERFLOW does not suffice. */
+ if (! INT_ADD_OVERFLOW (rs, bs) && tmin <= rs + bs && rs + bs <= tmax)
+ rs += bs;
+ else
{
if (rs < 0)
{
- rs = TYPE_MINIMUM (time_t);
+ rs = tmin;
rns = 0;
}
else
{
high_overflow:
- rs = TYPE_MAXIMUM (time_t);
+ rs = tmax;
rns = TIMESPEC_RESOLUTION - 1;
}
}
- else
- rs += bs;
return make_timespec (rs, rns);
}