mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
gh-91731: Replace Py_BUILD_ASSERT() with static_assert() (#91730)
Python 3.11 now uses C11 standard which adds static_assert() to <assert.h>. * In pytime.c, replace Py_BUILD_ASSERT() with preprocessor checks on SIZEOF_TIME_T with #error. * On macOS, py_mach_timebase_info() now accepts timebase members with the same size than _PyTime_t. * py_get_monotonic_clock() now saturates GetTickCount64() to _PyTime_MAX: GetTickCount64() is unsigned, whereas _PyTime_t is signed.
This commit is contained in:
parent
ad3ca17ff5
commit
7cdaf87ec5
10 changed files with 68 additions and 38 deletions
|
@ -956,7 +956,7 @@ static wchar_t *
|
|||
_Py_ConvertWCharForm(const wchar_t *source, Py_ssize_t size,
|
||||
const char *tocode, const char *fromcode)
|
||||
{
|
||||
Py_BUILD_ASSERT(sizeof(wchar_t) == 4);
|
||||
static_assert(sizeof(wchar_t) == 4, "wchar_t must be 32-bit");
|
||||
|
||||
/* Ensure we won't overflow the size. */
|
||||
if (size > (PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t))) {
|
||||
|
|
|
@ -1507,9 +1507,11 @@ config_get_xoption_value(const PyConfig *config, wchar_t *name)
|
|||
static PyStatus
|
||||
config_init_hash_seed(PyConfig *config)
|
||||
{
|
||||
static_assert(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc),
|
||||
"_Py_HashSecret_t has wrong size");
|
||||
|
||||
const char *seed_text = config_get_env(config, "PYTHONHASHSEED");
|
||||
|
||||
Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
|
||||
/* Convert a text seed to a numeric one */
|
||||
if (seed_text && strcmp(seed_text, "random") != 0) {
|
||||
const char *endptr = seed_text;
|
||||
|
|
|
@ -162,12 +162,11 @@ time_t
|
|||
_PyLong_AsTime_t(PyObject *obj)
|
||||
{
|
||||
#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
||||
long long val;
|
||||
val = PyLong_AsLongLong(obj);
|
||||
long long val = PyLong_AsLongLong(obj);
|
||||
#elif SIZEOF_TIME_T <= SIZEOF_LONG
|
||||
long val = PyLong_AsLong(obj);
|
||||
#else
|
||||
long val;
|
||||
Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long));
|
||||
val = PyLong_AsLong(obj);
|
||||
# error "unsupported time_t size"
|
||||
#endif
|
||||
if (val == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
|
@ -184,9 +183,10 @@ _PyLong_FromTime_t(time_t t)
|
|||
{
|
||||
#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
||||
return PyLong_FromLongLong((long long)t);
|
||||
#else
|
||||
Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long));
|
||||
#elif SIZEOF_TIME_T <= SIZEOF_LONG
|
||||
return PyLong_FromLong((long)t);
|
||||
#else
|
||||
# error "unsupported time_t size"
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -386,10 +386,10 @@ _PyTime_t
|
|||
_PyTime_FromSeconds(int seconds)
|
||||
{
|
||||
/* ensure that integer overflow cannot happen, int type should have 32
|
||||
bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
|
||||
bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_NS takes 30
|
||||
bits). */
|
||||
Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
|
||||
Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS);
|
||||
static_assert(INT_MAX <= _PyTime_MAX / SEC_TO_NS, "_PyTime_t overflow");
|
||||
static_assert(INT_MIN >= _PyTime_MIN / SEC_TO_NS, "_PyTime_t underflow");
|
||||
|
||||
_PyTime_t t = (_PyTime_t)seconds;
|
||||
assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
|
||||
|
@ -416,7 +416,8 @@ _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
|
|||
return -1;
|
||||
}
|
||||
|
||||
Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t));
|
||||
static_assert(sizeof(long long) == sizeof(_PyTime_t),
|
||||
"_PyTime_t is not long long");
|
||||
long long nsec = PyLong_AsLongLong(obj);
|
||||
if (nsec == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
|
@ -437,7 +438,8 @@ pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise_exc)
|
|||
{
|
||||
_PyTime_t t, tv_nsec;
|
||||
|
||||
Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
|
||||
static_assert(sizeof(ts->tv_sec) <= sizeof(_PyTime_t),
|
||||
"timespec.tv_sec is larger than _PyTime_t");
|
||||
t = (_PyTime_t)ts->tv_sec;
|
||||
|
||||
int res1 = pytime_mul(&t, SEC_TO_NS);
|
||||
|
@ -466,7 +468,8 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts)
|
|||
static int
|
||||
pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise_exc)
|
||||
{
|
||||
Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t));
|
||||
static_assert(sizeof(tv->tv_sec) <= sizeof(_PyTime_t),
|
||||
"timeval.tv_sec is larger than _PyTime_t");
|
||||
_PyTime_t t = (_PyTime_t)tv->tv_sec;
|
||||
|
||||
int res1 = pytime_mul(&t, SEC_TO_NS);
|
||||
|
@ -537,7 +540,8 @@ pytime_from_object(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round,
|
|||
return -1;
|
||||
}
|
||||
|
||||
Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
|
||||
static_assert(sizeof(long long) <= sizeof(_PyTime_t),
|
||||
"_PyTime_t is smaller than long long");
|
||||
_PyTime_t ns = (_PyTime_t)sec;
|
||||
if (pytime_mul(&ns, unit_to_ns) < 0) {
|
||||
pytime_overflow();
|
||||
|
@ -589,7 +593,8 @@ PyObject *
|
|||
_PyTime_AsNanosecondsObject(_PyTime_t t)
|
||||
{
|
||||
_PyTime_t ns = pytime_as_nanoseconds(t);
|
||||
Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t));
|
||||
static_assert(sizeof(long long) >= sizeof(_PyTime_t),
|
||||
"_PyTime_t is larger than long long");
|
||||
return PyLong_FromLongLong((long long)ns);
|
||||
}
|
||||
|
||||
|
@ -984,15 +989,17 @@ py_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise)
|
|||
_PyTime_t. In practice, timebase uses uint32_t, so casting cannot
|
||||
overflow. At the end, only make sure that the type is uint32_t
|
||||
(_PyTime_t is 64-bit long). */
|
||||
Py_BUILD_ASSERT(sizeof(timebase.numer) < sizeof(_PyTime_t));
|
||||
Py_BUILD_ASSERT(sizeof(timebase.denom) < sizeof(_PyTime_t));
|
||||
static_assert(sizeof(timebase.numer) <= sizeof(_PyTime_t),
|
||||
"timebase.numer is larger than _PyTime_t");
|
||||
static_assert(sizeof(timebase.denom) <= sizeof(_PyTime_t),
|
||||
"timebase.denom is larger than _PyTime_t");
|
||||
|
||||
/* Make sure that (ticks * timebase.numer) cannot overflow in
|
||||
_PyTime_MulDiv(), with ticks < timebase.denom.
|
||||
/* Make sure that _PyTime_MulDiv(ticks, timebase_numer, timebase_denom)
|
||||
cannot overflow.
|
||||
|
||||
Known time bases:
|
||||
|
||||
* always (1, 1) on Intel
|
||||
* (1, 1) on Intel
|
||||
* (1000000000, 33333335) or (1000000000, 25000000) on PowerPC
|
||||
|
||||
None of these time bases can overflow with 64-bit _PyTime_t, but
|
||||
|
@ -1019,8 +1026,17 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
|
|||
|
||||
#if defined(MS_WINDOWS)
|
||||
ULONGLONG ticks = GetTickCount64();
|
||||
Py_BUILD_ASSERT(sizeof(ticks) <= sizeof(_PyTime_t));
|
||||
_PyTime_t t = (_PyTime_t)ticks;
|
||||
static_assert(sizeof(ticks) <= sizeof(_PyTime_t),
|
||||
"ULONGLONG is larger than _PyTime_t");
|
||||
_PyTime_t t;
|
||||
if (ticks <= (ULONGLONG)_PyTime_MAX) {
|
||||
t = (_PyTime_t)ticks;
|
||||
}
|
||||
else {
|
||||
// GetTickCount64() maximum is larger than _PyTime_t maximum:
|
||||
// ULONGLONG is unsigned, whereas _PyTime_t is signed.
|
||||
t = _PyTime_MAX;
|
||||
}
|
||||
|
||||
int res = pytime_mul(&t, MS_TO_NS);
|
||||
*tp = t;
|
||||
|
@ -1211,7 +1227,8 @@ py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
|
|||
/* Make sure that casting LONGLONG to _PyTime_t cannot overflow,
|
||||
both types are signed */
|
||||
_PyTime_t ticks;
|
||||
Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks));
|
||||
static_assert(sizeof(ticksll) <= sizeof(ticks),
|
||||
"LONGLONG is larger than _PyTime_t");
|
||||
ticks = (_PyTime_t)ticksll;
|
||||
|
||||
_PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue