Repository navigation
Description
Bug description:
Since gh-158080 (GH-158085), PyStatus.exitcode is declared with Py_DEPRECATED(3.16) in Include/cpython/initconfig.h. Because the C API passes and returns PyStatus by value (PyStatus_Exception(), PyStatus_IsError(), Py_InitializeFromConfig(), ...), C++ code that uses the API in the documented way makes clang generate the implicit copy constructor / move assignment operator of PyStatus. These use the deprecated member, so clang emits -Wdeprecated-declarations even though the code never touches exitcode. With -Werror, the build fails.
The usage pattern of the Doc/c-api/init_config.rst examples (ex: init_python()), compiled as C++, is enough to reproduce:
#include <Python.h>
int main(int argc, char** argv) {
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
if (PyStatus_Exception(status)) {
goto exception;
}
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto exception;
}
PyConfig_Clear(&config);
return Py_RunMain();
exception:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}$ clang++ -std=c++17 -Wall -Werror -I<cpython>/Include -I<build> -c embed.cpp
Include/cpython/initconfig.h:10:9: error: 'exitcode' is deprecated [-Werror,-Wdeprecated-declarations]
embed.cpp:7:12: note: in implicit move assignment operator for 'PyStatus' first required here
Include/cpython/initconfig.h:10:9: error: 'exitcode' is deprecated [-Werror,-Wdeprecated-declarations]
Include/cpython/initconfig.h:10:9: error: 'exitcode' is deprecated [-Werror,-Wdeprecated-declarations]
embed.cpp:8:28: note: in implicit copy constructor for 'PyStatus' first required here
- Reproduced with 3.16.0a1, with Ubuntu clang 21.1.8 (Linux aarch64) and Apple clang 21.0.0 (macOS arm64); the
PyStatusdefinition is unchanged on currentmain. - g++ 15, and clang compiling the same file as C, emit no warning.
- The diagnostic is reported at the definition of the structure in
initconfig.h, so users cannot silence it locally with a pragma around their own calls; they have to wrap the#include <Python.h>itself.
Possible fix
Suppress the warning around the definition of the structure, with the existing _Py_COMP_DIAG_* macros of pyport.h:
/* --- PyStatus ----------------------------------------------- */
+_Py_COMP_DIAG_PUSH
+_Py_COMP_DIAG_IGNORE_DEPR_DECLS
typedef struct {
enum {
_PyStatus_TYPE_OK=0,
_PyStatus_TYPE_ERROR=1,
_PyStatus_TYPE_EXIT=2 // deprecated
} _type;
const char *func;
const char *err_msg;
Py_DEPRECATED(3.16) int exitcode;
} PyStatus;
+_Py_COMP_DIAG_POPWith this change the example above compiles cleanly with clang++ -Werror, while real uses (status.exitcode, PyStatus_Exit(), PyStatus_IsExit()) still emit the deprecation warning. (Alternatively, only the functions could be marked deprecated and the member documented as deprecated.)
A C++ test in Lib/test/test_cppext that copies a PyStatus would catch regressions of this kind.
CPython versions tested on:
3.16, CPython main branch
Operating systems tested on:
Linux, macOS
Activity
NekoAsakura commentedon Oct 27, 2026
Reproduced with clang 5 to 21. It looks like we already do the pragma option for deprecated code elsewhere.
cpython/Include/internal/pycore_bytesobject.h
Lines 96 to 103 in 969af80
@vstinner shall I go with that?
vstinner commentedon Oct 27, 2026
I cannot reproduce the C++ warning on Fedora 44 with g++ 16.2.1 or clang++ 22.1.8 using your example.
Building this C++ code with
g++ -std=c++17 x.cpp -o -x -Wall -Wextraorclang++ -std=c++17 x.cpp -o -x -Wall -Wextradoesn't emit compiler warnings neither:vstinner commentedon Oct 27, 2026
Can you please try this patch?
vstinner commentedon Oct 27, 2026
@NekoAsakura:
_Py_COMP_DIAG_IGNORE_DEPR_DECLSis designed to ignore a deprecation warning when using a deprecated function/API. I don't think that it should be used when marking an API as deprecated.NekoAsakura commentedon Oct 28, 2026
@vstinner That's because it was fixed in clang >= 22 (#147400). I can confirm your example also warns on older versions.
I also tried your patch. It fixes the issue, but it causes a regression where using
status.exitcodein C++ no longer warns.It is usually used around code that uses a deprecated API, but here the warning is reported inside Python.h, so users can't silence it in their own code.
davidnich commentedon Oct 28, 2026
Tested with Apple clang 21.0.0 (clang-2100.3.34.2, current Xcode, arm64), using a copy of the 3.14 headers with
PyStatus.exitcodedeclared as in 3.16, with-std=c++17 -Wall:initconfig.hs.exitcodein C++s.exitcodein C#ifndef __cpluspluspatch_Py_COMP_DIAG_PUSH/_Py_COMP_DIAG_IGNORE_DEPR_DECLSaround the struct definitionSo, as @NekoAsakura says, the
#ifndef __cpluspluspatch fixes the false positive but drops the deprecation for real C++ uses. Suppressing the warning only around the definition keeps it. Clang reports the warning for a use in the user's own code, outside the push/pop region, so only the implicit copy/move members generated from the definition are affected. Apple's current clang 21 still has the behavior fixed in clang 22 (llvm/llvm-project#147400), so macOS embedders building with Xcode will hit this until Xcode ships clang 22+.vstinner commentedon Nov 4, 2026
Ah. In that case, I suggest to skip Py_DEPRECATED() on clang++ 21 and older. It's not a big deal, PyStatus.exitcode deprecation is not very important :-)
@NekoAsakura: Do you want to propose a PR for that?