]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38249: Expand Py_UNREACHABLE() to __builtin_unreachable() in the release mode...
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 9 Mar 2020 18:49:52 +0000 (20:49 +0200)
committerGitHub <noreply@github.com>
Mon, 9 Mar 2020 18:49:52 +0000 (20:49 +0200)
Co-authored-by: Victor Stinner <vstinner@python.org>
Doc/c-api/intro.rst
Include/pymacro.h
Misc/NEWS.d/next/C API/2020-03-09-20-27-19.bpo-38249.IxYbQy.rst [new file with mode: 0644]
Modules/_tracemalloc.c
Objects/stringlib/eq.h
Python/formatter_unicode.c
Python/peephole.c
Python/pytime.c

index d08d4f97a308e72d1601e8bc173d8a72e36ec15a..5a99631bbbdcfb1f445844a7701df1f360056998 100644 (file)
@@ -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)
index c080fb164e353a5291ba71941648156aada6558f..856cae774d61c765ebeb0d75f23cd3deb31b6bc6 100644 (file)
 #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" \
         "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
 
diff --git a/Misc/NEWS.d/next/C API/2020-03-09-20-27-19.bpo-38249.IxYbQy.rst b/Misc/NEWS.d/next/C API/2020-03-09-20-27-19.bpo-38249.IxYbQy.rst
new file mode 100644 (file)
index 0000000..e209c8b
--- /dev/null
@@ -0,0 +1,2 @@
+:c:macro:`Py_UNREACHABLE` is now implemented with
+``__builtin_unreachable()`` and analogs in release mode.
index ddf6ef4e11dd4fd3dad5e82856bc1c98174e3ba1..74c09e4d48535cff74a9cdd3805c5999144f95a6 100644 (file)
@@ -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();
     }
index ff22f913712e8dfa88a90ad4f7b02e1b3be2975a..9c1058b86cbedbd5aa43c689eb18cb413f993ee6 100644 (file)
@@ -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)
index 55ed59d36898d16b4f2df5198b00d1a4f2d3a3f6..841b25a43fce3414af47eb98c818fc074f6827f9 100644 (file)
@@ -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();
         }
     }
index baa217ad02d1d294e7f908f2abc83a54ef01906c..84de1abc175476dc1bd525ff8c6180d40c0fe291 100644 (file)
@@ -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;
     }
index 9b2b74af5c04385d082270fbf1e245091be54693..6affccbeffa88a046ff14e874b999411b853efe5 100644 (file)
@@ -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;
 }