aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-09-22 16:54:37 +0200
committerGitHub <noreply@github.com>2023-09-22 14:54:37 +0000
commit09a25616a908a028b6373f9ab372d86edf064282 (patch)
tree38675294937df3ea61de15b73271ebc42339d487
parentc32abf1f21c4bd32abcefe4d601611b152568961 (diff)
downloadcpython-09a25616a908a028b6373f9ab372d86edf064282.tar.gz
cpython-09a25616a908a028b6373f9ab372d86edf064282.zip
gh-109723: Disable Py_BUILD_CORE in _testcapi (#109727)
Make sure that the internal C API is not tested by mistake by _testcapi. Undefine Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE macros in Modules/_testcapi/parts.h: move code from _testcapimodule.c. heaptype_relative.c and vectorcall_limited.c are using the limited C API which is incompatible with the internal C API. Move test_long_numbits() from _testcapi to _testinternalcapi since it uses the internal C API "pycore_long.h". Fix Modules/_testcapi/pyatomic.c: don't include Python.h directly, just include _testcapi/parts.h. Ajust "make check-c-globals" for these changes.
-rw-r--r--Modules/_testcapi/clinic/long.c.h19
-rw-r--r--Modules/_testcapi/long.c53
-rw-r--r--Modules/_testcapi/parts.h16
-rw-r--r--Modules/_testcapi/pyatomic.c4
-rw-r--r--Modules/_testcapimodule.c25
-rw-r--r--Modules/_testinternalcapi.c62
-rw-r--r--Modules/clinic/_testinternalcapi.c.h19
-rw-r--r--Tools/c-analyzer/c_parser/preprocessor/gcc.py17
8 files changed, 114 insertions, 101 deletions
diff --git a/Modules/_testcapi/clinic/long.c.h b/Modules/_testcapi/clinic/long.c.h
index b77cb51810c..e2f7042be12 100644
--- a/Modules/_testcapi/clinic/long.c.h
+++ b/Modules/_testcapi/clinic/long.c.h
@@ -133,23 +133,6 @@ _testcapi_test_long_as_double(PyObject *module, PyObject *Py_UNUSED(ignored))
return _testcapi_test_long_as_double_impl(module);
}
-PyDoc_STRVAR(_testcapi_test_long_numbits__doc__,
-"test_long_numbits($module, /)\n"
-"--\n"
-"\n");
-
-#define _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF \
- {"test_long_numbits", (PyCFunction)_testcapi_test_long_numbits, METH_NOARGS, _testcapi_test_long_numbits__doc__},
-
-static PyObject *
-_testcapi_test_long_numbits_impl(PyObject *module);
-
-static PyObject *
-_testcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignored))
-{
- return _testcapi_test_long_numbits_impl(module);
-}
-
PyDoc_STRVAR(_testcapi_call_long_compact_api__doc__,
"call_long_compact_api($module, arg, /)\n"
"--\n"
@@ -165,4 +148,4 @@ PyDoc_STRVAR(_testcapi_PyLong_AsInt__doc__,
#define _TESTCAPI_PYLONG_ASINT_METHODDEF \
{"PyLong_AsInt", (PyCFunction)_testcapi_PyLong_AsInt, METH_O, _testcapi_PyLong_AsInt__doc__},
-/*[clinic end generated code: output=31267ab2dd90aa1d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=de762870526e241d input=a9049054013a1b77]*/
diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c
index c1d2d42a2c4..4362f431fc3 100644
--- a/Modules/_testcapi/long.c
+++ b/Modules/_testcapi/long.c
@@ -4,7 +4,6 @@
#include "parts.h"
#include "clinic/long.c.h"
-#include "pycore_long.h" // _PyLong_Sign()
/*[clinic input]
module _testcapi
@@ -536,57 +535,6 @@ _testcapi_test_long_as_double_impl(PyObject *module)
}
/*[clinic input]
-_testcapi.test_long_numbits
-[clinic start generated code]*/
-
-static PyObject *
-_testcapi_test_long_numbits_impl(PyObject *module)
-/*[clinic end generated code: output=9eaf8458cb15d7f7 input=265c02d48a13059e]*/
-{
- struct triple {
- long input;
- size_t nbits;
- int sign;
- } testcases[] = {{0, 0, 0},
- {1L, 1, 1},
- {-1L, 1, -1},
- {2L, 2, 1},
- {-2L, 2, -1},
- {3L, 2, 1},
- {-3L, 2, -1},
- {4L, 3, 1},
- {-4L, 3, -1},
- {0x7fffL, 15, 1}, /* one Python int digit */
- {-0x7fffL, 15, -1},
- {0xffffL, 16, 1},
- {-0xffffL, 16, -1},
- {0xfffffffL, 28, 1},
- {-0xfffffffL, 28, -1}};
- size_t i;
-
- for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) {
- size_t nbits;
- int sign;
- PyObject *plong;
-
- plong = PyLong_FromLong(testcases[i].input);
- if (plong == NULL)
- return NULL;
- nbits = _PyLong_NumBits(plong);
- sign = _PyLong_Sign(plong);
-
- Py_DECREF(plong);
- if (nbits != testcases[i].nbits)
- return raiseTestError("test_long_numbits",
- "wrong result for _PyLong_NumBits");
- if (sign != testcases[i].sign)
- return raiseTestError("test_long_numbits",
- "wrong result for _PyLong_Sign");
- }
- Py_RETURN_NONE;
-}
-
-/*[clinic input]
_testcapi.call_long_compact_api
arg: object
/
@@ -631,7 +579,6 @@ static PyMethodDef test_methods[] = {
_TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF
_TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF
_TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF
- _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF
_TESTCAPI_TEST_LONGLONG_API_METHODDEF
_TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF
_TESTCAPI_PYLONG_ASINT_METHODDEF
diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h
index c162dbc65db..24abe54814e 100644
--- a/Modules/_testcapi/parts.h
+++ b/Modules/_testcapi/parts.h
@@ -4,8 +4,24 @@
// Always enable assertions
#undef NDEBUG
+// The _testcapi extension tests the public C API: header files in Include/ and
+// Include/cpython/ directories. The internal C API must not be tested by
+// _testcapi: use _testinternalcapi for that.
+//
+// _testcapi C files can built with the Py_BUILD_CORE_BUILTIN macro defined if
+// one of the Modules/Setup files asks to build _testcapi as "static"
+// (gh-109723).
+//
+// The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE.
+#undef Py_BUILD_CORE_MODULE
+#undef Py_BUILD_CORE_BUILTIN
+
#include "Python.h"
+#ifdef Py_BUILD_CORE
+# error "_testcapi must test the public Python C API, not the internal C API"
+#endif
+
int _PyTestCapi_Init_Vectorcall(PyObject *module);
int _PyTestCapi_Init_Heaptype(PyObject *module);
int _PyTestCapi_Init_Abstract(PyObject *module);
diff --git a/Modules/_testcapi/pyatomic.c b/Modules/_testcapi/pyatomic.c
index f0be2cfcccc..5aedf687705 100644
--- a/Modules/_testcapi/pyatomic.c
+++ b/Modules/_testcapi/pyatomic.c
@@ -4,10 +4,6 @@
* This only tests basic functionality, not any synchronizing ordering.
*/
-/* Always enable assertions */
-#undef NDEBUG
-
-#include "Python.h"
#include "parts.h"
// We define atomic bitwise operations on these types
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index f356fc5a6a0..e09fd8806d2 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -5,19 +5,13 @@
* standard Python regression test, via Lib/test/test_capi.py.
*/
-/* This module tests the public (Include/ and Include/cpython/) C API.
- The internal C API must not be used here: use _testinternalcapi for that.
-
- The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE
- macro defined, but only the public C API must be tested here. */
-
-#undef Py_BUILD_CORE_MODULE
-#undef Py_BUILD_CORE_BUILTIN
-
-/* Always enable assertions */
-#undef NDEBUG
+// Include parts.h first since it takes care of NDEBUG and Py_BUILD_CORE macros
+// and including Python.h.
+//
+// Several parts of this module are broken out into files in _testcapi/.
+// Include definitions from there.
+#include "_testcapi/parts.h"
-#include "Python.h"
#include "frameobject.h" // PyFrame_New()
#include "marshal.h" // PyMarshal_WriteLongToFile()
@@ -29,17 +23,10 @@
# include <sys/wait.h> // W_STOPCODE
#endif
-#ifdef Py_BUILD_CORE
-# error "_testcapi must test the public Python C API, not CPython internal C API"
-#endif
-
#ifdef bool
# error "The public headers should not include <stdbool.h>, see gh-48924"
#endif
-// Several parts of this module are broken out into files in _testcapi/.
-// Include definitions from there.
-#include "_testcapi/parts.h"
#include "_testcapi/util.h"
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index f97b609f7ad..c6b80fffdec 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -22,6 +22,7 @@
#include "pycore_hashtable.h" // _Py_hashtable_new()
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
+#include "pycore_long.h" // _PyLong_Sign()
#include "pycore_object.h" // _PyObject_IsFreed()
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
@@ -1466,6 +1467,66 @@ _testinternalcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc,
}
+static PyObject *
+raiseTestError(const char* test_name, const char* msg)
+{
+ PyErr_Format(PyExc_AssertionError, "%s: %s", test_name, msg);
+ return NULL;
+}
+
+
+/*[clinic input]
+_testinternalcapi.test_long_numbits
+[clinic start generated code]*/
+
+static PyObject *
+_testinternalcapi_test_long_numbits_impl(PyObject *module)
+/*[clinic end generated code: output=745d62d120359434 input=f14ca6f638e44dad]*/
+{
+ struct triple {
+ long input;
+ size_t nbits;
+ int sign;
+ } testcases[] = {{0, 0, 0},
+ {1L, 1, 1},
+ {-1L, 1, -1},
+ {2L, 2, 1},
+ {-2L, 2, -1},
+ {3L, 2, 1},
+ {-3L, 2, -1},
+ {4L, 3, 1},
+ {-4L, 3, -1},
+ {0x7fffL, 15, 1}, /* one Python int digit */
+ {-0x7fffL, 15, -1},
+ {0xffffL, 16, 1},
+ {-0xffffL, 16, -1},
+ {0xfffffffL, 28, 1},
+ {-0xfffffffL, 28, -1}};
+ size_t i;
+
+ for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) {
+ size_t nbits;
+ int sign;
+ PyObject *plong;
+
+ plong = PyLong_FromLong(testcases[i].input);
+ if (plong == NULL)
+ return NULL;
+ nbits = _PyLong_NumBits(plong);
+ sign = _PyLong_Sign(plong);
+
+ Py_DECREF(plong);
+ if (nbits != testcases[i].nbits)
+ return raiseTestError("test_long_numbits",
+ "wrong result for _PyLong_NumBits");
+ if (sign != testcases[i].sign)
+ return raiseTestError("test_long_numbits",
+ "wrong result for _PyLong_Sign");
+ }
+ Py_RETURN_NONE;
+}
+
+
static PyMethodDef module_functions[] = {
{"get_configs", get_configs, METH_NOARGS},
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1521,6 +1582,7 @@ static PyMethodDef module_functions[] = {
_PyCFunction_CAST(run_in_subinterp_with_config),
METH_VARARGS | METH_KEYWORDS},
_TESTINTERNALCAPI_WRITE_UNRAISABLE_EXC_METHODDEF
+ _TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF
{NULL, NULL} /* sentinel */
};
diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h
index 38a3579d7de..c1b42672e13 100644
--- a/Modules/clinic/_testinternalcapi.c.h
+++ b/Modules/clinic/_testinternalcapi.c.h
@@ -296,4 +296,21 @@ _testinternalcapi_write_unraisable_exc(PyObject *module, PyObject *const *args,
exit:
return return_value;
}
-/*[clinic end generated code: output=c7156622e80df1ce input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(_testinternalcapi_test_long_numbits__doc__,
+"test_long_numbits($module, /)\n"
+"--\n"
+"\n");
+
+#define _TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF \
+ {"test_long_numbits", (PyCFunction)_testinternalcapi_test_long_numbits, METH_NOARGS, _testinternalcapi_test_long_numbits__doc__},
+
+static PyObject *
+_testinternalcapi_test_long_numbits_impl(PyObject *module);
+
+static PyObject *
+_testinternalcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _testinternalcapi_test_long_numbits_impl(module);
+}
+/*[clinic end generated code: output=59144f59957627bd input=a9049054013a1b77]*/
diff --git a/Tools/c-analyzer/c_parser/preprocessor/gcc.py b/Tools/c-analyzer/c_parser/preprocessor/gcc.py
index d206ceb43a2..6ece70c77fd 100644
--- a/Tools/c-analyzer/c_parser/preprocessor/gcc.py
+++ b/Tools/c-analyzer/c_parser/preprocessor/gcc.py
@@ -3,18 +3,20 @@ import re
from . import common as _common
-# The following C files define the Py_LIMITED_API macro, and so must not be
-# built with the Py_BUILD_CORE macro defined.
-USE_LIMITED_C_API = frozenset((
+# The following C files must not built with Py_BUILD_CORE.
+FILES_WITHOUT_INTERNAL_CAPI = frozenset((
# Modules/
'_testcapimodule.c',
'_testclinic_limited.c',
'xxlimited.c',
'xxlimited_35.c',
+))
+# C files in the fhe following directories must not be built with
+# Py_BUILD_CORE.
+DIRS_WITHOUT_INTERNAL_CAPI = frozenset((
# Modules/_testcapi/
- 'heaptype_relative.c',
- 'vectorcall_limited.c',
+ '_testcapi',
))
TOOL = 'gcc'
@@ -75,7 +77,10 @@ def preprocess(filename,
filename = _normpath(filename, cwd)
postargs = POST_ARGS
- if os.path.basename(filename) not in USE_LIMITED_C_API:
+ basename = os.path.basename(filename)
+ dirname = os.path.basename(os.path.dirname(filename))
+ if (basename not in FILES_WITHOUT_INTERNAL_CAPI
+ and dirname not in DIRS_WITHOUT_INTERNAL_CAPI):
postargs += ('-DPy_BUILD_CORE=1',)
text = _common.preprocess(