* Add Py_UNREACHABLE() as an alias to abort().
* Use Py_UNREACHABLE() instead of assert(0)
* Convert more unreachable code to use Py_UNREACHABLE()
* Document Py_UNREACHABLE() and a few other macros.
This commit is contained in:
Barry Warsaw 2017-09-14 18:13:16 -07:00 committed by GitHub
parent d384a81f55
commit b2e5794870
22 changed files with 128 additions and 111 deletions

View File

@ -17,11 +17,11 @@ common use. The second reason is to use Python as a component in a larger
application; this technique is generally referred to as :dfn:`embedding` Python
in an application.
Writing an extension module is a relatively well-understood process, where a
"cookbook" approach works well. There are several tools that automate the
process to some extent. While people have embedded Python in other
applications since its early existence, the process of embedding Python is less
straightforward than writing an extension.
Writing an extension module is a relatively well-understood process, where a
"cookbook" approach works well. There are several tools that automate the
process to some extent. While people have embedded Python in other
applications since its early existence, the process of embedding Python is
less straightforward than writing an extension.
Many API functions are useful independent of whether you're embedding or
extending Python; moreover, most applications that embed Python will need to
@ -30,6 +30,16 @@ familiar with writing an extension before attempting to embed Python in a real
application.
Coding standards
================
If you're writing C code for inclusion in CPython, you **must** follow the
guidelines and standards defined in :PEP:`7`. These guidelines apply
regardless of the version of Python you are contributing to. Following these
conventions is not necessary for your own third party extension modules,
unless you eventually expect to contribute them to Python.
.. _api-includes:
Include Files
@ -81,6 +91,48 @@ header files do properly declare the entry points to be ``extern "C"``, so there
is no need to do anything special to use the API from C++.
Useful macros
=============
Several useful macros are defined in the Python header files. Many are
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.
.. c:macro:: Py_ABS(x)
Return the absolute value of ``x``.
.. c:macro:: Py_MIN(x, y)
Return the minimum value between ``x`` and ``y``.
.. c:macro:: Py_MAX(x, y)
Return the maximum value between ``x`` and ``y``.
.. c:macro:: Py_STRINGIFY(x)
Convert ``x`` to a C string. E.g. ``Py_STRINGIFY(123)`` returns
``"123"``.
.. c:macro:: Py_MEMBER_SIZE(type, member)
Return the size of a structure (``type``) ``member`` in bytes.
.. c:macro:: Py_CHARMASK(c)
Argument must be a character or an integer in the range [-128, 127] or [0,
255]. This macro returns ``c`` cast to an ``unsigned char``.
.. _api-objects:
Objects, Types and Reference Counts

View File

@ -95,4 +95,6 @@
#define Py_UNUSED(name) _unused_ ## name
#endif
#define Py_UNREACHABLE() abort()
#endif /* Py_PYMACRO_H */

View File

@ -0,0 +1,3 @@
Added the ``Py_UNREACHABLE()`` macro for code paths which are never expected
to be reached. This and a few other useful macros are now documented in the
C API manual.

View File

@ -1453,8 +1453,7 @@ diff_to_bool(int diff, int op)
case Py_LT: istrue = diff < 0; break;
case Py_GT: istrue = diff > 0; break;
default:
assert(! "op unknown");
istrue = 0; /* To shut up compiler */
Py_UNREACHABLE();
}
result = istrue ? Py_True : Py_False;
Py_INCREF(result);

View File

@ -750,8 +750,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
if (entry->me_key == NULL || entry->me_key == key)
return entry;
}
assert(0); /* Never reached */
return NULL;
Py_UNREACHABLE();
}
/* Returns -1 on failure, 0 on success. */

View File

@ -726,7 +726,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. */
assert(0 && "should never happen");
Py_UNREACHABLE();
}
TABLES_UNLOCK();
}

View File

@ -105,8 +105,7 @@ sinpi(double x)
r = sin(pi*(y-2.0));
break;
default:
assert(0); /* should never get here */
r = -1.23e200; /* silence gcc warning */
Py_UNREACHABLE();
}
return copysign(1.0, x)*r;
}

View File

@ -1984,7 +1984,7 @@ _PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)
goto Done;
default:
assert(!"unknown operation");
Py_UNREACHABLE();
}
}

View File

@ -868,7 +868,7 @@ _PyBytes_FormatEx(const char *format, Py_ssize_t format_len,
switch(c)
{
default:
assert(0 && "'type' not in [diuoxX]");
Py_UNREACHABLE();
case 'd':
case 'i':
case 'u':

View File

@ -643,8 +643,7 @@ lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
assert(0); /* NOT REACHED */
return DKIX_ERROR;
Py_UNREACHABLE();
}
/*
@ -723,8 +722,7 @@ top:
perturb >>= PERTURB_SHIFT;
i = (i*5 + perturb + 1) & mask;
}
assert(0); /* NOT REACHED */
return 0;
Py_UNREACHABLE();
}
/* Specialized version for string-only keys */
@ -766,9 +764,7 @@ lookdict_unicode(PyDictObject *mp, PyObject *key,
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
assert(0); /* NOT REACHED */
return 0;
Py_UNREACHABLE();
}
/* Faster version of lookdict_unicode when it is known that no <dummy> keys
@ -810,8 +806,7 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
assert(0); /* NOT REACHED */
return 0;
Py_UNREACHABLE();
}
/* Version of lookdict for split tables.
@ -856,8 +851,7 @@ lookdict_split(PyDictObject *mp, PyObject *key,
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
assert(0); /* NOT REACHED */
return 0;
Py_UNREACHABLE();
}
int
@ -3603,7 +3597,7 @@ dictiter_reduce(dictiterobject *di)
else if (Py_TYPE(di) == &PyDictIterValue_Type)
element = dictiter_iternextvalue(&tmp);
else
assert(0);
Py_UNREACHABLE();
if (element) {
if (PyList_Append(list, element)) {
Py_DECREF(element);

View File

@ -1806,8 +1806,7 @@ long_format_binary(PyObject *aa, int base, int alternate,
bits = 1;
break;
default:
assert(0); /* shouldn't ever get here */
bits = 0; /* to silence gcc warning */
Py_UNREACHABLE();
}
/* Compute exact length 'sz' of output string. */
@ -2169,8 +2168,8 @@ PyLong_FromString(const char *str, char **pend, int base)
}
}
if (str[0] == '_') {
/* May not start with underscores. */
goto onError;
/* May not start with underscores. */
goto onError;
}
start = str;

View File

@ -10,8 +10,7 @@ unicode_eq(PyObject *aa, PyObject *bb)
PyUnicodeObject *b = (PyUnicodeObject *)bb;
if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
assert(0 && "unicode_eq ready fail");
return 0;
Py_UNREACHABLE();
}
if (PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b))

View File

@ -768,7 +768,7 @@ make_bloom_mask(int kind, void* ptr, Py_ssize_t len)
BLOOM_UPDATE(Py_UCS4, mask, ptr, len);
break;
default:
assert(0);
Py_UNREACHABLE();
}
return mask;
@ -869,8 +869,7 @@ findchar(const void *s, int kind,
else
return ucs4lib_rfind_char((Py_UCS4 *) s, size, ch);
default:
assert(0);
return -1;
Py_UNREACHABLE();
}
}
@ -1520,8 +1519,7 @@ _copy_characters(PyObject *to, Py_ssize_t to_start,
);
}
else {
assert(0);
return -1;
Py_UNREACHABLE();
}
}
else {
@ -2079,7 +2077,7 @@ PyUnicode_FromWideChar(const wchar_t *u, Py_ssize_t size)
#endif
break;
default:
assert(0 && "Impossible state");
Py_UNREACHABLE();
}
return unicode_result(unicode);
@ -2172,8 +2170,7 @@ kind_maxchar_limit(unsigned int kind)
case PyUnicode_4BYTE_KIND:
return 0x10000;
default:
assert(0 && "invalid kind");
return MAX_UNICODE;
Py_UNREACHABLE();
}
}
@ -2317,8 +2314,7 @@ _PyUnicode_FindMaxChar(PyObject *unicode, Py_ssize_t start, Py_ssize_t end)
case PyUnicode_4BYTE_KIND:
return ucs4lib_find_max_char(startptr, endptr);
default:
assert(0);
return 0;
Py_UNREACHABLE();
}
}
@ -4068,7 +4064,7 @@ PyUnicode_AsUnicodeAndSize(PyObject *unicode, Py_ssize_t *size)
*w = *four_bytes;
if (w > wchar_end) {
assert(0 && "Miscalculated string end");
Py_UNREACHABLE();
}
}
*w = 0;
@ -4120,7 +4116,7 @@ PyUnicode_AsUnicodeAndSize(PyObject *unicode, Py_ssize_t *size)
#endif
}
else {
assert(0 && "This should never happen.");
Py_UNREACHABLE();
}
}
}
@ -5134,7 +5130,7 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size)
#endif
if (ch > 0xFF) {
#if SIZEOF_WCHAR_T == 4
assert(0);
Py_UNREACHABLE();
#else
assert(ch > 0xFFFF && ch <= MAX_UNICODE);
/* compute and append the two surrogates: */
@ -5187,7 +5183,7 @@ _PyUnicode_AsUTF8String(PyObject *unicode, const char *errors)
switch (kind) {
default:
assert(0);
Py_UNREACHABLE();
case PyUnicode_1BYTE_KIND:
/* the string cannot be ASCII, or PyUnicode_UTF8() would be set */
assert(!PyUnicode_IS_ASCII(unicode));
@ -9294,7 +9290,7 @@ any_find_slice(PyObject* s1, PyObject* s2,
result = ucs4lib_find_slice(buf1, len1, buf2, len2, start, end);
break;
default:
assert(0); result = -2;
Py_UNREACHABLE();
}
}
else {
@ -9312,7 +9308,7 @@ any_find_slice(PyObject* s1, PyObject* s2,
result = ucs4lib_rfind_slice(buf1, len1, buf2, len2, start, end);
break;
default:
assert(0); result = -2;
Py_UNREACHABLE();
}
}
@ -9386,8 +9382,7 @@ _PyUnicode_InsertThousandsGrouping(
(Py_UCS4 *) thousands_sep_data, thousands_sep_len);
break;
default:
assert(0);
return -1;
Py_UNREACHABLE();
}
if (unicode != NULL && thousands_sep_kind != kind) {
if (thousands_sep_kind < kind)
@ -9465,7 +9460,7 @@ PyUnicode_Count(PyObject *str,
);
break;
default:
assert(0); result = 0;
Py_UNREACHABLE();
}
if (kind2 != kind1)
@ -9881,8 +9876,7 @@ case_operation(PyObject *self,
memcpy(outdata, tmp, sizeof(Py_UCS4) * newlength);
break;
default:
assert(0);
break;
Py_UNREACHABLE();
}
leave:
PyMem_FREE(tmp);
@ -10105,7 +10099,7 @@ _PyUnicode_JoinArray(PyObject *separator, PyObject **items, Py_ssize_t seqlen)
for (; i_ < (length); ++i_, ++to_) *to_ = (value); \
break; \
} \
default: assert(0); \
default: Py_UNREACHABLE(); \
} \
} while (0)
@ -10229,8 +10223,7 @@ PyUnicode_Splitlines(PyObject *string, int keepends)
PyUnicode_GET_LENGTH(string), keepends);
break;
default:
assert(0);
list = 0;
Py_UNREACHABLE();
}
return list;
}
@ -10275,8 +10268,7 @@ split(PyObject *self,
PyUnicode_GET_LENGTH(self), maxcount
);
default:
assert(0);
return NULL;
Py_UNREACHABLE();
}
if (PyUnicode_READY(substring) == -1)
@ -10367,8 +10359,7 @@ rsplit(PyObject *self,
PyUnicode_GET_LENGTH(self), maxcount
);
default:
assert(0);
return NULL;
Py_UNREACHABLE();
}
if (PyUnicode_READY(substring) == -1)
@ -10434,8 +10425,7 @@ anylib_find(int kind, PyObject *str1, void *buf1, Py_ssize_t len1,
case PyUnicode_4BYTE_KIND:
return ucs4lib_find(buf1, len1, buf2, len2, offset);
}
assert(0);
return -1;
Py_UNREACHABLE();
}
static Py_ssize_t
@ -10453,8 +10443,7 @@ anylib_count(int kind, PyObject *sstr, void* sbuf, Py_ssize_t slen,
case PyUnicode_4BYTE_KIND:
return ucs4lib_count(sbuf, slen, buf1, len1, maxcount);
}
assert(0);
return 0;
Py_UNREACHABLE();
}
static void
@ -10909,7 +10898,7 @@ unicode_compare(PyObject *str1, PyObject *str2)
COMPARE(Py_UCS1, Py_UCS4);
break;
default:
assert(0);
Py_UNREACHABLE();
}
break;
}
@ -10928,7 +10917,7 @@ unicode_compare(PyObject *str1, PyObject *str2)
COMPARE(Py_UCS2, Py_UCS4);
break;
default:
assert(0);
Py_UNREACHABLE();
}
break;
}
@ -10956,12 +10945,12 @@ unicode_compare(PyObject *str1, PyObject *str2)
break;
}
default:
assert(0);
Py_UNREACHABLE();
}
break;
}
default:
assert(0);
Py_UNREACHABLE();
}
if (len1 == len2)
@ -11285,8 +11274,7 @@ PyUnicode_Contains(PyObject *str, PyObject *substr)
result = ucs4lib_find(buf1, len1, buf2, len2, 0) != -1;
break;
default:
result = -1;
assert(0);
Py_UNREACHABLE();
}
if (kind2 != kind1)
@ -11511,7 +11499,7 @@ unicode_count(PyObject *self, PyObject *args)
);
break;
default:
assert(0); iresult = 0;
Py_UNREACHABLE();
}
result = PyLong_FromSsize_t(iresult);
@ -12985,8 +12973,7 @@ PyUnicode_Partition(PyObject *str_obj, PyObject *sep_obj)
out = ucs4lib_partition(str_obj, buf1, len1, sep_obj, buf2, len2);
break;
default:
assert(0);
out = 0;
Py_UNREACHABLE();
}
if (kind2 != kind1)
@ -13043,8 +13030,7 @@ PyUnicode_RPartition(PyObject *str_obj, PyObject *sep_obj)
out = ucs4lib_rpartition(str_obj, buf1, len1, sep_obj, buf2, len2);
break;
default:
assert(0);
out = 0;
Py_UNREACHABLE();
}
if (kind2 != kind1)
@ -13627,8 +13613,7 @@ _PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer,
case PyUnicode_2BYTE_KIND: maxchar = 0xffff; break;
case PyUnicode_4BYTE_KIND: maxchar = 0x10ffff; break;
default:
assert(0 && "invalid kind");
return -1;
Py_UNREACHABLE();
}
return _PyUnicodeWriter_PrepareInternal(writer, 0, maxchar);
@ -13770,7 +13755,7 @@ _PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
break;
}
default:
assert(0);
Py_UNREACHABLE();
}
writer->pos += len;
@ -14204,7 +14189,7 @@ _PyUnicode_FormatLong(PyObject *val, int alt, int prec, int type)
switch (type) {
default:
assert(!"'type' not in [diuoxX]");
Py_UNREACHABLE();
case 'd':
case 'i':
case 'u':
@ -14362,7 +14347,7 @@ mainformatlong(PyObject *v,
switch(type)
{
default:
assert(0 && "'type' not in [diuoxX]");
Py_UNREACHABLE();
case 'd':
case 'i':
case 'u':
@ -15373,8 +15358,7 @@ _Py_ReleaseInternedUnicodeStrings(void)
for (i = 0; i < n; i++) {
s = PyList_GET_ITEM(keys, i);
if (PyUnicode_READY(s) == -1) {
assert(0 && "could not ready string");
fprintf(stderr, "could not ready string\n");
Py_UNREACHABLE();
}
switch (PyUnicode_CHECK_INTERNED(s)) {
case SSTATE_NOT_INTERNED:

View File

@ -25,8 +25,7 @@ PyGrammar_FindDFA(grammar *g, int type)
if (d->d_type == type)
return d;
}
assert(0);
/* NOTREACHED */
Py_UNREACHABLE();
#endif
}

View File

@ -100,8 +100,7 @@ expr_context_name(expr_context_ty ctx)
case Param:
return "Param";
default:
assert(0);
return "(unknown)";
Py_UNREACHABLE();
}
}
@ -759,8 +758,7 @@ num_stmts(const node *n)
Py_FatalError(buf);
}
}
assert(0);
return 0;
Py_UNREACHABLE();
}
/* Transform the CST rooted at node * to the appropriate AST

View File

@ -274,7 +274,7 @@ PyEval_RestoreThread(PyThreadState *tstate)
if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) {
drop_gil(tstate);
PyThread_exit_thread();
assert(0); /* unreachable */
Py_UNREACHABLE();
}
errno = err;
}
@ -3430,7 +3430,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
/* This should never be reached. Every opcode should end with DISPATCH()
or goto error. */
assert(0);
Py_UNREACHABLE();
error:

View File

@ -1350,8 +1350,7 @@ get_const_value(expr_ty e)
case NameConstant_kind:
return e->v.NameConstant.value;
default:
assert(!is_const(e));
return NULL;
Py_UNREACHABLE();
}
}

View File

@ -351,8 +351,7 @@ calc_padding(Py_ssize_t nchars, Py_ssize_t width, Py_UCS4 align,
*n_lpadding = 0;
else {
/* We should never have an unspecified alignment. */
*n_lpadding = 0;
assert(0);
Py_UNREACHABLE();
}
*n_rpadding = *n_total - nchars - *n_lpadding;
@ -569,9 +568,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
break;
default:
/* Shouldn't get here, but treat it as '>' */
spec->n_lpadding = n_padding;
assert(0);
break;
Py_UNREACHABLE();
}
}

View File

@ -175,7 +175,7 @@ _Py_HashBytes(const void *src, Py_ssize_t len)
case 2: hash = ((hash << 5) + hash) + *p++; /* fallthrough */
case 1: hash = ((hash << 5) + hash) + *p++; break;
default:
assert(0);
Py_UNREACHABLE();
}
hash ^= len;
hash ^= (Py_uhash_t) _Py_HashSecret.djbx33a.suffix;

View File

@ -431,8 +431,8 @@ _Py_string_to_number_with_underscores(
error:
PyMem_Free(dup);
PyErr_Format(PyExc_ValueError,
"could not convert string to %s: "
"%R", what, obj);
"could not convert string to %s: "
"%R", what, obj);
return NULL;
}
@ -1061,7 +1061,7 @@ format_float_short(double d, char format_code,
something starting with a digit, an 'I', or 'N' */
strncpy(p, "ERR", 3);
/* p += 3; */
assert(0);
Py_UNREACHABLE();
}
goto exit;
}

View File

@ -630,10 +630,7 @@ _PyTime_GetSystemClock(void)
_PyTime_t t;
if (pygettimeofday(&t, NULL, 0) < 0) {
/* should not happen, _PyTime_Init() checked the clock at startup */
assert(0);
/* use a fixed value instead of a random value from the stack */
t = 0;
Py_UNREACHABLE();
}
return t;
}
@ -663,7 +660,7 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
return -1;
}
/* Hello, time traveler! */
assert(0);
Py_UNREACHABLE();
}
*tp = t * MS_TO_NS;
@ -771,10 +768,7 @@ _PyTime_GetMonotonicClock(void)
if (pymonotonic(&t, NULL, 0) < 0) {
/* should not happen, _PyTime_Init() checked that monotonic clock at
startup */
assert(0);
/* use a fixed value instead of a random value from the stack */
t = 0;
Py_UNREACHABLE();
}
return t;
}

View File

@ -39,6 +39,6 @@ write_op_arg(_Py_CODEUNIT *codestr, unsigned char opcode,
*codestr++ = PACKOPARG(opcode, oparg & 0xff);
break;
default:
assert(0);
Py_UNREACHABLE();
}
}