Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
warsaw committed Sep 15, 2017
1 parent d384a81 commit b2e5794
Show file tree
Hide file tree
Showing 22 changed files with 128 additions and 111 deletions.
62 changes: 57 additions & 5 deletions Doc/c-api/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Include/pymacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,6 @@
#define Py_UNUSED(name) _unused_ ## name
#endif

#define Py_UNREACHABLE() abort()

#endif /* Py_PYMACRO_H */
Original file line number Diff line number Diff line change
@@ -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.
3 changes: 1 addition & 2 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
2 changes: 1 addition & 1 deletion Modules/_tracemalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
3 changes: 1 addition & 2 deletions Modules/mathmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion Objects/abstract.c
Original file line number Diff line number Diff line change
Expand Up @@ -1984,7 +1984,7 @@ _PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)
goto Done;

default:
assert(!"unknown operation");
Py_UNREACHABLE();
}
}

Expand Down
2 changes: 1 addition & 1 deletion Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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':
Expand Down
18 changes: 6 additions & 12 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

/*
Expand Down Expand Up @@ -723,8 +722,7 @@ lookdict(PyDictObject *mp, PyObject *key,
perturb >>= PERTURB_SHIFT;
i = (i*5 + perturb + 1) & mask;
}
assert(0); /* NOT REACHED */
return 0;
Py_UNREACHABLE();
}

/* Specialized version for string-only keys */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 3 additions & 4 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions Objects/stringlib/eq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Loading

0 comments on commit b2e5794

Please sign in to comment.