GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — C API: copying a PyStatus emits -Wdeprecated-declarations in C++ with clang since gh-158080 · Issue #160436 · python/cpython

C API: copying a PyStatus emits -Wdeprecated-declarations in C++ with clang since gh-158080 #160436

New issue
Copy link
New issue
Copy link
Open
Open
C API: copying a PyStatus emits -Wdeprecated-declarations in C++ with clang since gh-158080#160436
Copy link
Labels
3.16new features, bugs and security fixesnew features, bugs and security fixesbuildThe build process and cross-buildThe build process and cross-buildinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-C-API

Description

@davidnich
davidnich
opened on Oct 23, 2026
Issue body actions

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 PyStatus definition is unchanged on current main.
  • 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_POP

With 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

Linked PRs

  • gh-160436: skip PyStatus.exitcode deprecation on clang++ 21 and older #161341

Activity

  1. aisk
    added
    topic-C-API
    buildThe build process and cross-buildThe build process and cross-build
    3.16new features, bugs and security fixesnew features, bugs and security fixes
    on Oct 23, 2026
  2. picnixz
    added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
    on Oct 23, 2026
  3. NekoAsakura commented on Oct 27, 2026

    @NekoAsakura
    NekoAsakura
    on Oct 27, 2026
    Member
    More actions

    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

    _Py_COMP_DIAG_PUSH
    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
    #ifdef Py_GIL_DISABLED
    return _Py_atomic_load_ssize_relaxed(&self->ob_shash);
    #else
    return self->ob_shash;
    #endif
    _Py_COMP_DIAG_POP

    @vstinner shall I go with that?

  4. vstinner commented on Oct 27, 2026

    @vstinner
    vstinner
    on Oct 27, 2026
    Member
    More actions

    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 -Wextra or clang++ -std=c++17 x.cpp -o -x -Wall -Wextra doesn't emit compiler warnings neither:

    struct PyStatus {
        int status;
        __attribute__((__deprecated__)) int exitcode;
    };
    
    PyStatus func(void)
    {
    #if defined(__clang__)
    _Pragma("clang diagnostic push")
    _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
    #else
    _Pragma("GCC diagnostic push")
    _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
    #endif
        PyStatus status = {1, 0};
    #if defined(__clang__)
    _Pragma("clang diagnostic pop")
    #else
    _Pragma("GCC diagnostic pop")
    #endif
        return status;
    }
    
    int main(void)
    {
        PyStatus copy = func();
        return copy.status == 0;
    }
  5. vstinner commented on Oct 27, 2026

    @vstinner
    vstinner
    on Oct 27, 2026
    Member
    More actions

    Can you please try this patch?

    diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h
    index 846e05fb26a..1dcb7807761 100644
    --- a/Include/cpython/initconfig.h
    +++ b/Include/cpython/initconfig.h
    @@ -15,7 +15,13 @@ typedef struct {
         } _type;
         const char *func;
         const char *err_msg;
    +#ifndef __cplusplus
         Py_DEPRECATED(3.16) int exitcode;
    +#else
    +    // Avoid Py_DEPRECATED() on C++ to avoid a compile warning on an (implicit)
    +    // PyStatus move assignment operator.
    +    int exitcode;
    +#endif
     } PyStatus;
     
     PyAPI_FUNC(PyStatus) PyStatus_Ok(void);
  6. vstinner commented on Oct 27, 2026

    @vstinner
    vstinner
    on Oct 27, 2026
    Member
    More actions

    @NekoAsakura: _Py_COMP_DIAG_IGNORE_DEPR_DECLS is 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.

  7. NekoAsakura commented on Oct 28, 2026

    @NekoAsakura
    NekoAsakura
    on Oct 28, 2026
    Member
    More actions

    I cannot reproduce the C++ warning on Fedora 44 with g++ 16.2.1 or clang++ 22.1.8 using your example.

    @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.exitcode in C++ no longer warns.

    _Py_COMP_DIAG_IGNORE_DEPR_DECLS is 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.

    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.

  8. davidnich commented on Oct 28, 2026

    @davidnich
    davidnich
    on Oct 28, 2026
    Author
    More actions

    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.exitcode declared as in 3.16, with -std=c++17 -Wall:

    initconfig.h example from the report s.exitcode in C++ s.exitcode in C
    current (3.16) 3 warnings warning warning
    #ifndef __cplusplus patch no warning no warning warning
    _Py_COMP_DIAG_PUSH / _Py_COMP_DIAG_IGNORE_DEPR_DECLS around the struct definition no warning warning warning

    So, as @NekoAsakura says, the #ifndef __cplusplus patch 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+.

  9. vstinner commented on Nov 4, 2026

    @vstinner
    vstinner
    on Nov 4, 2026
    Member
    More actions

    @vstinner That's because it was fixed in clang >= 22 (llvm/llvm-project#147400). I can confirm your example also warns on older versions.

    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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.16new features, bugs and security fixesnew features, bugs and security fixesbuildThe build process and cross-buildThe build process and cross-buildinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-C-API

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.