diff --git a/Include/internal/pycore_pymath.h b/Include/internal/pycore_pymath.h index 5c6aee2a238..5f3afe4df68 100644 --- a/Include/internal/pycore_pymath.h +++ b/Include/internal/pycore_pymath.h @@ -56,17 +56,13 @@ static inline void _Py_ADJUST_ERANGE2(double x, double y) } } -// Return whether integral type *type* is signed or not. -#define _Py_IntegralTypeSigned(type) \ - ((type)(-1) < 0) - // Return the maximum value of integral type *type*. #define _Py_IntegralTypeMax(type) \ - ((_Py_IntegralTypeSigned(type)) ? (((((type)1 << (sizeof(type)*CHAR_BIT - 2)) - 1) << 1) + 1) : ~(type)0) + (_Py_IS_TYPE_SIGNED(type) ? (((((type)1 << (sizeof(type)*CHAR_BIT - 2)) - 1) << 1) + 1) : ~(type)0) // Return the minimum value of integral type *type*. #define _Py_IntegralTypeMin(type) \ - ((_Py_IntegralTypeSigned(type)) ? -_Py_IntegralTypeMax(type) - 1 : 0) + (_Py_IS_TYPE_SIGNED(type) ? -_Py_IntegralTypeMax(type) - 1 : 0) // Check whether *v* is in the range of integral type *type*. This is most // useful if *v* is floating-point, since demoting a floating-point *v* to an diff --git a/Include/pymacro.h b/Include/pymacro.h index b959eeb3f58..0a2c342e2c8 100644 --- a/Include/pymacro.h +++ b/Include/pymacro.h @@ -150,4 +150,9 @@ // For example, "int x; _Py_RVALUE(x) = 1;" fails with a compiler error. #define _Py_RVALUE(EXPR) ((void)0, (EXPR)) +// Return non-zero if the type is signed, return zero if it's unsigned. +// Use "<= 0" rather than "< 0" to prevent the compiler warning: +// "comparison of unsigned expression in '< 0' is always false". +#define _Py_IS_TYPE_SIGNED(type) ((type)(-1) <= 0) + #endif /* Py_PYMACRO_H */ diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 9132f13e816..44e60d7c149 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -612,8 +612,10 @@ child_exec(char *const exec_array[], #endif #ifdef HAVE_SETPGID - if (pgid_to_set >= 0) + static_assert(_Py_IS_TYPE_SIGNED(pid_t), "pid_t is unsigned"); + if (pgid_to_set >= 0) { POSIX_CALL(setpgid(0, pgid_to_set)); + } #endif #ifdef HAVE_SETGROUPS diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 37f4ded8001..ac0c96a11d3 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5858,6 +5858,20 @@ settrace_to_record(PyObject *self, PyObject *list) Py_RETURN_NONE; } +static PyObject * +test_macros(PyObject *self, PyObject *Py_UNUSED(args)) +{ + // Py_MIN(), Py_MAX() + assert(Py_MIN(5, 11) == 5); + assert(Py_MAX(5, 11) == 11); + + // _Py_IS_TYPE_SIGNED() + assert(_Py_IS_TYPE_SIGNED(int)); + assert(!_Py_IS_TYPE_SIGNED(unsigned int)); + + Py_RETURN_NONE; +} + static PyObject *negative_dictoffset(PyObject *, PyObject *); static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*); @@ -6149,6 +6163,7 @@ static PyMethodDef TestMethods[] = { {"get_feature_macros", get_feature_macros, METH_NOARGS, NULL}, {"test_code_api", test_code_api, METH_NOARGS, NULL}, {"settrace_to_record", settrace_to_record, METH_O, NULL}, + {"test_macros", test_macros, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ };