Page MenuHomeFreeBSD

D41734.diff
No OneTemporary

D41734.diff

diff --git a/include/Makefile b/include/Makefile
--- a/include/Makefile
+++ b/include/Makefile
@@ -30,7 +30,7 @@
pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h \
res_update.h resolv.h runetype.h sched.h \
search.h semaphore.h setjmp.h \
- signal.h spawn.h stab.h stdalign.h stdbool.h stddef.h \
+ signal.h spawn.h stab.h stdalign.h stdbool.h stdckdint.h stddef.h \
stdnoreturn.h stdio.h stdlib.h string.h stringlist.h \
strings.h sysexits.h tar.h termios.h tgmath.h \
time.h timeconv.h timers.h ttyent.h \
diff --git a/include/stdckdint.h b/include/stdckdint.h
new file mode 100644
--- /dev/null
+++ b/include/stdckdint.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2023 Dag-Erling Smørgrav
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __STDC_VERSION_STDCKDINT_H__
+#define __STDC_VERSION_STDCKDINT_H__ 202311L
+
+#include <sys/cdefs.h>
+
+#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 2023
+
+#if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_add_overflow)
+#define ckd_add(result, a, b) \
+ (_Bool)__builtin_add_overflow((a), (b), (result))
+#else
+#define ckd_add(result, a, b) \
+ _Static_assert(0, "checked addition not supported")
+#endif
+
+#if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_sub_overflow)
+#define ckd_sub(result, a, b) \
+ (_Bool)__builtin_sub_overflow((a), (b), (result))
+#else
+#define ckd_sub(result, a, b) \
+ _Static_assert(0, "checked subtraction not supported")
+#endif
+
+#if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_mul_overflow)
+#define ckd_mul(result, a, b) \
+ (_Bool)__builtin_mul_overflow((a), (b), (result))
+#else
+#define ckd_mul(result, a, b) \
+ _Static_assert(0, "checked multiplication not supported")
+#endif
+
+#endif
+
+#endif
diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile
--- a/share/man/man3/Makefile
+++ b/share/man/man3/Makefile
@@ -29,6 +29,7 @@
snl.3 \
stats.3 \
stdarg.3 \
+ stdckdint.3 \
sysexits.3 \
tgmath.3 \
timeradd.3 \
@@ -310,6 +311,9 @@
stdarg.3 va_end.3 \
stdarg.3 varargs.3 \
stdarg.3 va_start.3
+MLINKS+= stdckdint.3 ckd_add.3 \
+ stdckdint.3 ckd_sub.3 \
+ stdckdint.3 ckd_mul.3
MLINKS+= timeradd.3 timerclear.3 \
timeradd.3 timercmp.3 \
timeradd.3 timerisset.3 \
diff --git a/share/man/man3/stdckdint.3 b/share/man/man3/stdckdint.3
new file mode 100644
--- /dev/null
+++ b/share/man/man3/stdckdint.3
@@ -0,0 +1,106 @@
+.\"-
+.\" Copyright (c) 2023 Dag-Erling Smørgrav
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.Dd September 5, 2023
+.Dt STDCKDINT 3
+.Os
+.Sh NAME
+.Nm stdckdint
+.Nd checked integer arithmetic
+.Sh SYNOPSIS
+.In stdckdint.h
+.Ft bool
+.Fn ckd_add "type1 *result" "type2 a" "type3 b"
+.Ft bool
+.Fn ckd_sub "type1 *result" "type2 a" "type3 b"
+.Ft bool
+.Fn ckd_mul "type1 *result" "type2 a" "type3 b"
+.Sh DESCRIPTION
+The function-like macros
+.Nm ckd_add ,
+.Nm ckd_sub ,
+and
+.Nm ckd_mul
+perform checked integer addition, subtraction, and multiplication,
+respectively.
+If the result of adding, subtracting, or multiplying
+.Fa a
+and
+.Fa b
+as if their respective types had infinite range fits in
+.Ft type1 ,
+it is stored in the location pointed to by
+.Fa result
+and the macro evaluates to
+.Dv false .
+Otherwise, the macro evaluates to
+.Dv true
+and the contents of the location pointed to by
+.Fa result
+is the result of the operation wrapped to the range of
+.Ft type1 .
+.Sh RETURN VALUES
+The
+.Nm ckd_add ,
+.Nm ckd_sub ,
+and
+.Nm ckd_mul
+macros evaluate to
+.Dv true
+if the requested operation overflowed the result type and
+.Dv false
+otherwise.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+#include <assert.h>
+#include <limits.h>
+#include <stdckdint.h>
+
+int main(void)
+{
+ int result;
+
+ assert(!ckd_add(&result, INT_MAX, 0));
+ assert(result == INT_MAX);
+ assert(ckd_add(&result, INT_MAX, 1));
+ assert(result == INT_MIN);
+
+ assert(!ckd_sub(&result, INT_MIN, 0));
+ assert(result == INT_MIN);
+ assert(ckd_sub(&result, INT_MIN, 1));
+ assert(result == INT_MAX);
+
+ assert(!ckd_mul(&result, INT_MAX / 2, 2));
+ assert(result == INT_MAX - 1);
+ assert(ckd_mul(&result, INT_MAX / 2 + 1, 2));
+ assert(result == INT_MIN);
+
+ return 0;
+}
+.Ed
+.\" .Sh STANDARDS
+.\" The
+.\" .Nm ckd_add ,
+.\" .Nm ckd_sub ,
+.\" and
+.\" .Nm ckd_mul
+.\" macros conform to
+.\" .St -isoC-23 .
+.Sh HISTORY
+The
+.Nm ckd_add ,
+.Nm ckd_sub ,
+and
+.Nm ckd_mul
+macros were first introduced in
+.Fx 14.0 .
+.Sh AUTHORS
+The
+.Nm ckd_add ,
+.Nm ckd_sub ,
+and
+.Nm ckd_mul
+macros and this manual page were written by
+.An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org .

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 9, 9:49 PM (19 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14566229
Default Alt Text
D41734.diff (4 KB)

Event Timeline