diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ec274a025d..c1b88c4c20 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3398,37 +3398,12 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) } } - res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, nmembers); - if (res == NULL) - return NULL; - res_start = (char*)res; - if (spec->name == NULL) { PyErr_SetString(PyExc_SystemError, "Type spec does not define the name field."); - goto fail; + return NULL; } - /* Set the type name and qualname */ - const char *s = strrchr(spec->name, '.'); - if (s == NULL) - s = spec->name; - else - s++; - - type = &res->ht_type; - /* The flags must be initialized early, before the GC traverses us */ - type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; - res->ht_name = PyUnicode_FromString(s); - if (!res->ht_name) - goto fail; - res->ht_qualname = res->ht_name; - Py_INCREF(res->ht_qualname); - type->tp_name = spec->name; - - Py_XINCREF(module); - res->ht_module = module; - /* Adjust for empty tuple bases */ if (!bases) { base = &PyBaseObject_Type; @@ -3443,11 +3418,11 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) if (!bases) { bases = PyTuple_Pack(1, base); if (!bases) - goto fail; + return NULL; } else if (!PyTuple_Check(bases)) { PyErr_SetString(PyExc_SystemError, "Py_tp_bases is not a tuple"); - goto fail; + return NULL; } else { Py_INCREF(bases); @@ -3456,12 +3431,47 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) else if (!PyTuple_Check(bases)) { bases = PyTuple_Pack(1, bases); if (!bases) - goto fail; + return NULL; } else { Py_INCREF(bases); } + /* NOTE: We could e.g. use a slot to customize `&PyType_Type` here */ + PyTypeObject *metatype = _PyType_CalculateMetaclass(&PyType_Type, bases); + if (metatype == NULL) { + Py_DECREF(bases); + return NULL; + } + res = (PyHeapTypeObject*)metatype->tp_alloc(metatype, nmembers); + if (res == NULL) { + Py_DECREF(bases); + return NULL; + } + res_start = (char*)res; + + /* Set the type name and qualname */ + const char *s = strrchr(spec->name, '.'); + if (s == NULL) + s = spec->name; + else + s++; + + type = &res->ht_type; + /* The flags must be initialized early, before the GC traverses us */ + type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; + res->ht_name = PyUnicode_FromString(s); + if (!res->ht_name) { + Py_DECREF(bases); + goto fail; + } + res->ht_qualname = res->ht_name; + Py_INCREF(res->ht_qualname); + type->tp_name = spec->name; + + Py_XINCREF(module); + res->ht_module = module; + /* Calculate best base, and check that all bases are type objects */ base = best_base(bases); if (base == NULL) {