Skip to content

Extension type from documentation doesn't compile in C++20 mode #99202

Description

@arogge

Bug report

C++20 added support for designated initializers and fails to compile if you mix named and unnamed initializers.

For demonstration I'll use the example from the documentation section "Defining Extension Types: Tutorial" with .tp_doc removed from CustomType so it builds on Python 3.10.

When building with C++ compiler in C++20 mode using
g++ $(python3-config --cflags) -std=c++20 -Wall -Wextra -Wno-missing-field-initializers -c pymod.cc
it fails with the following message:

pymod.cc:11:5: error: either all initializer clauses should be designated or none of them should be
   11 |     .tp_name = "custom.Custom",
      |     ^
pymod.cc:20:5: error: either all initializer clauses should be designated or none of them should be
   20 |     .m_name = "custom",
      |     ^

The problem is the macros that produce non-designated initializers here.

Additional information

The following compiles work flawlessly:
GNU C compiler:
gcc $(python3-config --cflags) -Wall -Wextra -Wno-missing-field-initializers -c pymod.cc

GNU C++ compiler with no C++ version specified:
g++ $(python3-config --cflags) -Wall -Wextra -Wno-missing-field-initializers -c pymod.cc

GNU C++ Compiler in C++17 mode:
g++ $(python3-config --cflags) -std=c++17 -Wall -Wextra -Wno-missing-field-initializers -c pymod.cc

Your environment

  • Fedora 36 container with python-devel, gcc and gcc-c++ installed
  • CPython: 3.10.7
  • GCC: 12.2.1 20220819 (Red Hat 12.2.1-2)

The issue leading up to this was our build failing in C++20 mode on at least RHEL 7/8/9, Fedora 34 to 37, SLES 12, SLES 15, Debian 10/11, Ubuntu 16 to 22.
So I guess building with pretty much every GNU C++ compiler will break if you turn on C++20.

pymod.cc:

#define PY_SSIZE_T_CLEAN
#include <Python.h>

typedef struct {
    PyObject_HEAD
    /* Type-specific fields go here. */
} CustomObject;

static PyTypeObject CustomType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "custom.Custom",
    .tp_basicsize = sizeof(CustomObject),
    .tp_itemsize = 0,
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_new = PyType_GenericNew,
};

static PyModuleDef custommodule = {
    PyModuleDef_HEAD_INIT,
    .m_name = "custom",
    .m_doc = "Example module that creates an extension type.",
    .m_size = -1,
};

PyMODINIT_FUNC
PyInit_custom(void)
{
    PyObject *m;
    if (PyType_Ready(&CustomType) < 0)
        return NULL;

    m = PyModule_Create(&custommodule);
    if (m == NULL)
        return NULL;

    Py_INCREF(&CustomType);
    if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
        Py_DECREF(&CustomType);
        Py_DECREF(m);
        return NULL;
    }

    return m;
}

Linked PRs

Activity

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

    docsDocumentation in the Doc dirtopic-C-APItype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions