]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109723: Disable Py_BUILD_CORE in _testcapi (#109727)
authorVictor Stinner <vstinner@python.org>
Fri, 22 Sep 2023 14:54:37 +0000 (16:54 +0200)
committerGitHub <noreply@github.com>
Fri, 22 Sep 2023 14:54:37 +0000 (14:54 +0000)
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.

Modules/_testcapi/clinic/long.c.h
Modules/_testcapi/long.c
Modules/_testcapi/parts.h
Modules/_testcapi/pyatomic.c
Modules/_testcapimodule.c
Modules/_testinternalcapi.c
Modules/clinic/_testinternalcapi.c.h
Tools/c-analyzer/c_parser/preprocessor/gcc.py

index b77cb51810cb65adfe2a9ff67cf2ff6427a8da47..e2f7042be12c48f7a40412c094b9177b544d25ca 100644 (file)
@@ -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]*/
index c1d2d42a2c434e38c502b1e2bd6623f5abec84d2..4362f431fc3f4d5d7ea566d99459649973630c70 100644 (file)
@@ -4,7 +4,6 @@
 
 #include "parts.h"
 #include "clinic/long.c.h"
-#include "pycore_long.h"          // _PyLong_Sign()
 
 /*[clinic input]
 module _testcapi
@@ -535,57 +534,6 @@ _testcapi_test_long_as_double_impl(PyObject *module)
     return Py_None;
 }
 
-/*[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
index c162dbc65db81ae0032abd01569ea920c730a36c..24abe54814e611b42f841a102ba3957de73bdc31 100644 (file)
@@ -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);
index f0be2cfccccc98f99d49ec4dfa9b5ed4452abf17..5aedf6877057072e8a6acadf36286b7d623b57d3 100644 (file)
@@ -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
index f356fc5a6a016e1b7ced11be398ced71d9cfdabc..e09fd8806d2f64618da15f001ca296cec01b1486 100644 (file)
@@ -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()
 
 #  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"
 
 
index f97b609f7ad2efa8e08bfa7b3eaaa14f74e682ee..c6b80fffdec16d893ea8dee7de27dd4d9765e7a7 100644 (file)
@@ -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 */
 };
 
index 38a3579d7dec77b0c0b31f5839ba65e1a9f5305b..c1b42672e13d535eb1711447c8de3c5f1b681cc6 100644 (file)
@@ -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]*/
index d206ceb43a268edd0d7e29db3573ff562d060296..6ece70c77fd55c3947f2ebca7c32bb1da64dac23 100644 (file)
@@ -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(