* 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.
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
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
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
#define Py_UNUSED(name) _unused_ ## name
#endif
+#define Py_UNREACHABLE() abort()
+
#endif /* Py_PYMACRO_H */
--- /dev/null
+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.
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);
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. */
The GIL and the table lock ensures that only one thread is
allocating memory. */
- assert(0 && "should never happen");
+ Py_UNREACHABLE();
}
TABLES_UNLOCK();
}
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;
}
goto Done;
default:
- assert(!"unknown operation");
+ Py_UNREACHABLE();
}
}
switch(c)
{
default:
- assert(0 && "'type' not in [diuoxX]");
+ Py_UNREACHABLE();
case 'd':
case 'i':
case 'u':
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
- assert(0); /* NOT REACHED */
- return DKIX_ERROR;
+ Py_UNREACHABLE();
}
/*
perturb >>= PERTURB_SHIFT;
i = (i*5 + perturb + 1) & mask;
}
- assert(0); /* NOT REACHED */
- return 0;
+ Py_UNREACHABLE();
}
/* Specialized version for string-only keys */
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
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
- assert(0); /* NOT REACHED */
- return 0;
+ Py_UNREACHABLE();
}
/* Version of lookdict for split tables.
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
- assert(0); /* NOT REACHED */
- return 0;
+ Py_UNREACHABLE();
}
int
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);
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. */
}
}
if (str[0] == '_') {
- /* May not start with underscores. */
- goto onError;
+ /* May not start with underscores. */
+ goto onError;
}
start = str;
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))
BLOOM_UPDATE(Py_UCS4, mask, ptr, len);
break;
default:
- assert(0);
+ Py_UNREACHABLE();
}
return mask;
else
return ucs4lib_rfind_char((Py_UCS4 *) s, size, ch);
default:
- assert(0);
- return -1;
+ Py_UNREACHABLE();
}
}
);
}
else {
- assert(0);
- return -1;
+ Py_UNREACHABLE();
}
}
else {
#endif
break;
default:
- assert(0 && "Impossible state");
+ Py_UNREACHABLE();
}
return unicode_result(unicode);
case PyUnicode_4BYTE_KIND:
return 0x10000;
default:
- assert(0 && "invalid kind");
- return MAX_UNICODE;
+ Py_UNREACHABLE();
}
}
case PyUnicode_4BYTE_KIND:
return ucs4lib_find_max_char(startptr, endptr);
default:
- assert(0);
- return 0;
+ Py_UNREACHABLE();
}
}
*w = *four_bytes;
if (w > wchar_end) {
- assert(0 && "Miscalculated string end");
+ Py_UNREACHABLE();
}
}
*w = 0;
#endif
}
else {
- assert(0 && "This should never happen.");
+ Py_UNREACHABLE();
}
}
}
#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: */
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));
result = ucs4lib_find_slice(buf1, len1, buf2, len2, start, end);
break;
default:
- assert(0); result = -2;
+ Py_UNREACHABLE();
}
}
else {
result = ucs4lib_rfind_slice(buf1, len1, buf2, len2, start, end);
break;
default:
- assert(0); result = -2;
+ Py_UNREACHABLE();
}
}
(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)
);
break;
default:
- assert(0); result = 0;
+ Py_UNREACHABLE();
}
if (kind2 != kind1)
memcpy(outdata, tmp, sizeof(Py_UCS4) * newlength);
break;
default:
- assert(0);
- break;
+ Py_UNREACHABLE();
}
leave:
PyMem_FREE(tmp);
for (; i_ < (length); ++i_, ++to_) *to_ = (value); \
break; \
} \
- default: assert(0); \
+ default: Py_UNREACHABLE(); \
} \
} while (0)
PyUnicode_GET_LENGTH(string), keepends);
break;
default:
- assert(0);
- list = 0;
+ Py_UNREACHABLE();
}
return list;
}
PyUnicode_GET_LENGTH(self), maxcount
);
default:
- assert(0);
- return NULL;
+ Py_UNREACHABLE();
}
if (PyUnicode_READY(substring) == -1)
PyUnicode_GET_LENGTH(self), maxcount
);
default:
- assert(0);
- return NULL;
+ Py_UNREACHABLE();
}
if (PyUnicode_READY(substring) == -1)
case PyUnicode_4BYTE_KIND:
return ucs4lib_find(buf1, len1, buf2, len2, offset);
}
- assert(0);
- return -1;
+ Py_UNREACHABLE();
}
static Py_ssize_t
case PyUnicode_4BYTE_KIND:
return ucs4lib_count(sbuf, slen, buf1, len1, maxcount);
}
- assert(0);
- return 0;
+ Py_UNREACHABLE();
}
static void
COMPARE(Py_UCS1, Py_UCS4);
break;
default:
- assert(0);
+ Py_UNREACHABLE();
}
break;
}
COMPARE(Py_UCS2, Py_UCS4);
break;
default:
- assert(0);
+ Py_UNREACHABLE();
}
break;
}
break;
}
default:
- assert(0);
+ Py_UNREACHABLE();
}
break;
}
default:
- assert(0);
+ Py_UNREACHABLE();
}
if (len1 == len2)
result = ucs4lib_find(buf1, len1, buf2, len2, 0) != -1;
break;
default:
- result = -1;
- assert(0);
+ Py_UNREACHABLE();
}
if (kind2 != kind1)
);
break;
default:
- assert(0); iresult = 0;
+ Py_UNREACHABLE();
}
result = PyLong_FromSsize_t(iresult);
out = ucs4lib_partition(str_obj, buf1, len1, sep_obj, buf2, len2);
break;
default:
- assert(0);
- out = 0;
+ Py_UNREACHABLE();
}
if (kind2 != kind1)
out = ucs4lib_rpartition(str_obj, buf1, len1, sep_obj, buf2, len2);
break;
default:
- assert(0);
- out = 0;
+ Py_UNREACHABLE();
}
if (kind2 != kind1)
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);
break;
}
default:
- assert(0);
+ Py_UNREACHABLE();
}
writer->pos += len;
switch (type) {
default:
- assert(!"'type' not in [diuoxX]");
+ Py_UNREACHABLE();
case 'd':
case 'i':
case 'u':
switch(type)
{
default:
- assert(0 && "'type' not in [diuoxX]");
+ Py_UNREACHABLE();
case 'd':
case 'i':
case 'u':
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:
if (d->d_type == type)
return d;
}
- assert(0);
- /* NOTREACHED */
+ Py_UNREACHABLE();
#endif
}
case Param:
return "Param";
default:
- assert(0);
- return "(unknown)";
+ Py_UNREACHABLE();
}
}
Py_FatalError(buf);
}
}
- assert(0);
- return 0;
+ Py_UNREACHABLE();
}
/* Transform the CST rooted at node * to the appropriate AST
if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) {
drop_gil(tstate);
PyThread_exit_thread();
- assert(0); /* unreachable */
+ Py_UNREACHABLE();
}
errno = err;
}
/* This should never be reached. Every opcode should end with DISPATCH()
or goto error. */
- assert(0);
+ Py_UNREACHABLE();
error:
case NameConstant_kind:
return e->v.NameConstant.value;
default:
- assert(!is_const(e));
- return NULL;
+ Py_UNREACHABLE();
}
}
*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;
break;
default:
/* Shouldn't get here, but treat it as '>' */
- spec->n_lpadding = n_padding;
- assert(0);
- break;
+ Py_UNREACHABLE();
}
}
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;
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;
}
something starting with a digit, an 'I', or 'N' */
strncpy(p, "ERR", 3);
/* p += 3; */
- assert(0);
+ Py_UNREACHABLE();
}
goto exit;
}
_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;
}
return -1;
}
/* Hello, time traveler! */
- assert(0);
+ Py_UNREACHABLE();
}
*tp = t * MS_TO_NS;
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;
}
*codestr++ = PACKOPARG(opcode, oparg & 0xff);
break;
default:
- assert(0);
+ Py_UNREACHABLE();
}
}