mirror of https://github.com/python/cpython
bpo-38249: Expand Py_UNREACHABLE() to __builtin_unreachable() in the release mode. (GH-16329)
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
6d0ee60740
commit
eebaa9bfc5
|
@ -107,11 +107,24 @@ complete listing.
|
|||
|
||||
.. c:macro:: Py_UNREACHABLE()
|
||||
|
||||
Use this when you have a code path that you do not expect to be reached.
|
||||
Use this when you have a code path that cannot be reached by design.
|
||||
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.
|
||||
|
||||
In release mode, the macro helps the compiler to optimize the code, and
|
||||
avoids a warning about unreachable code. For example, the macro is
|
||||
implemented with ``__builtin_unreachable()`` on GCC in release mode.
|
||||
|
||||
A use for ``Py_UNREACHABLE()`` is following a call a function that
|
||||
never returns but that is not declared :c:macro:`_Py_NO_RETURN`.
|
||||
|
||||
If a code path is very unlikely code but can be reached under exceptional
|
||||
case, this macro must not be used. For example, under low memory condition
|
||||
or if a system call returns a value out of the expected range. In this
|
||||
case, it's better to report the error to the caller. If the error cannot
|
||||
be reported to caller, :c:func:`Py_FatalError` can be used.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
.. c:macro:: Py_ABS(x)
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(RANDALL_WAS_HERE)
|
||||
#define Py_UNREACHABLE() \
|
||||
# define Py_UNREACHABLE() \
|
||||
Py_FatalError( \
|
||||
"If you're seeing this, the code is in what I thought was\n" \
|
||||
"an unreachable state.\n\n" \
|
||||
|
@ -113,13 +113,17 @@
|
|||
"I'm so sorry.\n" \
|
||||
"https://xkcd.com/2200")
|
||||
#elif defined(Py_DEBUG)
|
||||
#define Py_UNREACHABLE() \
|
||||
# define Py_UNREACHABLE() \
|
||||
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")
|
||||
#elif defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
|
||||
# define Py_UNREACHABLE() __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
# define Py_UNREACHABLE() __assume(0)
|
||||
#else
|
||||
#define Py_UNREACHABLE() \
|
||||
# define Py_UNREACHABLE() \
|
||||
Py_FatalError("Unreachable C code path reached")
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
:c:macro:`Py_UNREACHABLE` is now implemented with
|
||||
``__builtin_unreachable()`` and analogs in release mode.
|
|
@ -712,7 +712,7 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
|
|||
|
||||
The GIL and the table lock ensures that only one thread is
|
||||
allocating memory. */
|
||||
Py_UNREACHABLE();
|
||||
Py_FatalError("tracemalloc_realloc() failed to allocate a trace");
|
||||
}
|
||||
TABLES_UNLOCK();
|
||||
}
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
Py_LOCAL_INLINE(int)
|
||||
unicode_eq(PyObject *aa, PyObject *bb)
|
||||
{
|
||||
assert(PyUnicode_Check(aa));
|
||||
assert(PyUnicode_Check(bb));
|
||||
assert(PyUnicode_IS_READY(aa));
|
||||
assert(PyUnicode_IS_READY(bb));
|
||||
|
||||
PyUnicodeObject *a = (PyUnicodeObject *)aa;
|
||||
PyUnicodeObject *b = (PyUnicodeObject *)bb;
|
||||
|
||||
if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b))
|
||||
return 0;
|
||||
if (PyUnicode_GET_LENGTH(a) == 0)
|
||||
|
|
|
@ -574,7 +574,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
|
|||
spec->n_lpadding = n_padding;
|
||||
break;
|
||||
default:
|
||||
/* Shouldn't get here, but treat it as '>' */
|
||||
/* Shouldn't get here */
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -511,8 +511,12 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
if (instrsize(j) > ilen) {
|
||||
goto exitUnchanged;
|
||||
}
|
||||
assert(ilen <= INT_MAX);
|
||||
/* If instrsize(j) < ilen, we'll emit EXTENDED_ARG 0 */
|
||||
if (ilen > 4) {
|
||||
/* Can only happen when PyCode_Optimize() is called with
|
||||
malformed bytecode. */
|
||||
goto exitUnchanged;
|
||||
}
|
||||
write_op_arg(codestr + h, opcode, j, (int)ilen);
|
||||
h += ilen;
|
||||
}
|
||||
|
|
|
@ -746,7 +746,7 @@ _PyTime_GetSystemClock(void)
|
|||
_PyTime_t t;
|
||||
if (pygettimeofday(&t, NULL, 0) < 0) {
|
||||
/* should not happen, _PyTime_Init() checked the clock at startup */
|
||||
Py_UNREACHABLE();
|
||||
Py_FatalError("pygettimeofday() failed");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
@ -776,7 +776,7 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
|||
return -1;
|
||||
}
|
||||
/* Hello, time traveler! */
|
||||
Py_UNREACHABLE();
|
||||
Py_FatalError("pymonotonic: integer overflow");
|
||||
}
|
||||
*tp = t * MS_TO_NS;
|
||||
|
||||
|
@ -918,7 +918,7 @@ _PyTime_GetMonotonicClock(void)
|
|||
if (pymonotonic(&t, NULL, 0) < 0) {
|
||||
/* should not happen, _PyTime_Init() checked that monotonic clock at
|
||||
startup */
|
||||
Py_UNREACHABLE();
|
||||
Py_FatalError("pymonotonic() failed");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
@ -1019,7 +1019,7 @@ _PyTime_GetPerfCounter(void)
|
|||
{
|
||||
_PyTime_t t;
|
||||
if (_PyTime_GetPerfCounterWithInfo(&t, NULL)) {
|
||||
Py_UNREACHABLE();
|
||||
Py_FatalError("_PyTime_GetPerfCounterWithInfo() failed");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue