classification
Title: Consider enabling -Wmissing-prototypes
Type: enhancement Stage:
Components: Build Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: eric.snow, izbyshev, vstinner
Priority: normal Keywords:

Created on 2018-11-15 17:33 by izbyshev, last changed 2019-02-01 19:39 by eric.snow.

Messages (1)
msg329954 - (view) Author: Alexey Izbyshev (izbyshev) * (Python triager) Date: 2018-11-15 17:33
This issue is a follow-up of msg329608 of #35081.

GCC and Clang have -Wmissing-prototypes[1] diagnostic that is reported if a global function is defined without a previous declaration containing a prototype. The reasons may be the following:

1) The header where it is declared is not included before the definition.
2) There is a declaration before the definition, but it doesn't contain a prototype (e.g., "int foo()").
3) There is no separate declaration of the function in the project at all.

(1) is undesirable because the compiler can't check that signatures of the declaration and the definition match. If they don't, subtle issues may occur when such function is called using a wrong declaration.

(2) is undesirable too because there is usually no reason to use declarations without prototypes. Often "int foo()" was meant to be "int foo(void)" -- these two have different meaning in C.

(3) may mean that either the function is unused (which is probably undesirable) or it was intentionally defined without a declaration. One case when the latter makes sense is plugin-like files which define initialization functions or similar external entry points. Those may be called via pointers obtained with dlsym() or have calls generated at compile time, like Modules/config.c in CPython.

It would be good to enable -Wmissing-prototypes to catch (1) and (2) -- such issues exist as of time of this report. However, (3) is a problem because of module initialization functions which would cause unwanted diagnostics.

There is no function attribute that could be put in PyMODINIT_FUNC macro to suppress the diagnostic for a single function. The general diagnostic suppression machinery (#pragma GCC diagnostic[2]) affects everything on the following lines, and while the state can be saved and restored via "#pragma GCC diagnostic push/pop", we'd either need another macro to restore the state after the end of module initializer definitions or require that initializers always come last in the file.

A workaround is to declare the initializer inside PyMODINIT_FUNC (or a new macro). For example (omitting platform-specific parts of PyMODINIT_FUNC):

#define PyMODINIT_FUNC(name) \
    extern PyObject *name(void); \
    PyObject *name(void)

PyMODINIT_FUNC(PyInit_time)
{
  ...
}

I've also noticed that PyMODINIT_FUNC is used for functions with a different signature in Modules/_testmultiphase.c, so either another macro would be needed for that, or a general macro accepting a prototype as its variadic parameter could be added.

Even if it's deemed infeasible to enable -Wmissing-prototypes by default,
developers may find it useful to ensure that the diagnostic is reported only for files in Modules directory.

[1] https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
[2] https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
History
Date User Action Args
2019-02-01 19:39:03eric.snowsetnosy: + eric.snow
2018-11-15 17:33:43izbyshevcreate