From d91cc9db155024b0a221cf32f4f49617544618bf Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 4 Mar 2025 14:10:09 +0100 Subject: gh-129666: Add C11/C++11 to docs and -pedantic-errors to GCC/clang test_c[pp]ext tests (GH-130692) Disable pedantic check for c++03 (unlimited API) Also add a check for c++03 *limited* API, which passes in pedantic mode after removing a comma in the `PySendResult` declaration, and allowing `long long`. --- Doc/c-api/intro.rst | 10 ++++++++++ Include/object.h | 2 +- Lib/test/test_cext/__init__.py | 3 +++ Lib/test/test_cext/extension.c | 13 +++++++++++++ Lib/test/test_cext/setup.py | 3 +++ Lib/test/test_cppext/__init__.py | 7 +++++++ Lib/test/test_cppext/extension.cpp | 22 ++++++++++++++++++++++ Lib/test/test_cppext/setup.py | 16 ++++++++++++++++ 8 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index 8ef463e..76d7d57 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -30,6 +30,16 @@ familiar with writing an extension before attempting to embed Python in a real application. +Language version compatibility +============================== + +Python's C API is compatible with C11 and C++11 versions of C and C++. + +This is a lower limit: the C API does not require features from later +C/C++ versions. +You do *not* need to enable your compiler's "c11 mode". + + Coding standards ================ diff --git a/Include/object.h b/Include/object.h index da7b366..7d1667d 100644 --- a/Include/object.h +++ b/Include/object.h @@ -683,7 +683,7 @@ PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */ typedef enum { PYGEN_RETURN = 0, PYGEN_ERROR = -1, - PYGEN_NEXT = 1, + PYGEN_NEXT = 1 } PySendResult; #endif diff --git a/Lib/test/test_cext/__init__.py b/Lib/test/test_cext/__init__.py index 54859f9..402a2d0 100644 --- a/Lib/test/test_cext/__init__.py +++ b/Lib/test/test_cext/__init__.py @@ -38,6 +38,9 @@ class TestExt(unittest.TestCase): @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c99") def test_build_c99(self): + # In public docs, we say C API is compatible with C11. However, + # in practice we do maintain C99 compatibility in public headers. + # Please ask the C API WG before adding a new C11-only feature. self.check_build('_test_c99_cext', std='c99') @support.requires_gil_enabled('incompatible with Free Threading') diff --git a/Lib/test/test_cext/extension.c b/Lib/test/test_cext/extension.c index b76abe1..64629c5 100644 --- a/Lib/test/test_cext/extension.c +++ b/Lib/test/test_cext/extension.c @@ -58,11 +58,24 @@ _testcext_exec( 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."); diff --git a/Lib/test/test_cext/setup.py b/Lib/test/test_cext/setup.py index e97749b..1275282 100644 --- a/Lib/test/test_cext/setup.py +++ b/Lib/test/test_cext/setup.py @@ -21,6 +21,9 @@ if not support.MS_WINDOWS: # gh-120593: Check the 'const' qualifier '-Wcast-qual', + + # Ask for strict(er) compliance with the standard + '-pedantic-errors', ] if not support.Py_GIL_DISABLED: CFLAGS.append( diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py index d519522..13f9ea1 100644 --- a/Lib/test/test_cppext/__init__.py +++ b/Lib/test/test_cppext/__init__.py @@ -29,8 +29,15 @@ class TestCPPExt(unittest.TestCase): self.check_build('_testcppext') def test_build_cpp03(self): + # In public docs, we say C API is compatible with C++11. However, + # in practice we do maintain C++03 compatibility in public headers. + # Please ask the C API WG before adding a new C++11-only feature. self.check_build('_testcpp03ext', std='c++03') + @support.requires_gil_enabled('incompatible with Free Threading') + def test_build_limited_cpp03(self): + self.check_build('_test_limited_cpp03ext', std='c++03', limited=True) + @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c++11") def test_build_cpp11(self): self.check_build('_testcpp11ext', std='c++11') diff --git a/Lib/test/test_cppext/extension.cpp b/Lib/test/test_cppext/extension.cpp index 500d591..5b3571b 100644 --- a/Lib/test/test_cppext/extension.cpp +++ b/Lib/test/test_cppext/extension.cpp @@ -161,11 +161,24 @@ private: int VirtualPyObject::instance_count = 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 + PyType_Slot VirtualPyObject_Slots[] = { {Py_tp_free, (void*)VirtualPyObject::dealloc}, {0, _Py_NULL}, }; +_Py_COMP_DIAG_POP + PyType_Spec VirtualPyObject_Spec = { /* .name */ STR(MODULE_NAME) ".VirtualPyObject", /* .basicsize */ sizeof(VirtualPyObject), @@ -241,11 +254,20 @@ _testcppext_exec(PyObject *module) return 0; } +// Need to ignore "-Wpedantic" warnings; see VirtualPyObject_Slots above +_Py_COMP_DIAG_PUSH +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wpedantic" +#elif defined(__clang__) +#pragma clang diagnostic ignored "-Wpedantic" +#endif + static PyModuleDef_Slot _testcppext_slots[] = { {Py_mod_exec, reinterpret_cast(_testcppext_exec)}, {0, _Py_NULL} }; +_Py_COMP_DIAG_POP PyDoc_STRVAR(_testcppext_doc, "C++ test extension."); diff --git a/Lib/test/test_cppext/setup.py b/Lib/test/test_cppext/setup.py index 019ff18..b30c9e2 100644 --- a/Lib/test/test_cppext/setup.py +++ b/Lib/test/test_cppext/setup.py @@ -19,6 +19,17 @@ if not support.MS_WINDOWS: # warnings '-Werror', ] + + CPPFLAGS_PEDANTIC = [ + # Ask for strict(er) compliance with the standard. + # We cannot do this for c++03 unlimited API, since several headers in + # Include/cpython/ use commas at end of `enum` declarations, a C++11 + # feature for which GCC has no narrower option than -Wpedantic itself. + '-pedantic-errors', + + # We also use `long long`, a C++11 feature we can enable individually. + '-Wno-long-long', + ] else: # MSVC compiler flags CPPFLAGS = [ @@ -27,6 +38,7 @@ else: # Treat all compiler warnings as compiler errors '/WX', ] + CPPFLAGS_PEDANTIC = [] def main(): @@ -45,6 +57,10 @@ def main(): else: cppflags.append(f'-std={std}') + if limited or (std != 'c++03'): + # See CPPFLAGS_PEDANTIC docstring + cppflags.extend(CPPFLAGS_PEDANTIC) + # gh-105776: When "gcc -std=11" is used as the C++ compiler, -std=c11 # option emits a C++ compiler warning. Remove "-std11" option from the # CC command. -- cgit v0.12