1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-21 07:15:49 +00:00

include: Implement N2867.

This adds macros for checked addition, subtraction, and multiplication with semantics similar to the builtins gcc and clang have had for years.

Reviewed by:	kib, emaste
Differential Revision:	https://reviews.freebsd.org/D41734
This commit is contained in:
Dag-Erling Smørgrav 2023-09-07 06:14:54 +00:00
parent 12b1c1e3fb
commit e6615b1034
4 changed files with 151 additions and 1 deletions

View File

@ -30,7 +30,7 @@ INCS= a.out.h ar.h assert.h bitstring.h byteswap.h \
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 \

40
include/stdckdint.h Normal file
View File

@ -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

View File

@ -29,6 +29,7 @@ MAN= arb.3 \
snl.3 \
stats.3 \
stdarg.3 \
stdckdint.3 \
sysexits.3 \
tgmath.3 \
timeradd.3 \
@ -310,6 +311,9 @@ MLINKS+= stdarg.3 va_arg.3 \
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 \

106
share/man/man3/stdckdint.3 Normal file
View File

@ -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 .