From d76b59e187391ab5bad1945bae63b94e2b220cab Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 19 Sep 2019 11:09:59 +0200 Subject: [PATCH 1/3] bpo-38205: Convert Py_UNREACHABLE() macro to a function --- Doc/c-api/intro.rst | 9 ------ Doc/c-api/sys.rst | 14 ++++++++++ Include/pyerrors.h | 2 ++ Include/pymacro.h | 28 ------------------- .../2019-09-19-11-19-26.bpo-38205.GT40vF.rst | 1 + Python/bltinmodule.c | 1 + Python/errors.c | 13 +++++++++ 7 files changed, 31 insertions(+), 37 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2019-09-19-11-19-26.bpo-38205.GT40vF.rst diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index 80eebd89ad3f251..1cf9c7dd49fe9af 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -105,15 +105,6 @@ defined closer to where they are useful (e.g. :c:macro:`Py_RETURN_NONE`). Others of a more general utility are defined here. This is not necessarily a complete listing. -.. c:macro:: Py_UNREACHABLE() - - Use this when you have a code path that you do not expect to be reached. - For example, in the ``default:`` clause in a ``switch`` statement for which - all possible values are covered in ``case`` statements. Use this in places - where you might be tempted to put an ``assert(0)`` or ``abort()`` call. - - .. versionadded:: 3.7 - .. c:macro:: Py_ABS(x) Return the absolute value of ``x``. diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst index 838a97cacfdf10b..c29e489bbb0a3d9 100644 --- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -380,3 +380,17 @@ Process Control function registered last is called first. Each cleanup function will be called at most once. Since Python's internal finalization will have completed before the cleanup function, no Python APIs should be called by *func*. + +.. c:function:: void Py_UNREACHABLE(void) + + Use this when you have a code path that you do not expect to be reached. + For example, in the ``default:`` clause in a ``switch`` statement for which + all possible values are covered in ``case`` statements. Use this in places + where you might be tempted to put an ``assert(0)`` or ``abort()`` call. + + Call :c:func:`Py_FatalError` which dumps the Python traceback where the + bug occurs. + + In Python 3.8 and older, ``Py_UNREACHABLE()`` was a macro. + + .. versionadded:: 3.9 diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 5125a51ec1aa17e..e9a5d9edb14b8c4 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -323,6 +323,8 @@ PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const char *format, ...) PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) Py_GCC_ATTRIBUTE((format(printf, 3, 0))); +PyAPI_FUNC(void) _Py_NO_RETURN Py_UNREACHABLE(void); + #ifndef Py_LIMITED_API # define Py_CPYTHON_ERRORS_H # include "cpython/pyerrors.h" diff --git a/Include/pymacro.h b/Include/pymacro.h index ae09063e10d8723..d17d313e7677b5d 100644 --- a/Include/pymacro.h +++ b/Include/pymacro.h @@ -100,32 +100,4 @@ # define Py_UNUSED(name) _unused_ ## name #endif -#if defined(RANDALL_WAS_HERE) -#define Py_UNREACHABLE() do { \ - fputs( \ - "ERROR:\n\n" \ - "If you're seeing this, the code is in what I thought was\n" \ - "an unreachable state.\n\n" \ - "I could give you advice for what to do, but honestly, why\n" \ - "should you trust me? I clearly screwed this up. I'm writing\n" \ - "a message that should never appear, yet I know it will\n" \ - "probably appear someday.\n\n" \ - "On a deep level, I know I'm not up to this task.\n" \ - "I'm so sorry.\n\n" \ - "https://xkcd.com/2200\n", stderr); \ - abort(); \ - } while(0) -#elif defined(Py_DEBUG) -#define Py_UNREACHABLE() do { \ - fputs( \ - "ERROR:\n\n" \ - "We've reached an unreachable state. Anything is possible.\n" \ - "The limits were in our heads all along. Follow your dreams.\n\n" \ - "https://xkcd.com/2200\n", stderr); \ - abort(); \ - } while(0) -#else -#define Py_UNREACHABLE() abort() -#endif - #endif /* Py_PYMACRO_H */ diff --git a/Misc/NEWS.d/next/C API/2019-09-19-11-19-26.bpo-38205.GT40vF.rst b/Misc/NEWS.d/next/C API/2019-09-19-11-19-26.bpo-38205.GT40vF.rst new file mode 100644 index 000000000000000..ea3859833abc6af --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-09-19-11-19-26.bpo-38205.GT40vF.rst @@ -0,0 +1 @@ +Convert :c:func:`Py_UNREACHABLE` macro to a function. diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index a40eb421f5de6b6..accd08c842fbd9a 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1552,6 +1552,7 @@ builtin_len(PyObject *module, PyObject *obj) assert(PyErr_Occurred()); return NULL; } + return PyLong_FromSsize_t(res); } diff --git a/Python/errors.c b/Python/errors.c index b935341636f7878..2803908ddb444bf 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1603,6 +1603,19 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno) return err_programtext(tstate, fp, lineno); } +void _Py_NO_RETURN +Py_UNREACHABLE(void) +{ +#ifdef Py_DEBUG + Py_FatalError( + "We've reached an unreachable state. Anything is possible.\n" + "The limits were in our heads all along. Follow your dreams.\n" + "https://xkcd.com/2200"); +#else + Py_FatalError("Python internals reached an unreachable code path"); +#endif +} + #ifdef __cplusplus } #endif From e58f3b483e37c3d3bcca759902e51568199bf4ed Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 19 Sep 2019 11:29:45 +0200 Subject: [PATCH 2/3] revert unrelated change --- Python/bltinmodule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index accd08c842fbd9a..a40eb421f5de6b6 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1552,7 +1552,6 @@ builtin_len(PyObject *module, PyObject *obj) assert(PyErr_Occurred()); return NULL; } - return PyLong_FromSsize_t(res); } From 72ff132e41fb8acbc51f8bb7ea3952b3e4248820 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 19 Sep 2019 16:27:45 +0200 Subject: [PATCH 3/3] Change error message --- Python/errors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/errors.c b/Python/errors.c index 2803908ddb444bf..414446022213d56 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1612,7 +1612,7 @@ Py_UNREACHABLE(void) "The limits were in our heads all along. Follow your dreams.\n" "https://xkcd.com/2200"); #else - Py_FatalError("Python internals reached an unreachable code path"); + Py_FatalError("Unreachable C code path reached"); #endif }