forked from freebsd/freebsd-src
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
1 parent
12b1c1e
commit e6615b1
Showing
4 changed files
with
151 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 [email protected] . |