On Tue, 2012-02-28 at 14:35 -0500, David Malcolm wrote:
On Mon, 2012-02-27 at 23:30 +0000, Daniele Varrazzo wrote:
[...]
> A separate, smallish issue, yet requiring "worsening the
code" in
> order to silence a false positive is a function returning a specific
> object - XidObject - a "subclass" of PyObject.
> A caller to the function "XidObject *xid_ensure(PyObject *o)":
>
> XidObject *xid = NULL;
> PyObject *oxid; /* from the args */
> if (NULL == (xid = xid_ensure(oxid))) {
> goto exit;
> }
>
> is also flagged as returning NULL without setting an exception. The
> above statement specifically is marked as "when treating unknown
> struct XidObject * from ... as NULL
> taking True path".
>
> Fixing the warning by changing the xid_ensure signature as returning
> PyObject *, and using it as "xid = (XidObject *)xid_ensure(oxid)"
> works, but is not ideal.
>
> Is there any way to propagate the PyObject semantics to its subtypes?
I'm investigating this.
Fixed (I hope) as of ef9cdb8bb9af87e6b4b310ffd152b0dbc280ceba.
BTW, I'm seeing still tracebacks in the checker when compiling the
branch here:
https://github.com/dvarrazzo/psycopg/tree/gcc-python-plugin
where the messages are of the form:
psycopg/cursor_type.c: In function ‘psyco_curs_copy_to’:
psycopg/cursor_type.c:1447:5: error: Unhandled Python exception raised
calling 'execute' method
Traceback (most recent call last):
[...snip...]
File "/home/david/coding/gcc-python/gccutils.py", line 629, in
check_isinstance
raise TypeError('%s / %r is not an instance of %s' % (obj, obj,
types))
TypeError: None / None is not an instance of <type 'gcc.PointerType'>
I looked into these, and it looks like in each case the traceback is
preceded by a warning about the format code, like this one:
psycopg/cursor_type.c:1408:37: warning: Mismatching type in call to
PyArg_ParseTupleAndKeywords with format code "O&s|ssO" [enabled by
default]
argument 6 ("&file") had type
"struct PyObject * *"
but was expecting
"void *" (from second argument of "int (*fn) (struct PyObject *,
void *)")
for format code "O&"
The code here is:
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ssO", kwlist,
_psyco_curs_has_write_check, &file,
&table_name, &sep, &null, &columns))
{
return NULL;
}
where the "O&" format code is being used with:
_psyco_curs_has_write_check, &file
The issue is that the callback _psyco_curs_has_write_check has type:
static int _psyco_curs_has_write_check(PyObject* o, void* var);
when the second argument:
void* var
looks like it really ought to simply be:
PyObject **var
since this would save a lot of unnecessary casting within its
implementation here:
*((PyObject**)var) = o;
I think what's happening is that the checker gets sufficiently confused
by this that it can't effectively carry on, and it doesn't know enough
about "file", so that when this line happens within psyco_curs_copy_to:
Py_INCREF(file);
"file" is an UnknownValue with unknown type; it doesn't even know that
it's a pointer (hence the traceback when it tries to split the analysis
into NULL vs non-NULL versions of the value).
The easiest fix would seem to be to fix the signature of
_psyco_curs_has_write_check and the other "O&" callbacks. (I tried to
fix the checker to be more robust against this kind of error, but
unfortunately it's difficult: the code to handle format strings is
rather messy, alas).
Hope this is helpful
Dave