1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
// 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"
#include "datetime.h"
#ifdef TEST_INTERNAL_C_API
// gh-135906: Check for compiler warnings in the internal C API.
// - Cython uses pycore_critical_section.h, pycore_frame.h and
// pycore_template.h.
// - greenlet uses pycore_frame.h, pycore_interpframe_structs.h and
// pycore_interpframe.h.
# include "internal/pycore_critical_section.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"
# include "internal/pycore_template.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 PyObject *
test_datetime(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
// datetime.h is excluded from the limited C API
#ifndef Py_LIMITED_API
PyDateTime_IMPORT;
if (PyErr_Occurred()) {
return NULL;
}
#endif
Py_RETURN_NONE;
}
static PyMethodDef _testcext_methods[] = {
{"add", _testcext_add, METH_VARARGS, _testcext_add_doc},
{"test_datetime", test_datetime, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL} // sentinel
};
static int
_testcext_exec(PyObject *module)
{
PyObject *result;
#ifdef __STDC_VERSION__
if (PyModule_AddIntMacro(module, __STDC_VERSION__) < 0) {
return -1;
}
#endif
result = PyObject_CallMethod(module, "test_datetime", "");
if (!result) return -1;
Py_DECREF(result);
// 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;
}
// 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"
#elif defined(__clang__)
#pragma clang diagnostic ignored "-Wpedantic"
#endif
static PyModuleDef_Slot _testcext_slots[] = {
{Py_mod_exec, (void*)_testcext_exec},
{0, NULL}
};
_Py_COMP_DIAG_POP
PyDoc_STRVAR(_testcext_doc, "C test extension.");
static struct PyModuleDef _testcext_module = {
PyModuleDef_HEAD_INIT, // m_base
STR(MODULE_NAME), // m_name
_testcext_doc, // m_doc
0, // m_size
_testcext_methods, // m_methods
_testcext_slots, // m_slots
NULL, // m_traverse
NULL, // m_clear
NULL, // m_free
};
#define _FUNC_NAME(NAME) PyInit_ ## NAME
#define FUNC_NAME(NAME) _FUNC_NAME(NAME)
PyMODINIT_FUNC
FUNC_NAME(MODULE_NAME)(void)
{
return PyModuleDef_Init(&_testcext_module);
}
|