chg: dev: Improve C23 compatibility

Use C23 stdckdint.h when available and define ckd_{mul,add,sub} shims to __builtin_{mul,add,sub}_overflow(). Require all the __builtin functions to be supported to further simplify the non-C23 implementation.  Rename the <stdbit.h>-shims in <isc/bit.h> to their C23 names.

Merge branch 'ondrej/use-stdckdint.h-if-available' into 'main'

See merge request isc-projects/bind9!10818
This commit is contained in:
Ondřej Surý 2025-08-26 16:35:53 +02:00
commit bfbc58063a
11 changed files with 63 additions and 102 deletions

View file

@ -319,7 +319,7 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
return 0;
}
if (ISC_OVERFLOW_ADD(active, klifetime, &retire)) {
if (ckd_add(&retire, active, klifetime)) {
log_key_overflow(key->key, "retire");
retire = UINT32_MAX;
}
@ -442,7 +442,7 @@ keymgr_key_update_lifetime(dns_dnsseckey_t *key, dns_kasp_t *kasp,
uint32_t a = now;
uint32_t inactive;
(void)dst_key_gettime(key->key, DST_TIME_ACTIVATE, &a);
if (ISC_OVERFLOW_ADD(a, lifetime, &inactive)) {
if (ckd_add(&inactive, a, lifetime)) {
log_key_overflow(key->key, "inactive");
inactive = UINT32_MAX;
}
@ -1986,7 +1986,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
if (lifetime > 0) {
uint32_t inactive;
if (ISC_OVERFLOW_ADD(active, lifetime, &inactive)) {
if (ckd_add(&inactive, active, lifetime)) {
log_key_overflow(new_key->key, "inactive");
inactive = UINT32_MAX;
}

View file

@ -495,10 +495,10 @@ static dns_qpcell_t
next_capacity(uint32_t prev_capacity, uint32_t size) {
/*
* Request size was floored at 2 because builtin_clz used to be 0.
* We keep this behavior because ISC_LEADING_ZEROS(0) = 32.
* We keep this behavior because stdc_leading_zeros(0) = 32.
*/
size = ISC_MAX3(size, prev_capacity, 2U);
uint32_t log2 = 32U - ISC_LEADING_ZEROS(size - 1U);
uint32_t log2 = 32U - stdc_leading_zeros(size - 1U);
return 1U << ISC_CLAMP(log2, QP_CHUNK_LOG_MIN, QP_CHUNK_LOG_MAX);
}

View file

@ -753,7 +753,7 @@ static inline dns_qpweight_t
branch_count_bitmap_before(dns_qpnode_t *n, dns_qpshift_t bit) {
uint64_t mask = (1ULL << bit) - 1 - TAG_MASK;
uint64_t bitmap = branch_index(n) & mask;
return (dns_qpweight_t)ISC_POPCOUNT(bitmap);
return (dns_qpweight_t)stdc_count_zeros(bitmap);
}
/*

View file

@ -173,7 +173,7 @@ makeslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region,
*/
nalloc = nitems;
RUNTIME_CHECK(!ISC_OVERFLOW_MUL(nalloc, sizeof(rdata[0]), &rdatasize));
RUNTIME_CHECK(!ckd_mul(&rdatasize, nalloc, sizeof(rdata[0])));
rdata = isc_mem_get(mctx, rdatasize);
/*

View file

@ -1095,7 +1095,7 @@ diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_prefix_t prefix1,
for (i = 0; bit < maxbit; i++, bit += DNS_RPZ_CIDR_WORD_BITS) {
delta = key1->w[i] ^ key2->w[i];
if (delta != 0) {
bit += ISC_LEADING_ZEROS(delta);
bit += stdc_leading_zeros(delta);
break;
}
}

View file

@ -181,7 +181,7 @@ static inline uint
value_to_key(const isc_histo_t *hg, uint64_t value) {
/* ensure that denormal numbers are all in chunk zero */
uint64_t chunked = value | CHUNKSIZE(hg);
int clz = ISC_LEADING_ZEROS(chunked);
int clz = stdc_leading_zeros(chunked);
/* actually 1 less than the exponent except for denormals */
uint exponent = 63 - hg->sigbits - clz;
/* mantissa has leading bit set except for denormals */

View file

@ -19,26 +19,16 @@
#include <isc/attributes.h>
#include <isc/util.h>
#ifndef __has_header
#define __has_header(x) 0
#endif
#if __has_header(<stdbit.h>)
#include <stdbit.h>
#define ISC_POPCOUNT(x) stdc_count_zeros(x)
#define ISC_LEADING_ZEROS(x) stdc_leading_zeros(x)
#define ISC_TRAILING_ZEROS(x) stdc_trailing_zeros(x)
#define ISC_LEADING_ONES(x) stdc_leading_ones(x)
#define ISC_TRAILING_ONES(x) stdc_trailing_ones(x)
#else /* __has_header(<stdbit.h>) */
#ifdef HAVE_BUILTIN_POPCOUNTG
#define ISC_POPCOUNT(x) __builtin_popcountg(x)
#define stdc_count_zeros(x) __builtin_popcountg(x)
#else /* HAVE_BUILTIN_POPCOUNTG */
#define ISC_POPCOUNT(x) \
#define stdc_count_zeros(x) \
_Generic((x), \
unsigned int: __builtin_popcount, \
unsigned long: __builtin_popcountl, \
@ -46,9 +36,9 @@
#endif /* HAVE_BUILTIN_POPCOUNTG */
#ifdef HAVE_BUILTIN_CLZG
#define ISC_LEADING_ZEROS(x) __builtin_clzg(x, (int)(sizeof(x) * 8))
#define stdc_leading_zeros(x) __builtin_clzg(x, (int)(sizeof(x) * 8))
#else /* HAVE_BUILTIN_CLZG */
#define ISC_LEADING_ZEROS(x) \
#define stdc_leading_zeros(x) \
(((x) == 0) ? (sizeof(x) * 8) \
: _Generic((x), \
unsigned int: __builtin_clz, \
@ -57,9 +47,9 @@
#endif /* HAVE_BUILTIN_CLZG */
#ifdef HAVE_BUILTIN_CTZG
#define ISC_TRAILING_ZEROS(x) __builtin_ctzg(x, (int)sizeof(x) * 8)
#define stdc_trailing_zeros(x) __builtin_ctzg(x, (int)sizeof(x) * 8)
#else /* HAVE_BUILTIN_CTZG */
#define ISC_TRAILING_ZEROS(x) \
#define stdc_trailing_zeros(x) \
(((x) == 0) ? (sizeof(x) * 8) \
: _Generic((x), \
unsigned int: __builtin_ctz, \
@ -67,8 +57,8 @@
unsigned long long: __builtin_ctzll)(x))
#endif /* HAVE_BUILTIN_CTZG */
#define ISC_LEADING_ONES(x) ISC_LEADING_ZEROS(~(x))
#define ISC_TRAILING_ONES(x) ISC_TRAILING_ZEROS(~(x))
#define stdc_leading_ones(x) stdc_leading_zeros(~(x))
#define stdc_trailing_ones(x) stdc_trailing_zeros(~(x))
#endif /* __has_header(<stdbit.h>) */

View file

@ -17,81 +17,45 @@
#include <isc/util.h>
/*
* It is awkward to support signed numbers as well, so keep it simple
* (with a safety check).
*/
#define ISC_OVERFLOW_IS_UNSIGNED(a) \
({ \
STATIC_ASSERT((typeof(a))-1 > 0, \
"overflow checks require unsigned types"); \
(a); \
#if HAVE_STDCKDINT_H
#include <stdckdint.h>
#else /* HAVE_STDCKDINT_H */
#define ckd_mul(cp, a, b) __builtin_mul_overflow(a, b, cp)
#define ckd_add(cp, a, b) __builtin_add_overflow(a, b, cp)
#define ckd_sub(cp, a, b) __builtin_sub_overflow(a, b, cp)
#endif /* HAVE_STDCKDINT_H */
#define ISC_CHECKED_MUL(a, b) \
({ \
typeof(a) _c; \
bool _overflow = ckd_mul(&_c, a, b); \
INSIST(!_overflow); \
_c; \
})
#define ISC_OVERFLOW_UINT_MAX(a) ISC_OVERFLOW_IS_UNSIGNED((typeof(a))-1)
#define ISC_OVERFLOW_UINT_MIN(a) ISC_OVERFLOW_IS_UNSIGNED(0)
/*
* Return true on overflow, e.g.
*
* bool overflow = ISC_OVERFLOW_MUL(count, sizeof(array[0]), &bytes);
* INSIST(!overflow);
*/
#if HAVE_BUILTIN_MUL_OVERFLOW
#define ISC_OVERFLOW_MUL(a, b, cp) __builtin_mul_overflow(a, b, cp)
#else
#define ISC_OVERFLOW_MUL(a, b, cp) \
((ISC_OVERFLOW_UINT_MAX(a) / (b) > (a)) ? (*(cp) = (a) * (b), false) \
: true)
#endif
#if HAVE_BUILTIN_ADD_OVERFLOW
#define ISC_OVERFLOW_ADD(a, b, cp) __builtin_add_overflow(a, b, cp)
#else
#define ISC_OVERFLOW_ADD(a, b, cp) \
((ISC_OVERFLOW_UINT_MAX(a) - (b) > (a)) ? (*(cp) = (a) + (b), false) \
: true)
#endif
#if HAVE_BUILTIN_SUB_OVERFLOW
#define ISC_OVERFLOW_SUB(a, b, cp) __builtin_sub_overflow(a, b, cp)
#else
#define ISC_OVERFLOW_SUB(a, b, cp) \
((ISC_OVERFLOW_UINT_MIN(a) + (b) < (a)) ? (*(cp) = (a) - (b), false) \
: true)
#endif
#define ISC_CHECKED_MUL(a, b) \
({ \
typeof(a) _c; \
bool _overflow = ISC_OVERFLOW_MUL(a, b, &_c); \
INSIST(!_overflow); \
_c; \
#define ISC_CHECKED_ADD(a, b) \
({ \
typeof(a) _c; \
bool _overflow = ckd_add(&_c, a, b); \
INSIST(!_overflow); \
_c; \
})
#define ISC_CHECKED_ADD(a, b) \
({ \
typeof(a) _c; \
bool _overflow = ISC_OVERFLOW_ADD(a, b, &_c); \
INSIST(!_overflow); \
_c; \
#define ISC_CHECKED_SUB(a, b) \
({ \
typeof(a) _c; \
bool _overflow = ckd_sub(&_c, a, b); \
INSIST(!_overflow); \
_c; \
})
#define ISC_CHECKED_SUB(a, b) \
({ \
typeof(a) _c; \
bool _overflow = ISC_OVERFLOW_SUB(a, b, cp); \
INSIST(!_overflow); \
_c; \
})
#define ISC_CHECKED_MUL_ADD(a, b, c) \
({ \
size_t _d; \
bool _overflow = ISC_OVERFLOW_MUL(a, b, &_d) || \
ISC_OVERFLOW_ADD(_d, c, &_d); \
INSIST(!_overflow); \
_d; \
#define ISC_CHECKED_MUL_ADD(a, b, c) \
({ \
size_t _d; \
bool _overflow = ckd_mul(&_d, a, b) || ckd_add(&_d, _d, c); \
INSIST(!_overflow); \
_d; \
})

View file

@ -35,6 +35,10 @@
#define __has_feature(x) 0
#endif /* if !defined(__has_feature) */
#ifndef __has_header
#define __has_header(x) 0
#endif
/***
*** General Macros.
***/

View file

@ -190,7 +190,7 @@ isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) {
REQUIRE(t->nanoseconds < NS_PER_SEC && i->nanoseconds < NS_PER_SEC);
/* Seconds */
if (ISC_OVERFLOW_ADD(t->seconds, i->seconds, &result->seconds)) {
if (ckd_add(&result->seconds, t->seconds, i->seconds)) {
return ISC_R_RANGE;
}
@ -214,7 +214,7 @@ isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
REQUIRE(t->nanoseconds < NS_PER_SEC && i->nanoseconds < NS_PER_SEC);
/* Seconds */
if (ISC_OVERFLOW_SUB(t->seconds, i->seconds, &result->seconds)) {
if (ckd_sub(&result->seconds, t->seconds, i->seconds)) {
return ISC_R_RANGE;
}

View file

@ -316,12 +316,14 @@ endif
foreach fn : [
'__builtin_add_overflow',
'__builtin_expect',
'__builtin_mul_overflow',
'__builtin_prefetch',
'__builtin_sub_overflow',
'__builtin_unreachable',
]
if cc.has_function(fn)
config.set('HAVE_@0@'.format(fn.substring(2).to_upper()), 1)
if not cc.has_function(fn)
error('@0@ support required'.format(fn))
endif
endforeach
@ -523,6 +525,7 @@ foreach h : [
'net/if6.h',
'net/route.h',
'regex.h',
'stdckdint.h',
'sys/mman.h',
'sys/select.h',
'sys/sockio.h',