[Python-Dev] ANSI strict aliasing and Python
Martin v. Löwis
martin@v.loewis.de
18 Jul 2003 01:01:24 +0200
Neil Schemenauer <nas@python.ca> writes:
> It looks like most (maybe all) of those warnings are triggered by
> Py_True and Py_False.
While it is the case that only those places trigger the warning, the
issue goes beyond that. All usages of PyObject* in Python are
incorrect, and may result in bad code.
> Is there some other way of defining Py_True and
> Py_False so that we can avoid those errors?
We would have to give up PyObject_HEAD, and make that a structure.
> Does this mean that code like:
>
> void f (PyObject *a, PyDictObject *b)
> {
> a->ob_refcnt += 1;
> b->ob_refcnt -= 1;
> }
> [...]
> f((PyObject *)somedict, somedict);
>
> is disallowed?
Correct.
a->ob_refcnt += 1
has undefined behaviour, as 'a' does *not* point to a PyObject, but
instead points to, say, a PyDictObject, and PyObject is not a field of
PyDictObject.
As a result of that, gcc can infer that 'a' and 'b' are different
pointers, and it could implement that sequence as
tmp1 = a->ob_refcnt;
tmp2 = b->ob_refcnt;
tmp1 += 1;
tmp2 -= 1;
a->ob_refcnt = tmp1;
b->ob_refcnt = tmp2;
The compiler could not use this optimization if we had
struct _dictobject {
PyObject _o;
int ma_fill;
int ma_used;
int ma_mask;
PyDictEntry *ma_table;
PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash);
PyDictEntry ma_smalltable[PyDict_MINSIZE];
};
Then, of course, we'ld have to write
b->_o->ob_refcnt -= 1;
Regards,
Martin