Bug 84531 - c/c++: bogus warning for functions with different argument lengths but compatible arguments
Summary: c/c++: bogus warning for functions with different argument lengths but compat...
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2018-02-23 16:11 UTC by Siddhesh Poyarekar
Modified: 2018-02-26 06:56 UTC (History)
0 users

See Also:
Known to work:
Known to fail:
Last reconfirmed:


Note You need to log in before you can comment on or make changes to this bug.
Description Siddhesh Poyarekar 2018-02-23 16:11:16 UTC
gcc trunk throws a bogus warning about incompatible function cast when the cast target and the function have different argument lengths but the same arguments for the common subset.  An example of this is the PyCFunction <-> PyCFunctionWithKeywords cast in python.

Patch posted along with test case:

Comment 1 Bernd Edlinger 2018-02-24 10:41:17 UTC
The suggested wild-card function type for functions taking 2 or more parameters
would be something like this:

PyObject * (*) (PyObject *, PyObject *, ...);

It is still necessary to cast it back to the correct type before calling.
Comment 2 Siddhesh Poyarekar 2018-02-25 03:38:43 UTC
There's also a PyCFunctionWithoutArgs that takes just one parameter so it'll have to be one arg onwards but I don't know the impact on it's API. I'm going to test that when I get back home tonight and propose a fix in Python. I kinda understand the rationale behind not diluting the warning, but I'd like to keep this open pending conclusion of the discussion on the ML.
Comment 3 Bernd Edlinger 2018-02-25 08:20:57 UTC
Actually the warning on PyCFunctionWithoutArgs
is _not_ a false positive:

I am looking at Python-3.6.1 right now.
What I see is that functions with no arguments
have the signature "PyObject * (*)(PyObject *)"
but on the call side the Call passes two arguments
see Python-3.6.1/Objects/methodobject.c:

        case METH_NOARGS:
            size = PyTuple_GET_SIZE(args);
            if (size != 0) {
                    "%.200s() takes no arguments (%zd given)",
                    f->m_ml->ml_name, size);
                return NULL;

            res = (*meth)(self, NULL);
Comment 4 Bernd Edlinger 2018-02-25 11:34:48 UTC
Also these look like more like invalid casts than bogus warnings:

../Python-3.6.1/Objects/frameobject.c:586:5: Warnung: cast between incompatible function types from »void (*)(PyFrameObject *)« {alias »void (*)(struct _fra
me *)«} to »int (*)(PyObject *)« {alias »int (*)(struct _object *)«} [-Wcast-function-type]
     (inquiry)frame_tp_clear,                    /* tp_clear */
../Python-3.6.1/Objects/funcobject.c:408:18: Warnung: cast between incompatible function types from »PyObject * (*)(PyFunctionObject *)« {alias »struct _obj
ect * (*)(struct <anonym> *)«} to »PyObject * (*)(PyObject *, void *)« {alias »struct _object * (*)(struct _object *, void *)«} [-Wcast-function-type]
     {"__code__", (getter)func_get_code, (setter)func_set_code},
../Python-3.6.1/Objects/funcobject.c:408:41: Warnung: cast between incompatible function types from »int (*)(PyFunctionObject *, PyObject *)« {alias »int (*
)(struct <anonym> *, struct _object *)«} to »int (*)(PyObject *, PyObject *, void *)« {alias »int (*)(struct _object *, struct _object *, void *)«} [-Wcast-
     {"__code__", (getter)func_get_code, (setter)func_set_code},

And unfortunately the last two would be suppressed by the proposed patch.
Comment 5 Siddhesh Poyarekar 2018-02-26 06:56:43 UTC
Yeah that doesn't look good.  I had not done a cpython build; I had started with a gem5 build (which builds python modules) and only superficially looked at cpython.

I thought about this over the weekend and agree that silencing the warning will only hold us back indefinitely.  I'll look at the cpython build a bit closer and try to fix it there when I have time for it.  Thanks for looking into this.