From 5ef169ed701fa4f850fdca5563cdd468207d5d4f Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 17 May 2023 15:36:54 -0700
Subject: [PATCH] Prefer C23 ckd_* to Gnulib *_WRAPV macros

C23 has added ckd_add etc. macros with functionality equivalent to
the older Gnulib INT_ADD_WRAPV macros, so switch to the
more-standard names.
* admin/merge-gnulib (GNULIB_MODULES): Add stdckdint.
This merely makes the dependency explicit, as we were already
using this Gnulib module indirectly.
* lib-src/etags.c, src/lisp.h: Include stdckdint.h.
* lib-src/etags.c (xnmalloc, xnrealloc):
* src/alloc.c (xnmalloc, xnrealloc, xpalloc, Fmake_string)
(mark_memory):
* src/bignum.c (emacs_mpz_pow_ui):
* src/buffer.c (record_overlay_string, overlay_strings):
* src/bytecode.c (exec_byte_code):
* src/casefiddle.c (do_casify_multibyte_string):
* src/ccl.c (ccl_driver, Fccl_execute_on_string):
* src/character.c (char_width, c_string_width)
(lisp_string_width, count_size_as_multibyte)
(string_escape_byte8):
* src/cmds.c (internal_self_insert):
* src/coding.c (coding_alloc_by_realloc, produce_chars):
* src/data.c (arith_driver):
* src/dispnew.c (realloc_glyph_pool, init_display_interactive):
* src/doprnt.c (parse_format_integer):
* src/editfns.c (Freplace_buffer_contents, str2num)
(styled_format):
* src/emacs-module.c (module_global_reference_p)
(module_make_global_ref, module_funcall):
* src/eval.c (max_ensure_room):
* src/fileio.c (blocks_to_bytes):
* src/fns.c (Ffillarray):
* src/font.c (font_intern_prop):
* src/frame.c (check_frame_pixels):
* src/gnutls.c (gnutls_hex_string, gnutls_symmetric_aead):
* src/gtkutil.c (get_utf8_string):
* src/haikuterm.c (haiku_term_init):
* src/image.c (xbm_scan, image_to_emacs_colors)
(image_detect_edges, png_load_body):
* src/keyboard.c (Frecursion_depth):
* src/keymap.c (Flookup_key, Fkey_description):
* src/lisp.h (modiff_incr, SAFE_ALLOCA_LISP_EXTRA):
* src/lread.c (read_bool_vector):
* src/pgtkterm.c (pgtk_term_init):
* src/regex-emacs.c (regex_compile):
* src/term.c (encode_terminal_code):
* src/termcap.c (tputs):
* src/textconv.c (textconv_query):
* src/timefns.c (timespec_ticks, lisp_time_hz_ticks)
(Fdecode_time, check_tm_member):
* src/tparam.c (tparam1):
* src/w32term.c (w32_initialize_display_info):
* src/xdisp.c (fill_column_indicator_column, decode_mode_spec):
* src/xselect.c (selection_data_size, x_property_data_to_lisp):
* src/xsmfns.c (smc_save_yourself_CB):
* src/xterm.c (xm_setup_dnd_targets, x_sync_get_monotonic_time)
(x_sync_current_monotonic_time, x_sync_note_frame_times)
(x_display_set_last_user_time, x_term_init):
Prefer the C23 stdckdint macros to their
Gnulib intprops.h counterparts, since C23 is standard.
---
 admin/merge-gnulib |  2 +-
 lib-src/etags.c    |  5 +++--
 lib/gnulib.mk.in   |  1 +
 src/alloc.c        | 16 ++++++++--------
 src/bignum.c       |  2 +-
 src/buffer.c       |  6 +++---
 src/bytecode.c     |  2 +-
 src/casefiddle.c   |  4 ++--
 src/ccl.c          | 20 ++++++++++----------
 src/character.c    | 16 ++++++++--------
 src/cmds.c         |  2 +-
 src/coding.c       |  7 +++----
 src/data.c         |  6 +++---
 src/dispnew.c      |  6 +++---
 src/doprnt.c       |  4 ++--
 src/editfns.c      | 16 ++++++++--------
 src/emacs-module.c |  6 +++---
 src/eval.c         |  2 +-
 src/fileio.c       |  2 +-
 src/fns.c          |  3 +--
 src/font.c         |  2 +-
 src/frame.c        |  2 +-
 src/gnutls.c       |  6 +++---
 src/gtkutil.c      |  4 ++--
 src/haikuterm.c    |  2 +-
 src/image.c        | 22 +++++++++++-----------
 src/keyboard.c     |  2 +-
 src/keymap.c       |  6 +++---
 src/lisp.h         |  7 ++++---
 src/lread.c        | 12 ++++++------
 src/pgtkterm.c     |  3 +--
 src/regex-emacs.c  |  5 ++---
 src/term.c         |  2 +-
 src/termcap.c      |  2 +-
 src/textconv.c     |  6 +++---
 src/timefns.c      | 18 ++++++++----------
 src/tparam.c       |  3 +--
 src/w32term.c      |  2 +-
 src/xdisp.c        |  9 ++++-----
 src/xselect.c      |  6 +++---
 src/xsmfns.c       |  2 +-
 src/xterm.c        | 46 ++++++++++++++++++++--------------------------
 42 files changed, 143 insertions(+), 154 deletions(-)

diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 97487381886..3e7526102ae 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -44,7 +44,7 @@ GNULIB_MODULES='
   nanosleep nproc nstrftime
   pathmax pipe2 pselect pthread_sigmask
   qcopy-acl readlink readlinkat regex
-  sig2str sigdescr_np socklen stat-time std-gnu11 stdbool stddef stdio
+  sig2str sigdescr_np socklen stat-time std-gnu11 stdbool stdckdint stddef stdio
   stpcpy strnlen strtoimax symlink sys_stat sys_time
   tempname time-h time_r time_rz timegm timer-time timespec-add timespec-sub
   update-copyright unlocked-io utimensat
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 2c6b4e7a630..147ecbd7c1b 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -109,6 +109,7 @@ University of California, as described above. */
 #include <limits.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <stdckdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sysstdio.h>
@@ -8038,7 +8039,7 @@ xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
   ptrdiff_t nbytes;
   assume (0 <= nitems);
   assume (0 < item_size);
-  if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes))
+  if (ckd_mul (&nbytes, nitems, item_size))
     memory_full ();
   return xmalloc (nbytes);
 }
@@ -8049,7 +8050,7 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
   ptrdiff_t nbytes;
   assume (0 <= nitems);
   assume (0 < item_size);
-  if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
+  if (ckd_mul (&nbytes, nitems, item_size) || SIZE_MAX < nbytes)
     memory_full ();
   void *result = realloc (pa, nbytes);
   if (!result)
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 5722e2588eb..a25bee25aae 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -147,6 +147,7 @@
 #  stat-time \
 #  std-gnu11 \
 #  stdbool \
+#  stdckdint \
 #  stddef \
 #  stdio \
 #  stpcpy \
diff --git a/src/alloc.c b/src/alloc.c
index 29393deeff4..17ca5c725d0 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -863,7 +863,7 @@ xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
 {
   eassert (0 <= nitems && 0 < item_size);
   ptrdiff_t nbytes;
-  if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
+  if (ckd_mul (&nbytes, nitems, item_size) || SIZE_MAX < nbytes)
     memory_full (SIZE_MAX);
   return xmalloc (nbytes);
 }
@@ -877,7 +877,7 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
 {
   eassert (0 <= nitems && 0 < item_size);
   ptrdiff_t nbytes;
-  if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
+  if (ckd_mul (&nbytes, nitems, item_size) || SIZE_MAX < nbytes)
     memory_full (SIZE_MAX);
   return xrealloc (pa, nbytes);
 }
@@ -924,13 +924,13 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
      NITEMS_MAX, and what the C language can represent safely.  */
 
   ptrdiff_t n, nbytes;
-  if (INT_ADD_WRAPV (n0, n0 >> 1, &n))
+  if (ckd_add (&n, n0, n0 >> 1))
     n = PTRDIFF_MAX;
   if (0 <= nitems_max && nitems_max < n)
     n = nitems_max;
 
   ptrdiff_t adjusted_nbytes
-    = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes)
+    = ((ckd_mul (&nbytes, n, item_size) || SIZE_MAX < nbytes)
        ? min (PTRDIFF_MAX, SIZE_MAX)
        : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
   if (adjusted_nbytes)
@@ -942,9 +942,9 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
   if (! pa)
     *nitems = 0;
   if (n - n0 < nitems_incr_min
-      && (INT_ADD_WRAPV (n0, nitems_incr_min, &n)
+      && (ckd_add (&n, n0, nitems_incr_min)
 	  || (0 <= nitems_max && nitems_max < n)
-	  || INT_MULTIPLY_WRAPV (n, item_size, &nbytes)))
+	  || ckd_mul (&nbytes, n, item_size)))
     memory_full (SIZE_MAX);
   pa = xrealloc (pa, nbytes);
   *nitems = n;
@@ -2375,7 +2375,7 @@ a multibyte string even if INIT is an ASCII character.  */)
       ptrdiff_t len = CHAR_STRING (c, str);
       EMACS_INT string_len = XFIXNUM (length);
 
-      if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes))
+      if (ckd_mul (&nbytes, len, string_len))
 	string_overflow ();
       val = make_clear_multibyte_string (string_len, nbytes, clearit);
       if (!clearit)
@@ -5226,7 +5226,7 @@ mark_memory (void const *start, void const *end)
 	 a Lisp_Object might be split into registers saved into
 	 non-adjacent words and P might be the low-order word's value.  */
       intptr_t ip;
-      INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip);
+      ckd_add (&ip, (intptr_t) p, (intptr_t) lispsym);
       mark_maybe_pointer ((void *) ip, true);
     }
 }
diff --git a/src/bignum.c b/src/bignum.c
index e64653b2873..22ed171533f 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -354,7 +354,7 @@ emacs_mpz_pow_ui (mpz_t rop, mpz_t const base, unsigned long exp)
   enum { lim = min (NLIMBS_LIMIT, GMP_NLIMBS_MAX - pow_ui_extra_limbs) };
 
   int nbase = emacs_mpz_size (base), n;
-  if (INT_MULTIPLY_WRAPV (nbase, exp, &n) || lim < n)
+  if (ckd_mul (&n, nbase, exp) || lim < n)
     overflow_error ();
   mpz_pow_ui (rop, base, exp);
 }
diff --git a/src/buffer.c b/src/buffer.c
index 7951b7ac322..0c46b201586 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -3343,7 +3343,7 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str,
   else
     nbytes = SBYTES (str);
 
-  if (INT_ADD_WRAPV (ssl->bytes, nbytes, &nbytes))
+  if (ckd_add (&nbytes, nbytes, ssl->bytes))
     memory_full (SIZE_MAX);
   ssl->bytes = nbytes;
 
@@ -3357,7 +3357,7 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str,
       else
 	nbytes = SBYTES (str2);
 
-      if (INT_ADD_WRAPV (ssl->bytes, nbytes, &nbytes))
+      if (ckd_add (&nbytes, nbytes, ssl->bytes))
 	memory_full (SIZE_MAX);
       ssl->bytes = nbytes;
     }
@@ -3429,7 +3429,7 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
       unsigned char *p;
       ptrdiff_t total;
 
-      if (INT_ADD_WRAPV (overlay_heads.bytes, overlay_tails.bytes, &total))
+      if (ckd_add (&total, overlay_heads.bytes, overlay_tails.bytes))
 	memory_full (SIZE_MAX);
       if (total > overlay_str_len)
 	overlay_str_buf = xpalloc (overlay_str_buf, &overlay_str_len,
diff --git a/src/bytecode.c b/src/bytecode.c
index 74a94859aba..4207ff0b71f 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1327,7 +1327,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
 	    Lisp_Object v1 = TOP;
 	    intmax_t res;
 	    if (FIXNUMP (v1) && FIXNUMP (v2)
-		&& !INT_MULTIPLY_WRAPV (XFIXNUM (v1), XFIXNUM (v2), &res)
+		&& !ckd_mul (&res, XFIXNUM (v1), XFIXNUM (v2))
 		&& !FIXNUM_OVERFLOW_P (res))
 	      TOP = make_fixnum (res);
 	    else
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 1a959b1c07b..d567a5e353a 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -283,8 +283,8 @@ do_casify_multibyte_string (struct casing_context *ctx, Lisp_Object obj)
 
   ptrdiff_t size = SCHARS (obj), n;
   USE_SAFE_ALLOCA;
-  if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &n)
-      || INT_ADD_WRAPV (n, sizeof (struct casing_str_buf), &n))
+  if (ckd_mul (&n, size, MAX_MULTIBYTE_LENGTH)
+      || ckd_add (&n, n, sizeof (struct casing_str_buf)))
     n = PTRDIFF_MAX;
   unsigned char *dst = SAFE_ALLOCA (n);
   unsigned char *dst_end = dst + n;
diff --git a/src/ccl.c b/src/ccl.c
index ce9abd59493..67f2a275841 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -1156,9 +1156,9 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
 	ccl_expr_self:
 	  switch (op)
 	    {
-	    case CCL_PLUS: INT_ADD_WRAPV (reg[rrr], i, &reg[rrr]); break;
-	    case CCL_MINUS: INT_SUBTRACT_WRAPV (reg[rrr], i, &reg[rrr]); break;
-	    case CCL_MUL: INT_MULTIPLY_WRAPV (reg[rrr], i, &reg[rrr]); break;
+	    case CCL_PLUS: ckd_add (&reg[rrr], reg[rrr], i); break;
+	    case CCL_MINUS: ckd_sub (&reg[rrr], reg[rrr], i); break;
+	    case CCL_MUL: ckd_mul (&reg[rrr], reg[rrr], i); break;
 	    case CCL_DIV:
 	      if (!i)
 		CCL_INVALID_CMD;
@@ -1194,7 +1194,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
 	      if (i == -1)
 		{
 		  reg[7] = 0;
-		  INT_SUBTRACT_WRAPV (0, reg[rrr], &reg[rrr]);
+		  ckd_sub (&reg[rrr], 0, reg[rrr]);
 		}
 	      else
 		{
@@ -1251,9 +1251,9 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
 	ccl_set_expr:
 	  switch (op)
 	    {
-	    case CCL_PLUS: INT_ADD_WRAPV (i, j, &reg[rrr]); break;
-	    case CCL_MINUS: INT_SUBTRACT_WRAPV (i, j, &reg[rrr]); break;
-	    case CCL_MUL: INT_MULTIPLY_WRAPV (i, j, &reg[rrr]); break;
+	    case CCL_PLUS: ckd_add (&reg[rrr], i, j); break;
+	    case CCL_MINUS: ckd_sub (&reg[rrr], i, j); break;
+	    case CCL_MUL: ckd_mul (&reg[rrr], i, j); break;
 	    case CCL_DIV:
 	      if (!j)
 		CCL_INVALID_CMD;
@@ -1288,7 +1288,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
 		CCL_INVALID_CMD;
 	      if (j == -1)
 		{
-		  INT_SUBTRACT_WRAPV (0, reg[rrr], &reg[rrr]);
+		  ckd_sub (&reg[rrr], 0, reg[rrr]);
 		  reg[7] = 0;
 		}
 	      else
@@ -2169,8 +2169,8 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY
 
   buf_magnification = ccl.buf_magnification ? ccl.buf_magnification : 1;
   outbufsize = str_bytes;
-  if (INT_MULTIPLY_WRAPV (buf_magnification, outbufsize, &outbufsize)
-      || INT_ADD_WRAPV (256, outbufsize, &outbufsize))
+  if (ckd_mul (&outbufsize, outbufsize, buf_magnification)
+      || ckd_add (&outbufsize, outbufsize, 256))
     memory_full (SIZE_MAX);
   outp = outbuf = xmalloc (outbufsize);
 
diff --git a/src/character.c b/src/character.c
index d0b18367a83..ae153a579d6 100644
--- a/src/character.c
+++ b/src/character.c
@@ -250,7 +250,7 @@ char_width (int c, struct Lisp_Char_Table *dp)
 	    if (c >= 0)
 	      {
 		int w = CHARACTER_WIDTH (c);
-		if (INT_ADD_WRAPV (width, w, &width))
+		if (ckd_add (&width, width, w))
 		  string_overflow ();
 	      }
 	  }
@@ -301,7 +301,7 @@ c_string_width (const unsigned char *str, ptrdiff_t len, int precision,
 	  *nbytes = i_byte;
 	  return width;
 	}
-      if (INT_ADD_WRAPV (thiswidth, width, &width))
+      if (ckd_add (&width, width, thiswidth))
 	string_overflow ();
       i++;
       i_byte += bytes;
@@ -441,7 +441,7 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to,
 	  *nbytes = i_byte - from_byte;
 	  return width;
 	}
-      if (INT_ADD_WRAPV (thiswidth, width, &width))
+      if (ckd_add (&width, width, thiswidth))
 	string_overflow ();
       i += chars;
       i_byte += bytes;
@@ -664,7 +664,7 @@ count_size_as_multibyte (const unsigned char *str, ptrdiff_t len)
   for (ptrdiff_t i = 0; i < len; i++)
     nonascii += str[i] >> 7;
   ptrdiff_t bytes;
-  if (INT_ADD_WRAPV (len, nonascii, &bytes))
+  if (ckd_add (&bytes, len, nonascii))
     string_overflow ();
   return bytes;
 }
@@ -780,21 +780,21 @@ string_escape_byte8 (Lisp_Object string)
   if (byte8_count == 0)
     return string;
 
-  if (INT_MULTIPLY_WRAPV (byte8_count, 3, &thrice_byte8_count))
+  if (ckd_mul (&thrice_byte8_count, byte8_count, 3))
     string_overflow ();
 
   if (multibyte)
     {
       /* Convert 2-byte sequence of byte8 chars to 4-byte octal.  */
-      if (INT_ADD_WRAPV (nchars, thrice_byte8_count, &uninit_nchars)
-	  || INT_ADD_WRAPV (nbytes, 2 * byte8_count, &uninit_nbytes))
+      if (ckd_add (&uninit_nchars, nchars, thrice_byte8_count)
+	  || ckd_add (&uninit_nbytes, nbytes, 2 * byte8_count))
 	string_overflow ();
       val = make_uninit_multibyte_string (uninit_nchars, uninit_nbytes);
     }
   else
     {
       /* Convert 1-byte sequence of byte8 chars to 4-byte octal.  */
-      if (INT_ADD_WRAPV (thrice_byte8_count, nbytes, &uninit_nbytes))
+      if (ckd_add (&uninit_nbytes, thrice_byte8_count, nbytes))
 	string_overflow ();
       val = make_uninit_string (uninit_nbytes);
     }
diff --git a/src/cmds.c b/src/cmds.c
index 15caa4a6972..37e1779296a 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -453,7 +453,7 @@ internal_self_insert (int c, EMACS_INT n)
 	}
 
       ptrdiff_t to;
-      if (INT_ADD_WRAPV (PT, chars_to_delete, &to))
+      if (ckd_add (&to, PT, chars_to_delete))
 	to = PTRDIFF_MAX;
       replace_range (PT, to, string, 1, 1, 1, 0, false);
       Fforward_char (make_fixnum (n));
diff --git a/src/coding.c b/src/coding.c
index a2e0d7040f8..f014749c4ea 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -989,7 +989,7 @@ static void
 coding_alloc_by_realloc (struct coding_system *coding, ptrdiff_t bytes)
 {
   ptrdiff_t newbytes;
-  if (INT_ADD_WRAPV (coding->dst_bytes, bytes, &newbytes)
+  if (ckd_add (&newbytes, coding->dst_bytes, bytes)
       || SIZE_MAX < newbytes)
     string_overflow ();
   coding->destination = xrealloc (coding->destination, newbytes);
@@ -7059,9 +7059,8 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table,
 		{
 		  eassert (growable_destination (coding));
 		  ptrdiff_t dst_size;
-		  if (INT_MULTIPLY_WRAPV (to_nchars, MAX_MULTIBYTE_LENGTH,
-					  &dst_size)
-		      || INT_ADD_WRAPV (buf_end - buf, dst_size, &dst_size))
+		  if (ckd_mul (&dst_size, to_nchars, MAX_MULTIBYTE_LENGTH)
+		      || ckd_add (&dst_size, dst_size, buf_end - buf))
 		    memory_full (SIZE_MAX);
 		  dst = alloc_destination (coding, dst_size, dst);
 		  if (EQ (coding->src_object, coding->dst_object))
diff --git a/src/data.c b/src/data.c
index 8f9ee63e779..9d7e7effdcd 100644
--- a/src/data.c
+++ b/src/data.c
@@ -3190,9 +3190,9 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args,
 	intmax_t a;
 	switch (code)
 	  {
-	  case Aadd : overflow = INT_ADD_WRAPV (accum, next, &a); break;
-	  case Amult: overflow = INT_MULTIPLY_WRAPV (accum, next, &a); break;
-	  case Asub : overflow = INT_SUBTRACT_WRAPV (accum, next, &a); break;
+	  case Aadd : overflow = ckd_add (&a, accum, next); break;
+	  case Amult: overflow = ckd_mul (&a, accum, next); break;
+	  case Asub : overflow = ckd_sub (&a, accum, next); break;
 	  case Adiv:
 	    if (next == 0)
 	      xsignal0 (Qarith_error);
diff --git a/src/dispnew.c b/src/dispnew.c
index a928a5d1b14..9133d515ca3 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -1385,7 +1385,7 @@ realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim)
 	       || matrix_dim.width != pool->ncolumns);
 
   /* Enlarge the glyph pool.  */
-  if (INT_MULTIPLY_WRAPV (matrix_dim.height, matrix_dim.width, &needed))
+  if (ckd_mul (&needed, matrix_dim.height, matrix_dim.width))
     memory_full (SIZE_MAX);
   if (needed > pool->nglyphs)
     {
@@ -6653,8 +6653,8 @@ init_display_interactive (void)
        change.  It's not clear what better we could do.  The rest of
        the code assumes that (width + 2) * height * sizeof (struct glyph)
        does not overflow and does not exceed PTRDIFF_MAX or SIZE_MAX.  */
-    if (INT_ADD_WRAPV (width, 2, &area)
-	|| INT_MULTIPLY_WRAPV (height, area, &area)
+    if (ckd_add (&area, width, 2)
+	|| ckd_mul (&area, area, height)
 	|| min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) < area)
       fatal ("screen size %dx%d too big", width, height);
   }
diff --git a/src/doprnt.c b/src/doprnt.c
index 3ebb957e9f2..e8911fad252 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -134,8 +134,8 @@ parse_format_integer (char const *fmt, int *value)
   bool overflow = false;
   for (; '0' <= *fmt && *fmt <= '9'; fmt++)
     {
-      overflow |= INT_MULTIPLY_WRAPV (n, 10, &n);
-      overflow |= INT_ADD_WRAPV (n, *fmt - '0', &n);
+      overflow |= ckd_mul (&n, n, 10);
+      overflow |= ckd_add (&n, n, *fmt - '0');
     }
   if (overflow || min (PTRDIFF_MAX, SIZE_MAX) - SIZE_BOUND_EXTRA < n)
     error ("Format width or precision too large");
diff --git a/src/editfns.c b/src/editfns.c
index d02cce4aef3..44e11841faa 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2027,8 +2027,8 @@ nil.  */)
   ptrdiff_t ins_bytes = size_b / CHAR_BIT + 1;
   ptrdiff_t *buffer;
   ptrdiff_t bytes_needed;
-  if (INT_MULTIPLY_WRAPV (diags, 2 * sizeof *buffer, &bytes_needed)
-      || INT_ADD_WRAPV (del_bytes + ins_bytes, bytes_needed, &bytes_needed))
+  if (ckd_mul (&bytes_needed, diags, 2 * sizeof *buffer)
+      || ckd_add (&bytes_needed, bytes_needed, del_bytes + ins_bytes))
     memory_full (SIZE_MAX);
   USE_SAFE_ALLOCA;
   buffer = SAFE_ALLOCA (bytes_needed);
@@ -3296,7 +3296,7 @@ str2num (char *str, char **str_end)
 {
   ptrdiff_t n = 0;
   for (; c_isdigit (*str); str++)
-    if (INT_MULTIPLY_WRAPV (n, 10, &n) || INT_ADD_WRAPV (n, *str - '0', &n))
+    if (ckd_mul (&n, n, 10) || ckd_add (&n, n, *str - '0'))
       n = PTRDIFF_MAX;
   *str_end = str;
   return n;
@@ -3464,8 +3464,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
 
   /* Allocate the info and discarded tables.  */
   ptrdiff_t info_size, alloca_size;
-  if (INT_MULTIPLY_WRAPV (nspec_bound, sizeof *info, &info_size)
-      || INT_ADD_WRAPV (formatlen, info_size, &alloca_size)
+  if (ckd_mul (&info_size, nspec_bound, sizeof *info)
+      || ckd_add (&alloca_size, formatlen, info_size)
       || SIZE_MAX < alloca_size)
     memory_full (SIZE_MAX);
   info = SAFE_ALLOCA (alloca_size);
@@ -4012,8 +4012,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
 	      /* Compute the total bytes needed for this item, including
 		 excess precision and padding.  */
 	      ptrdiff_t numwidth;
-	      if (INT_ADD_WRAPV (prefixlen + sprintf_bytes, excess_precision,
-				 &numwidth))
+	      if (ckd_add (&numwidth, prefixlen + sprintf_bytes,
+			   excess_precision))
 		numwidth = PTRDIFF_MAX;
 	      ptrdiff_t padding
 		= numwidth < field_width ? field_width - numwidth : 0;
@@ -4173,7 +4173,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
 
       ptrdiff_t used = p - buf;
       ptrdiff_t buflen_needed;
-      if (INT_ADD_WRAPV (used, convbytes, &buflen_needed))
+      if (ckd_add (&buflen_needed, used, convbytes))
 	string_overflow ();
       if (bufsize <= buflen_needed)
 	{
diff --git a/src/emacs-module.c b/src/emacs-module.c
index d158e243139..10699ec25d9 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -416,7 +416,7 @@ module_global_reference_p (emacs_value v, ptrdiff_t *n)
     }
   /* Only used for debugging, so we don't care about overflow, just
      make sure the operation is defined.  */
-  INT_ADD_WRAPV (*n, h->count, n);
+  ckd_add (n, *n, h->count);
   return false;
 }
 
@@ -435,7 +435,7 @@ module_make_global_ref (emacs_env *env, emacs_value value)
     {
       Lisp_Object value = HASH_VALUE (h, i);
       struct module_global_reference *ref = XMODULE_GLOBAL_REFERENCE (value);
-      bool overflow = INT_ADD_WRAPV (ref->refcount, 1, &ref->refcount);
+      bool overflow = ckd_add (&ref->refcount, ref->refcount, 1);
       if (overflow)
 	overflow_error ();
       return &ref->value;
@@ -662,7 +662,7 @@ module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs,
   Lisp_Object *newargs;
   USE_SAFE_ALLOCA;
   ptrdiff_t nargs1;
-  if (INT_ADD_WRAPV (nargs, 1, &nargs1))
+  if (ckd_add (&nargs1, nargs, 1))
     overflow_error ();
   SAFE_ALLOCA_LISP (newargs, nargs1);
   newargs[0] = value_to_lisp (func);
diff --git a/src/eval.c b/src/eval.c
index cd3eb0a3676..3f4e77cd3b1 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -254,7 +254,7 @@ init_eval (void)
 static void
 max_ensure_room (intmax_t *m, intmax_t a, intmax_t b)
 {
-  intmax_t sum = INT_ADD_WRAPV (a, b, &sum) ? INTMAX_MAX : sum;
+  intmax_t sum = ckd_add (&sum, a, b) ? INTMAX_MAX : sum;
   *m = max (*m, sum);
 }
 
diff --git a/src/fileio.c b/src/fileio.c
index a364aa2ea33..859cf57d249 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -6276,7 +6276,7 @@ static Lisp_Object
 blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate)
 {
   intmax_t n;
-  if (!INT_MULTIPLY_WRAPV (blocksize, blocks, &n))
+  if (!ckd_mul (&n, blocksize, blocks))
     return make_int (negate ? -n : n);
   Lisp_Object bs = make_uint (blocksize);
   if (negate)
diff --git a/src/fns.c b/src/fns.c
index 561f526f8d0..bfd19e8c8f2 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2938,8 +2938,7 @@ ARRAY is a vector, string, char-table, or bool-vector.  */)
 	  else
 	    {
 	      ptrdiff_t product;
-	      if (INT_MULTIPLY_WRAPV (size, len, &product)
-		  || product != size_byte)
+	      if (ckd_mul (&product, size, len) || product != size_byte)
 		error ("Attempt to change byte length of a string");
 	      for (idx = 0; idx < size_byte; idx++)
 		*p++ = str[idx % len];
diff --git a/src/font.c b/src/font.c
index de8748dd857..e586277a5d3 100644
--- a/src/font.c
+++ b/src/font.c
@@ -279,7 +279,7 @@ font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol)
 	    {
 	      if (i == len)
 		return make_fixnum (n);
-	      if (INT_MULTIPLY_WRAPV (n, 10, &n))
+	      if (ckd_mul (&n, n, 10))
 		break;
 	    }
 
diff --git a/src/frame.c b/src/frame.c
index 2cea96d4a32..037914ac9dc 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3729,7 +3729,7 @@ check_frame_pixels (Lisp_Object size, Lisp_Object pixelwise, int item_size)
     item_size = 1;
 
   if (!integer_to_intmax (size, &sz)
-      || INT_MULTIPLY_WRAPV (sz, item_size, &pixel_size))
+      || ckd_mul (&pixel_size, sz, item_size))
     args_out_of_range_3 (size, make_int (INT_MIN / item_size),
 			 make_int (INT_MAX / item_size));
 
diff --git a/src/gnutls.c b/src/gnutls.c
index ca7e9fc4c73..8f0e2d01703 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -1083,8 +1083,8 @@ gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
 {
   ptrdiff_t prefix_length = strlen (prefix);
   ptrdiff_t retlen;
-  if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
-      || INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
+  if (ckd_mul (&retlen, buf_size, 3)
+      || ckd_add (&retlen, retlen, prefix_length - (buf_size != 0)))
     string_overflow ();
   Lisp_Object ret = make_uninit_string (retlen);
   char *string = SSDATA (ret);
@@ -2378,7 +2378,7 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
 
   ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
   ptrdiff_t tagged_size;
-  if (INT_ADD_WRAPV (isize, cipher_tag_size, &tagged_size)
+  if (ckd_add (&tagged_size, isize, cipher_tag_size)
       || SIZE_MAX < tagged_size)
     memory_full (SIZE_MAX);
   size_t storage_length = tagged_size;
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 4cc0f9f15b4..22b2a70f279 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -694,8 +694,8 @@ get_utf8_string (const char *str)
 
       len = strlen (str);
       ptrdiff_t alloc;
-      if (INT_MULTIPLY_WRAPV (nr_bad, 4, &alloc)
-	  || INT_ADD_WRAPV (len + 1, alloc, &alloc)
+      if (ckd_mul (&alloc, nr_bad, 4)
+	  || ckd_add (&alloc, alloc, len + 1)
 	  || SIZE_MAX < alloc)
 	memory_full (SIZE_MAX);
       up = utf8_str = xmalloc (alloc);
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 8733b82fb2b..212870064e8 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -4420,7 +4420,7 @@ haiku_term_init (void)
     {
       nbytes = sizeof "GNU Emacs" + sizeof " at ";
 
-      if (INT_ADD_WRAPV (nbytes, SBYTES (system_name), &nbytes))
+      if (ckd_add (&nbytes, nbytes, SBYTES (system_name)))
 	memory_full (SIZE_MAX);
 
       name_buffer = alloca (nbytes);
diff --git a/src/image.c b/src/image.c
index 8ee802a9d62..87a0c1ca497 100644
--- a/src/image.c
+++ b/src/image.c
@@ -4003,7 +4003,7 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
 		  digit = char_hexdigit (c);
 		  if (digit < 0)
 		    break;
-		  overflow |= INT_MULTIPLY_WRAPV (value, 16, &value);
+		  overflow |= ckd_mul (&value, value, 16);
 		  value += digit;
 		}
 	    }
@@ -4013,7 +4013,7 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
 	      while (*s < end
 		     && (c = *(*s)++, '0' <= c && c <= '7'))
 		{
-		  overflow |= INT_MULTIPLY_WRAPV (value, 8, &value);
+		  overflow |= ckd_mul (&value, value, 8);
 		  value += c - '0';
 		}
 	    }
@@ -4024,8 +4024,8 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
 	  while (*s < end
 		 && (c = *(*s)++, c_isdigit (c)))
 	    {
-	      overflow |= INT_MULTIPLY_WRAPV (value, 10, &value);
-	      overflow |= INT_ADD_WRAPV (value, c - '0', &value);
+	      overflow |= ckd_mul (&value, value, 10);
+	      overflow |= ckd_add (&value, value, c - '0');
 	    }
 	}
 
@@ -4069,7 +4069,7 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
 	      if (digit < 0)
 		return 0;
 
-	      overflow |= INT_MULTIPLY_WRAPV (value, 16, &value);
+	      overflow |= ckd_mul (&value, value, 16);
 	      value += digit;
 	    }
 	}
@@ -6136,8 +6136,8 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p)
   HGDIOBJ prev;
 #endif /* HAVE_NTGUI */
 
-  if (INT_MULTIPLY_WRAPV (sizeof *colors, img->width, &nbytes)
-      || INT_MULTIPLY_WRAPV (img->height, nbytes, &nbytes)
+  if (ckd_mul (&nbytes, sizeof *colors, img->width)
+      || ckd_mul (&nbytes, nbytes, img->height)
       || SIZE_MAX < nbytes)
     memory_full (SIZE_MAX);
   colors = xmalloc (nbytes);
@@ -6282,8 +6282,8 @@ image_detect_edges (struct frame *f, struct image *img,
 
 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
 
-  if (INT_MULTIPLY_WRAPV (sizeof *new, img->width, &nbytes)
-      || INT_MULTIPLY_WRAPV (img->height, nbytes, &nbytes))
+  if (ckd_mul (&nbytes, sizeof *new, img->width)
+      || ckd_mul (&nbytes, nbytes, img->height))
     memory_full (SIZE_MAX);
   new = xmalloc (nbytes);
 
@@ -7655,8 +7655,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
   row_bytes = png_get_rowbytes (png_ptr, info_ptr);
 
   /* Allocate memory for the image.  */
-  if (INT_MULTIPLY_WRAPV (row_bytes, sizeof *pixels, &nbytes)
-      || INT_MULTIPLY_WRAPV (nbytes, height, &nbytes))
+  if (ckd_mul (&nbytes, row_bytes, sizeof *pixels)
+      || ckd_mul (&nbytes, nbytes, height))
     memory_full (SIZE_MAX);
   c->pixels = pixels = xmalloc (nbytes);
   c->rows = rows = xmalloc (height * sizeof *rows);
diff --git a/src/keyboard.c b/src/keyboard.c
index b1ccf4acde4..14c55666768 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -11161,7 +11161,7 @@ DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
   (void)
 {
   EMACS_INT sum;
-  INT_ADD_WRAPV (command_loop_level, minibuf_level, &sum);
+  ckd_add (&sum, command_loop_level, minibuf_level);
   return make_fixnum (sum);
 }
 
diff --git a/src/keymap.c b/src/keymap.c
index 7f5777c9251..da2af98c2d6 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -1363,7 +1363,7 @@ recognize the default bindings, just as `read-key-sequence' does.  */)
 		{
 		  USE_SAFE_ALLOCA;
 		  ptrdiff_t size = SCHARS (key_item), n;
-		  if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &n))
+		  if (ckd_mul (&n, size, MAX_MULTIBYTE_LENGTH))
 		    n = PTRDIFF_MAX;
 		  unsigned char *dst = SAFE_ALLOCA (n);
 		  unsigned char *p = dst;
@@ -1411,7 +1411,7 @@ recognize the default bindings, just as `read-key-sequence' does.  */)
 
 	  USE_SAFE_ALLOCA;
 	  ptrdiff_t size = SCHARS (lc_key), n;
-	  if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &n))
+	  if (ckd_mul (&n, size, MAX_MULTIBYTE_LENGTH))
 	    n = PTRDIFF_MAX;
 	  unsigned char *dst = SAFE_ALLOCA (n);
 
@@ -2097,7 +2097,7 @@ For an approximate inverse of this, see `kbd'.  */)
 
   /* This has one extra element at the end that we don't pass to Fconcat.  */
   ptrdiff_t size4;
-  if (INT_MULTIPLY_WRAPV (nkeys + nprefix, 4, &size4))
+  if (ckd_mul (&size4, nkeys + nprefix, 4))
     memory_full (SIZE_MAX);
   SAFE_ALLOCA_LISP (args, size4);
 
diff --git a/src/lisp.h b/src/lisp.h
index 57c1c7395c1..2bfcd1a1983 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -23,6 +23,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <alloca.h>
 #include <setjmp.h>
 #include <stdarg.h>
+#include <stdckdint.h>
 #include <stddef.h>
 #include <string.h>
 #include <float.h>
@@ -3927,7 +3928,7 @@ modiff_incr (modiff_count *a, ptrdiff_t len)
      increasing it too much.  */
   verify (PTRDIFF_MAX <= ULLONG_MAX);
   int incr = len == 0 ? 1 : elogb (len) + 1;
-  bool modiff_overflow = INT_ADD_WRAPV (a0, incr, a);
+  bool modiff_overflow = ckd_add (a, a0, incr);
   eassert (!modiff_overflow && *a >> 30 >> 30 == 0);
   return a0;
 }
@@ -5422,8 +5423,8 @@ safe_free_unbind_to (specpdl_ref count, specpdl_ref sa_count, Lisp_Object val)
 #define SAFE_ALLOCA_LISP_EXTRA(buf, nelt, extra)	       \
   do {							       \
     ptrdiff_t alloca_nbytes;				       \
-    if (INT_MULTIPLY_WRAPV (nelt, word_size, &alloca_nbytes)   \
-	|| INT_ADD_WRAPV (alloca_nbytes, extra, &alloca_nbytes) \
+    if (ckd_mul (&alloca_nbytes, nelt, word_size)	       \
+	|| ckd_add (&alloca_nbytes, alloca_nbytes, extra)      \
 	|| SIZE_MAX < alloca_nbytes)			       \
       memory_full (SIZE_MAX);				       \
     else if (alloca_nbytes <= sa_avail)			       \
diff --git a/src/lread.c b/src/lread.c
index 4f1d29d80b2..d2e544afef9 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -3377,8 +3377,8 @@ read_bool_vector (Lisp_Object readcharfun)
 	    invalid_syntax ("#&", readcharfun);
 	  break;
 	}
-      if (INT_MULTIPLY_WRAPV (length, 10, &length)
-	  || INT_ADD_WRAPV (length, c - '0', &length))
+      if (ckd_mul (&length, length, 10)
+	  || ckd_add (&length, length, c - '0'))
 	invalid_syntax ("#&", readcharfun);
     }
 
@@ -3423,8 +3423,8 @@ skip_lazy_string (Lisp_Object readcharfun)
 	    UNREAD (c);
 	  break;
 	}
-      if (INT_MULTIPLY_WRAPV (nskip, 10, &nskip)
-	  || INT_ADD_WRAPV (nskip, c - '0', &nskip))
+      if (ckd_mul (&nskip, nskip, 10)
+	  || ckd_add (&nskip, nskip, c - '0'))
 	invalid_syntax ("#@", readcharfun);
       digits++;
       if (digits == 2 && nskip == 0)
@@ -3988,8 +3988,8 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
 		    c = READCHAR;
 		    if (c < '0' || c > '9')
 		      break;
-		    if (INT_MULTIPLY_WRAPV (n, 10, &n)
-			|| INT_ADD_WRAPV (n, c - '0', &n))
+		    if (ckd_mul (&n, n, 10)
+			|| ckd_add (&n, n, c - '0'))
 		      invalid_syntax ("#", readcharfun);
 		  }
 		if (c == 'r' || c == 'R')
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 6cb1a3a4626..b8c626d81d8 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -6832,8 +6832,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
 
   Lisp_Object system_name = Fsystem_name ();
   ptrdiff_t nbytes;
-  if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2,
-		     &nbytes))
+  if (ckd_add (&nbytes, SBYTES (Vinvocation_name), SBYTES (system_name) + 2))
     memory_full (SIZE_MAX);
   dpyinfo->x_id = ++x_display_id;
   dpyinfo->x_id_name = xmalloc (nbytes);
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index 746779490ad..e3237cd425a 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -2202,9 +2202,8 @@ regex_compile (re_char *pattern, ptrdiff_t size,
 				FALLTHROUGH;
 			      case '1': case '2': case '3': case '4':
 			      case '5': case '6': case '7': case '8': case '9':
-				if (INT_MULTIPLY_WRAPV (regnum, 10, &regnum)
-				    || INT_ADD_WRAPV (regnum, c - '0',
-						      &regnum))
+				if (ckd_mul (&regnum, regnum, 10)
+				    || ckd_add (&regnum, regnum, c - '0'))
 				  FREE_STACK_RETURN (REG_ESIZE);
 				break;
 			      default:
diff --git a/src/term.c b/src/term.c
index 2b28d3303e8..4df3de8f4a5 100644
--- a/src/term.c
+++ b/src/term.c
@@ -533,7 +533,7 @@ encode_terminal_code (struct glyph *src, int src_len,
      multibyte-form.  But, it may be enlarged on demand if
      Vglyph_table contains a string or a composite glyph is
      encountered.  */
-  if (INT_MULTIPLY_WRAPV (src_len, MAX_MULTIBYTE_LENGTH, &required))
+  if (ckd_mul (&required, src_len, MAX_MULTIBYTE_LENGTH))
     memory_full (SIZE_MAX);
   if (encode_terminal_src_size < required)
     encode_terminal_src = xpalloc (encode_terminal_src,
diff --git a/src/termcap.c b/src/termcap.c
index d2688b3838d..1e989b6e2de 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -296,7 +296,7 @@ tputs (register const char *str, int nlines, int (*outfun) (int))
      BAUD_RATE is measured in characters per 10 seconds.
      Compute PADFACTOR = 100000 * (how many padding bytes are needed).  */
   intmax_t padfactor;
-  if (INT_MULTIPLY_WRAPV (padcount, baud_rate, &padfactor))
+  if (ckd_mul (&padfactor, padcount, baud_rate))
     padfactor = baud_rate < 0 ? INTMAX_MIN : INTMAX_MAX;
 
   for (; 50000 <= padfactor; padfactor -= 100000)
diff --git a/src/textconv.c b/src/textconv.c
index d5db6d11717..7ed8ede3544 100644
--- a/src/textconv.c
+++ b/src/textconv.c
@@ -125,7 +125,7 @@ textconv_query (struct frame *f, struct textconv_callback_struct *query)
      overflows, move back to point or to the extremes of the
      accessible region.  */
 
-  if (INT_ADD_WRAPV (pos, query->position, &pos))
+  if (ckd_add (&pos, pos, query->position))
     pos = PT;
 
   if (pos < BEGV)
@@ -145,7 +145,7 @@ textconv_query (struct frame *f, struct textconv_callback_struct *query)
     {
     case TEXTCONV_FORWARD_CHAR:
       /* Move forward by query->factor characters.  */
-      if (INT_ADD_WRAPV (pos, query->factor, &end) || end > ZV)
+      if (ckd_add (&end, pos, query->factor) || end > ZV)
 	end = ZV;
 
       end_byte = CHAR_TO_BYTE (end);
@@ -153,7 +153,7 @@ textconv_query (struct frame *f, struct textconv_callback_struct *query)
 
     case TEXTCONV_BACKWARD_CHAR:
       /* Move backward by query->factor characters.  */
-      if (INT_SUBTRACT_WRAPV (pos, query->factor, &end) || end < BEGV)
+      if (ckd_sub (&end, pos, query->factor) || end < BEGV)
 	end = BEGV;
 
       end_byte = CHAR_TO_BYTE (end);
diff --git a/src/timefns.c b/src/timefns.c
index 87971cf4563..151f5b482a3 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -514,8 +514,8 @@ timespec_ticks (struct timespec t)
   /* For speed, use intmax_t arithmetic if it will do.  */
   intmax_t accum;
   if (FASTER_TIMEFNS
-      && !INT_MULTIPLY_WRAPV (t.tv_sec, TIMESPEC_HZ, &accum)
-      && !INT_ADD_WRAPV (t.tv_nsec, accum, &accum))
+      && !ckd_mul (&accum, t.tv_sec, TIMESPEC_HZ)
+      && !ckd_add (&accum, accum, t.tv_nsec))
     return make_int (accum);
 
   /* Fall back on bignum arithmetic.  */
@@ -543,7 +543,7 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
       /* For speed, use intmax_t arithmetic if it will do.  */
       intmax_t ticks;
       if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz)
-	  && !INT_MULTIPLY_WRAPV (XFIXNUM (t.ticks), XFIXNUM (hz), &ticks))
+	  && !ckd_mul (&ticks, XFIXNUM (t.ticks), XFIXNUM (hz)))
 	return make_int (ticks / XFIXNUM (t.hz)
 			 - (ticks % XFIXNUM (t.hz) < 0));
     }
@@ -1557,12 +1557,10 @@ usage: (decode-time &optional TIME ZONE FORM)  */)
       Lisp_Object ticks;
       intmax_t n;
       if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz)
-	  && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n)
-	  && ! (INT_ADD_WRAPV
-		(n, (XFIXNUM (lt.ticks) % XFIXNUM (hz)
-		     + (XFIXNUM (lt.ticks) % XFIXNUM (hz) < 0
-			? XFIXNUM (hz) : 0)),
-		 &n)))
+	  && !ckd_mul (&n, XFIXNUM (hz), local_tm.tm_sec)
+	  && !ckd_add (&n, n, (XFIXNUM (lt.ticks) % XFIXNUM (hz)
+			       + (XFIXNUM (lt.ticks) % XFIXNUM (hz) < 0
+				  ? XFIXNUM (hz) : 0))))
 	ticks = make_int (n);
       else
 	{
@@ -1603,7 +1601,7 @@ check_tm_member (Lisp_Object obj, int offset)
       CHECK_FIXNUM (obj);
       EMACS_INT n = XFIXNUM (obj);
       int i;
-      if (INT_SUBTRACT_WRAPV (n, offset, &i))
+      if (ckd_sub (&i, n, offset))
 	time_overflow ();
       return i;
     }
diff --git a/src/tparam.c b/src/tparam.c
index 1a5eab37452..a0d2ee74d99 100644
--- a/src/tparam.c
+++ b/src/tparam.c
@@ -173,8 +173,7 @@ tparam1 (const char *string, char *outstring, int len,
 			doup++, append_len_incr = strlen (up);
 		      else
 			doleft++, append_len_incr = strlen (left);
-		      if (INT_ADD_WRAPV (append_len_incr,
-					 append_len, &append_len))
+		      if (ckd_add (&append_len, append_len, append_len_incr))
 			memory_full (SIZE_MAX);
 		    }
 		}
diff --git a/src/w32term.c b/src/w32term.c
index 2899e82b295..57dc6b465e4 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -7378,7 +7378,7 @@ w32_initialize_display_info (Lisp_Object display_name)
     {
       static char const at[] = " at ";
       ptrdiff_t nbytes = sizeof (title) + sizeof (at);
-      if (INT_ADD_WRAPV (nbytes, SCHARS (Vsystem_name), &nbytes))
+      if (ckd_add (&nbytes, nbytes, SCHARS (Vsystem_name)))
 	memory_full (SIZE_MAX);
       dpyinfo->w32_id_name = xmalloc (nbytes);
       sprintf (dpyinfo->w32_id_name, "%s%s%s", title, at, SDATA (Vsystem_name));
diff --git a/src/xdisp.c b/src/xdisp.c
index 982e1b3c103..e31533b3680 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -602,8 +602,8 @@ fill_column_indicator_column (struct it *it, int char_width)
       if (RANGED_FIXNUMP (0, col, INT_MAX))
 	{
           int icol = XFIXNUM (col);
-	  if (!INT_MULTIPLY_WRAPV (char_width, icol, &icol)
-	      && !INT_ADD_WRAPV (it->lnum_pixel_width, icol, &icol))
+	  if (!ckd_mul (&icol, icol, char_width)
+	      && !ckd_add (&icol, icol, it->lnum_pixel_width))
 	    return icol;
 	}
     }
@@ -28216,9 +28216,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 	    ptrdiff_t position;
 	    ptrdiff_t distance
 	      = (line_number_display_limit_width < 0 ? 0
-		 : INT_MULTIPLY_WRAPV (line_number_display_limit_width,
-				       height * 2 + 30,
-				       &distance)
+		 : ckd_mul (&distance, line_number_display_limit_width,
+			    height * 2 + 30)
 		 ? PTRDIFF_MAX : distance);
 
 	    if (startpos - distance > limit)
diff --git a/src/xselect.c b/src/xselect.c
index 0586e46870b..40be6d4c00c 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -744,13 +744,13 @@ selection_data_size (struct selection_data *data)
       return (size_t) data->size;
 
     case 16:
-      if (INT_MULTIPLY_WRAPV (data->size, 2, &scratch))
+      if (ckd_mul (&scratch, data->size, 2))
 	return SIZE_MAX;
 
       return scratch;
 
     case 32:
-      if (INT_MULTIPLY_WRAPV (data->size, 4, &scratch))
+      if (ckd_mul (&scratch, data->size, 4))
 	return SIZE_MAX;
 
       return scratch;
@@ -3027,7 +3027,7 @@ x_property_data_to_lisp (struct frame *f, const unsigned char *data,
 {
   ptrdiff_t format_bytes = format >> 3;
   ptrdiff_t data_bytes;
-  if (INT_MULTIPLY_WRAPV (size, format_bytes, &data_bytes))
+  if (ckd_mul (&data_bytes, size, format_bytes))
     memory_full (SIZE_MAX);
   return selection_data_to_lisp_data (FRAME_DISPLAY_INFO (f), data,
 				      data_bytes, type, format);
diff --git a/src/xsmfns.c b/src/xsmfns.c
index 799c9fd1053..3cf5165242e 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -223,7 +223,7 @@ smc_save_yourself_CB (SmcConn smcConn,
   props[props_idx]->name = xstrdup (SmRestartCommand);
   props[props_idx]->type = xstrdup (SmLISTofARRAY8);
   /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */
-  if (INT_ADD_WRAPV (initial_argc, 3, &i))
+  if (ckd_add (&i, initial_argc, 3))
     memory_full (SIZE_MAX);
   props[props_idx]->num_vals = i;
   vp = xnmalloc (i, sizeof *vp);
diff --git a/src/xterm.c b/src/xterm.c
index 0899fcdc2d6..15bd9f98d17 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -2322,13 +2322,10 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo,
 	  target_count = header.target_list_count;
 	  rc = false;
 
-	  if (INT_ADD_WRAPV (header.target_list_count, 1,
-			     &header.target_list_count)
-	      || INT_MULTIPLY_WRAPV (ntargets, 4, &size)
-	      || INT_ADD_WRAPV (header.total_data_size, size,
-				&header.total_data_size)
-	      || INT_ADD_WRAPV (header.total_data_size, 2,
-				&header.total_data_size))
+	  if (ckd_add (&header.target_list_count, header.target_list_count, 1)
+	      || ckd_mul (&size, ntargets, 4)
+	      || ckd_add (&header.total_data_size, header.total_data_size, size)
+	      || ckd_add (&header.total_data_size, header.total_data_size, 2))
 	    {
 	      /* Overflow, remove every entry from the targets table
 		 and add one for our current targets list.  This
@@ -6949,8 +6946,7 @@ x_sync_get_monotonic_time (struct x_display_info *dpyinfo,
     return 0;
 
   uint_fast64_t t;
-  return (INT_SUBTRACT_WRAPV (timestamp, dpyinfo->server_time_offset, &t)
-	  ? 0 : t);
+  return ckd_sub (&t, timestamp, dpyinfo->server_time_offset) ? 0 : t;
 }
 
 # ifndef CLOCK_MONOTONIC
@@ -6968,8 +6964,8 @@ x_sync_current_monotonic_time (void)
   return (((clock_gettime (CLOCK_MONOTONIC, &time) != 0
 	    && (CLOCK_MONOTONIC == CLOCK_REALTIME
 		|| clock_gettime (CLOCK_REALTIME, &time) != 0))
-	   || INT_MULTIPLY_WRAPV (time.tv_sec, 1000000, &t)
-	   || INT_ADD_WRAPV (t, time.tv_nsec / 1000, &t))
+	   || ckd_mul (&t, time.tv_sec, 1000000)
+	   || ckd_add (&t, t, time.tv_nsec / 1000))
 	  ? 0 : t);
 }
 
@@ -6990,8 +6986,7 @@ x_sync_note_frame_times (struct x_display_info *dpyinfo,
   time = x_sync_get_monotonic_time (dpyinfo, low | (high << 32));
 
   if (!time || !output->temp_frame_time
-      || INT_SUBTRACT_WRAPV (time, output->temp_frame_time,
-			     &output->last_frame_time))
+      || ckd_sub (&output->last_frame_time, time, output->temp_frame_time))
     output->last_frame_time = 0;
 
 #ifdef FRAME_DEBUG
@@ -7967,7 +7962,7 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
 
       dpyinfo->server_time_monotonic_p
 	= (monotonic_time != 0
-	   && !INT_SUBTRACT_WRAPV (time, monotonic_ms, &diff_ms)
+	   && !ckd_sub (&diff_ms, time, monotonic_ms)
 	   && -500 < diff_ms && diff_ms < 500);
 
       if (!dpyinfo->server_time_monotonic_p)
@@ -7976,10 +7971,9 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
 	     time to estimate the monotonic time on the X server.  */
 
 	  if (!monotonic_time
-	      || INT_MULTIPLY_WRAPV (time, 1000, &dpyinfo->server_time_offset)
-	      || INT_SUBTRACT_WRAPV (dpyinfo->server_time_offset,
-				     monotonic_time,
-				     &dpyinfo->server_time_offset))
+	      || ckd_mul (&dpyinfo->server_time_offset, time, 1000)
+	      || ckd_sub (&dpyinfo->server_time_offset,
+			  dpyinfo->server_time_offset, monotonic_time))
 	    dpyinfo->server_time_offset = 0;
 
 	  /* If the server time is reasonably close to the monotonic
@@ -7988,18 +7982,18 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
 	     actual time in ms.  */
 
 	  monotonic_ms = monotonic_ms & 0xffffffff;
-	  if (!INT_SUBTRACT_WRAPV (time, monotonic_ms, &diff_ms)
+	  if (!ckd_sub (&diff_ms, time, monotonic_ms)
 	      && -500 < diff_ms && diff_ms < 500)
 	    {
 	      /* The server timestamp overflowed.  Make the time
 		 offset exactly how much it overflowed by.  */
 
-	      if (INT_SUBTRACT_WRAPV (monotonic_time / 1000, monotonic_ms,
-				      &dpyinfo->server_time_offset)
-		  || INT_MULTIPLY_WRAPV (dpyinfo->server_time_offset,
-					 1000, &dpyinfo->server_time_offset)
-		  || INT_SUBTRACT_WRAPV (0, dpyinfo->server_time_offset,
-					 &dpyinfo->server_time_offset))
+	      if (ckd_sub (&dpyinfo->server_time_offset,
+			   monotonic_time / 1000, monotonic_ms)
+		  || ckd_mul (&dpyinfo->server_time_offset,
+			      dpyinfo->server_time_offset, 1000)
+		  || ckd_sub (&dpyinfo->server_time_offset,
+			      0, dpyinfo->server_time_offset))
 		dpyinfo->server_time_offset = 0;
 	    }
 	}
@@ -30199,7 +30193,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
     {
       static char const at[] = " at ";
       ptrdiff_t nbytes = sizeof (title) + sizeof (at);
-      if (INT_ADD_WRAPV (nbytes, SBYTES (system_name), &nbytes))
+      if (ckd_add (&nbytes, nbytes, SBYTES (system_name)))
 	memory_full (SIZE_MAX);
       dpyinfo->x_id_name = xmalloc (nbytes);
       sprintf (dpyinfo->x_id_name, "%s%s%s", title, at, SDATA (system_name));
-- 
2.39.5