Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
15 changes: 14 additions & 1 deletion 15 Doc/c-api/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 7 additions & 3 deletions 10 Include/pymacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:c:macro:`Py_UNREACHABLE` is now implemented with
``__builtin_unreachable()`` and analogs in release mode.
2 changes: 1 addition & 1 deletion 2 Modules/_tracemalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
9 changes: 5 additions & 4 deletions 9 Objects/stringlib/eq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion 2 Python/formatter_unicode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Expand Down
6 changes: 5 additions & 1 deletion 6 Python/peephole.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 4 additions & 4 deletions 8 Python/pytime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -1019,7 +1019,7 @@ _PyTime_GetPerfCounter(void)
{
_PyTime_t t;
if (_PyTime_GetPerfCounterWithInfo(&t, NULL)) {
Py_UNREACHABLE();
Py_FatalError("_PyTime_GetPerfCounterWithInfo() failed");
}
return t;
}
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.