mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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
	
	 Victor Stinner
						Victor Stinner