// gh-116869: Basic C test extension to check that the Python C API // does not emit C compiler warnings. // // Test also the internal C API if the TEST_INTERNAL_C_API macro is defined. // Always enable assertions #undef NDEBUG #ifdef TEST_INTERNAL_C_API # define Py_BUILD_CORE_MODULE 1 #endif #include "Python.h" #ifdef TEST_INTERNAL_C_API // gh-135906: Check for compiler warnings in the internal C API. // - Cython uses pycore_frame.h. // - greenlet uses pycore_frame.h, pycore_interpframe_structs.h and // pycore_interpframe.h. # include "internal/pycore_frame.h" # include "internal/pycore_gc.h" # include "internal/pycore_interp.h" # include "internal/pycore_interpframe.h" # include "internal/pycore_interpframe_structs.h" # include "internal/pycore_object.h" # include "internal/pycore_pystate.h" #endif #ifndef MODULE_NAME # error "MODULE_NAME macro must be defined" #endif #define _STR(NAME) #NAME #define STR(NAME) _STR(NAME) PyDoc_STRVAR(_testcext_add_doc, "add(x, y)\n" "\n" "Return the sum of two integers: x + y."); static PyObject * _testcext_add(PyObject *Py_UNUSED(module), PyObject *args) { long i, j, res; if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) { return NULL; } res = i + j; return PyLong_FromLong(res); } static PyMethodDef _testcext_methods[] = { {"add", _testcext_add, METH_VARARGS, _testcext_add_doc}, {NULL, NULL, 0, NULL} // sentinel }; static int _testcext_exec( #ifdef __STDC_VERSION__ PyObject *module #else PyObject *Py_UNUSED(module) #endif ) { #ifdef __STDC_VERSION__ if (PyModule_AddIntMacro(module, __STDC_VERSION__) < 0) { return -1; } #endif // test Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR() Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int)); assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0); return 0; } #define _FUNC_NAME(NAME) PyModExport_ ## NAME #define FUNC_NAME(NAME) _FUNC_NAME(NAME) // Converting from function pointer to void* has undefined behavior, but // works on all known platforms, and CPython's module and type slots currently // need it. // (GCC doesn't have a narrower category for this than -Wpedantic.) _Py_COMP_DIAG_PUSH #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpedantic" #pragma GCC diagnostic ignored "-Wcast-qual" #elif defined(__clang__) #pragma clang diagnostic ignored "-Wpedantic" #pragma clang diagnostic ignored "-Wcast-qual" #endif PyDoc_STRVAR(_testcext_doc, "C test extension."); static PyModuleDef_Slot _testcext_slots[] = { {Py_mod_name, STR(MODULE_NAME)}, {Py_mod_doc, (void*)(char*)_testcext_doc}, {Py_mod_exec, (void*)_testcext_exec}, {Py_mod_methods, _testcext_methods}, {0, NULL} }; _Py_COMP_DIAG_POP PyMODEXPORT_FUNC FUNC_NAME(MODULE_NAME)(void) { return _testcext_slots; } // Also define the soft-deprecated entrypoint to ensure it isn't called #define _INITFUNC_NAME(NAME) PyInit_ ## NAME #define INITFUNC_NAME(NAME) _INITFUNC_NAME(NAME) PyMODINIT_FUNC INITFUNC_NAME(MODULE_NAME)(void) { PyErr_SetString( PyExc_AssertionError, "PyInit_* function called while a PyModExport_* one is available"); return NULL; }