C23 is going to have this header.  The industry is already moving
towards accepting it; OSes and compilers started to implement theirs.

Why not detect its presence and if any, prefer over other ways.

See also:

- https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2683.pdf
- https://reviews.freebsd.org/D41734
- https://reviews.llvm.org/D157331
- https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=8441841a1b985d68245954af1ff023db121b0635
This commit is contained in:
卜部昌平 2024-04-25 09:25:15 +02:00
Родитель 9ea77cb351
Коммит bb5a538207
5 изменённых файлов: 81 добавлений и 3 удалений

Просмотреть файл

@ -1367,6 +1367,7 @@ AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(utime.h) AC_CHECK_HEADERS(utime.h)
AC_CHECK_HEADERS(sys/epoll.h) AC_CHECK_HEADERS(sys/epoll.h)
AC_CHECK_HEADERS(sys/event.h) AC_CHECK_HEADERS(sys/event.h)
AC_CHECK_HEADERS(stdckdint.h)
AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [ AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [
AC_CHECK_HEADERS(x86intrin.h) AC_CHECK_HEADERS(x86intrin.h)

3
gc.c
Просмотреть файл

@ -224,6 +224,9 @@ size_add_overflow(size_t x, size_t y)
bool p; bool p;
#if 0 #if 0
#elif defined(ckd_add)
p = ckd_add(&z, x, y);
#elif __has_builtin(__builtin_add_overflow) #elif __has_builtin(__builtin_add_overflow)
p = __builtin_add_overflow(x, y, &z); p = __builtin_add_overflow(x, y, &z);

Просмотреть файл

@ -6,6 +6,8 @@
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#include "internal/compilers.h"
/* /*
* Hi-res monotonic clock. It is currently nsec resolution, which has over * Hi-res monotonic clock. It is currently nsec resolution, which has over
* 500 years of range (with an unsigned 64-bit integer). Developers * 500 years of range (with an unsigned 64-bit integer). Developers
@ -61,7 +63,11 @@ rb_hrtime_mul(rb_hrtime_t a, rb_hrtime_t b)
{ {
rb_hrtime_t c; rb_hrtime_t c;
#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW #ifdef ckd_mul
if (ckd_mul(&c, a, b))
return RB_HRTIME_MAX;
#elif __has_builtin(__builtin_mul_overflow)
if (__builtin_mul_overflow(a, b, &c)) if (__builtin_mul_overflow(a, b, &c))
return RB_HRTIME_MAX; return RB_HRTIME_MAX;
#else #else
@ -81,7 +87,11 @@ rb_hrtime_add(rb_hrtime_t a, rb_hrtime_t b)
{ {
rb_hrtime_t c; rb_hrtime_t c;
#ifdef HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW #ifdef ckd_add
if (ckd_add(&c, a, b))
return RB_HRTIME_MAX;
#elif __has_builtin(__builtin_add_overflow)
if (__builtin_add_overflow(a, b, &c)) if (__builtin_add_overflow(a, b, &c))
return RB_HRTIME_MAX; return RB_HRTIME_MAX;
#else #else

Просмотреть файл

@ -56,6 +56,7 @@
#include "ruby/internal/has/builtin.h" #include "ruby/internal/has/builtin.h"
#include "ruby/internal/stdalign.h" #include "ruby/internal/stdalign.h"
#include "ruby/internal/stdbool.h" #include "ruby/internal/stdbool.h"
#include "ruby/internal/stdckdint.h"
#include "ruby/internal/xmalloc.h" #include "ruby/internal/xmalloc.h"
#include "ruby/backward/2/limits.h" #include "ruby/backward/2/limits.h"
#include "ruby/backward/2/long_long.h" #include "ruby/backward/2/long_long.h"
@ -567,7 +568,10 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
{ {
struct rbimpl_size_mul_overflow_tag ret = { false, 0, }; struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
#if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow) #if defined(ckd_mul)
ret.left = ckd_mul(&ret.right, x, y);
#elif RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
ret.left = __builtin_mul_overflow(x, y, &ret.right); ret.left = __builtin_mul_overflow(x, y, &ret.right);
#elif defined(DSIZE_T) #elif defined(DSIZE_T)

Просмотреть файл

@ -0,0 +1,60 @@
#ifndef RBIMPL_STDCKDINT_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_STDCKDINT_H
/**
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief C23 shim for <stdckdint.h>
*/
#include "ruby/internal/config.h"
#include "ruby/internal/has/builtin.h"
#include "ruby/internal/stdbool.h"
#ifdef __has_include
# if __has_include(<stdckdint.h>)
# /* Conforming C23 situation; e.g. recent clang */
# define RBIMPL_HAVE_STDCKDINT_H
# endif
#endif
#ifdef HAVE_STDCKDINT_H
# /* Some OSes (most notably FreeBSD) have this file. */
# define RBIMPL_HAVE_STDCKDINT_H
#endif
#ifdef RBIMPL_HAVE_STDCKDINT_H
# /* Take that. */
# include <stdckdint.h>
#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow)
# define ckd_add(x, y, z) ((bool)__builtin_add_overflow((y), (z), (x)))
# define ckd_sub(x, y, z) ((bool)__builtin_sub_overflow((y), (z), (x)))
# define ckd_mul(x, y, z) ((bool)__builtin_mul_overflow((y), (z), (x)))
# define __STDC_VERSION_STDCKDINT_H__ 202311L
#/* elif defined(__cplusplus) */
#/* :TODO: if we assume C++11 we can use `<type_traits>` to implement them. */
#else
# /* intentionally leave them undefined */
# /* to make `#ifdef ckd_add` etc. work as intended. */
# undef ckd_add
# undef ckd_sub
# undef ckd_mul
# undef __STDC_VERSION_STDCKDINT_H__
#endif
#endif /* RBIMPL_STDCKDINT_H */