gh-111178: Avoid calling functions from incompatible pointer types in dictobject.c (#112892)

Fix undefined behavior warnings (UBSan  -fsanitize=function).
This commit is contained in:
Christopher Chavez 2024-01-02 08:32:37 -06:00 committed by GitHub
parent acf4cf5ca5
commit a1eea1d032
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 126 additions and 100 deletions

View File

@ -237,7 +237,7 @@ equally good collision statistics, needed less code & used less memory.
static int dictresize(PyInterpreterState *interp, PyDictObject *mp,
uint8_t log_newsize, int unicode);
static PyObject* dict_iter(PyDictObject *dict);
static PyObject* dict_iter(PyObject *dict);
#include "clinic/dictobject.c.h"
@ -792,7 +792,7 @@ static PyDictKeysObject *
clone_combined_dict_keys(PyDictObject *orig)
{
assert(PyDict_Check(orig));
assert(Py_TYPE(orig)->tp_iter == (getiterfunc)dict_iter);
assert(Py_TYPE(orig)->tp_iter == dict_iter);
assert(orig->ma_values == NULL);
assert(orig->ma_keys != Py_EMPTY_KEYS);
assert(orig->ma_keys->dk_refcnt == 1);
@ -2450,8 +2450,9 @@ Fail:
/* Methods */
static void
dict_dealloc(PyDictObject *mp)
dict_dealloc(PyObject *self)
{
PyDictObject *mp = (PyDictObject *)self;
PyInterpreterState *interp = _PyInterpreterState_GET();
assert(Py_REFCNT(mp) == 0);
Py_SET_REFCNT(mp, 1);
@ -2499,8 +2500,9 @@ dict_dealloc(PyDictObject *mp)
static PyObject *
dict_repr(PyDictObject *mp)
dict_repr(PyObject *self)
{
PyDictObject *mp = (PyDictObject *)self;
Py_ssize_t i;
PyObject *key = NULL, *value = NULL;
_PyUnicodeWriter writer;
@ -2582,14 +2584,16 @@ error:
}
static Py_ssize_t
dict_length(PyDictObject *mp)
dict_length(PyObject *self)
{
PyDictObject *mp = (PyDictObject *)self;
return mp->ma_used;
}
static PyObject *
dict_subscript(PyDictObject *mp, PyObject *key)
dict_subscript(PyObject *self, PyObject *key)
{
PyDictObject *mp = (PyDictObject *)self;
Py_ssize_t ix;
Py_hash_t hash;
PyObject *value;
@ -2623,18 +2627,18 @@ dict_subscript(PyDictObject *mp, PyObject *key)
}
static int
dict_ass_sub(PyDictObject *mp, PyObject *v, PyObject *w)
dict_ass_sub(PyObject *mp, PyObject *v, PyObject *w)
{
if (w == NULL)
return PyDict_DelItem((PyObject *)mp, v);
return PyDict_DelItem(mp, v);
else
return PyDict_SetItem((PyObject *)mp, v, w);
return PyDict_SetItem(mp, v, w);
}
static PyMappingMethods dict_as_mapping = {
(lenfunc)dict_length, /*mp_length*/
(binaryfunc)dict_subscript, /*mp_subscript*/
(objobjargproc)dict_ass_sub, /*mp_ass_subscript*/
dict_length, /*mp_length*/
dict_subscript, /*mp_subscript*/
dict_ass_sub, /*mp_ass_subscript*/
};
static PyObject *
@ -2925,7 +2929,7 @@ dict_merge(PyInterpreterState *interp, PyObject *a, PyObject *b, int override)
return -1;
}
mp = (PyDictObject*)a;
if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == (getiterfunc)dict_iter)) {
if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == dict_iter)) {
other = (PyDictObject*)b;
if (other == mp || other->ma_used == 0)
/* a.update(a) or a.update({}); nothing to do */
@ -3105,9 +3109,9 @@ _PyDict_MergeEx(PyObject *a, PyObject *b, int override)
}
static PyObject *
dict_copy(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
dict_copy(PyObject *mp, PyObject *Py_UNUSED(ignored))
{
return PyDict_Copy((PyObject*)mp);
return PyDict_Copy(mp);
}
PyObject *
@ -3155,7 +3159,7 @@ PyDict_Copy(PyObject *o)
return (PyObject *)split_copy;
}
if (Py_TYPE(mp)->tp_iter == (getiterfunc)dict_iter &&
if (Py_TYPE(mp)->tp_iter == dict_iter &&
mp->ma_values == NULL &&
(mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3))
{
@ -3509,9 +3513,9 @@ dict_setdefault_impl(PyDictObject *self, PyObject *key,
}
static PyObject *
dict_clear(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
dict_clear(PyObject *mp, PyObject *Py_UNUSED(ignored))
{
PyDict_Clear((PyObject *)mp);
PyDict_Clear(mp);
Py_RETURN_NONE;
}
@ -3700,8 +3704,9 @@ _PyDict_KeysSize(PyDictKeysObject *keys)
}
static PyObject *
dict_sizeof(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
dict_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored))
{
PyDictObject *mp = (PyDictObject *)self;
return PyLong_FromSsize_t(_PyDict_SizeOf(mp));
}
@ -3763,9 +3768,9 @@ PyDoc_STRVAR(values__doc__,
static PyMethodDef mapp_methods[] = {
DICT___CONTAINS___METHODDEF
{"__getitem__", _PyCFunction_CAST(dict_subscript), METH_O | METH_COEXIST,
{"__getitem__", dict_subscript, METH_O | METH_COEXIST,
getitem__doc__},
{"__sizeof__", _PyCFunction_CAST(dict_sizeof), METH_NOARGS,
{"__sizeof__", dict_sizeof, METH_NOARGS,
sizeof__doc__},
DICT_GET_METHODDEF
DICT_SETDEFAULT_METHODDEF
@ -3780,9 +3785,9 @@ static PyMethodDef mapp_methods[] = {
{"update", _PyCFunction_CAST(dict_update), METH_VARARGS | METH_KEYWORDS,
update__doc__},
DICT_FROMKEYS_METHODDEF
{"clear", (PyCFunction)dict_clear, METH_NOARGS,
{"clear", dict_clear, METH_NOARGS,
clear__doc__},
{"copy", (PyCFunction)dict_copy, METH_NOARGS,
{"copy", dict_copy, METH_NOARGS,
copy__doc__},
DICT___REVERSED___METHODDEF
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
@ -3937,8 +3942,9 @@ dict_vectorcall(PyObject *type, PyObject * const*args,
}
static PyObject *
dict_iter(PyDictObject *dict)
dict_iter(PyObject *self)
{
PyDictObject *dict = (PyDictObject *)self;
return dictiter_new(dict, &PyDictIterKey_Type);
}
@ -3958,12 +3964,12 @@ PyTypeObject PyDict_Type = {
"dict",
sizeof(PyDictObject),
0,
(destructor)dict_dealloc, /* tp_dealloc */
dict_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)dict_repr, /* tp_repr */
dict_repr, /* tp_repr */
&dict_as_number, /* tp_as_number */
&dict_as_sequence, /* tp_as_sequence */
&dict_as_mapping, /* tp_as_mapping */
@ -3981,7 +3987,7 @@ PyTypeObject PyDict_Type = {
dict_tp_clear, /* tp_clear */
dict_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)dict_iter, /* tp_iter */
dict_iter, /* tp_iter */
0, /* tp_iternext */
mapp_methods, /* tp_methods */
0, /* tp_members */
@ -4128,8 +4134,9 @@ dictiter_new(PyDictObject *dict, PyTypeObject *itertype)
}
static void
dictiter_dealloc(dictiterobject *di)
dictiter_dealloc(PyObject *self)
{
dictiterobject *di = (dictiterobject *)self;
/* bpo-31095: UnTrack is needed before calling any callbacks */
_PyObject_GC_UNTRACK(di);
Py_XDECREF(di->di_dict);
@ -4138,16 +4145,18 @@ dictiter_dealloc(dictiterobject *di)
}
static int
dictiter_traverse(dictiterobject *di, visitproc visit, void *arg)
dictiter_traverse(PyObject *self, visitproc visit, void *arg)
{
dictiterobject *di = (dictiterobject *)self;
Py_VISIT(di->di_dict);
Py_VISIT(di->di_result);
return 0;
}
static PyObject *
dictiter_len(dictiterobject *di, PyObject *Py_UNUSED(ignored))
dictiter_len(PyObject *self, PyObject *Py_UNUSED(ignored))
{
dictiterobject *di = (dictiterobject *)self;
Py_ssize_t len = 0;
if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)
len = di->len;
@ -4158,21 +4167,22 @@ PyDoc_STRVAR(length_hint_doc,
"Private method returning an estimate of len(list(it)).");
static PyObject *
dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored));
dictiter_reduce(PyObject *di, PyObject *Py_UNUSED(ignored));
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
static PyMethodDef dictiter_methods[] = {
{"__length_hint__", _PyCFunction_CAST(dictiter_len), METH_NOARGS,
{"__length_hint__", dictiter_len, METH_NOARGS,
length_hint_doc},
{"__reduce__", _PyCFunction_CAST(dictiter_reduce), METH_NOARGS,
{"__reduce__", dictiter_reduce, METH_NOARGS,
reduce_doc},
{NULL, NULL} /* sentinel */
};
static PyObject*
dictiter_iternextkey(dictiterobject *di)
dictiter_iternextkey(PyObject *self)
{
dictiterobject *di = (dictiterobject *)self;
PyObject *key;
Py_ssize_t i;
PyDictKeysObject *k;
@ -4244,7 +4254,7 @@ PyTypeObject PyDictIterKey_Type = {
sizeof(dictiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dictiter_dealloc, /* tp_dealloc */
dictiter_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
@ -4261,19 +4271,20 @@ PyTypeObject PyDictIterKey_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)dictiter_traverse, /* tp_traverse */
dictiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)dictiter_iternextkey, /* tp_iternext */
dictiter_iternextkey, /* tp_iternext */
dictiter_methods, /* tp_methods */
0,
};
static PyObject *
dictiter_iternextvalue(dictiterobject *di)
dictiter_iternextvalue(PyObject *self)
{
dictiterobject *di = (dictiterobject *)self;
PyObject *value;
Py_ssize_t i;
PyDictObject *d = di->di_dict;
@ -4343,7 +4354,7 @@ PyTypeObject PyDictIterValue_Type = {
sizeof(dictiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dictiter_dealloc, /* tp_dealloc */
dictiter_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
@ -4360,19 +4371,20 @@ PyTypeObject PyDictIterValue_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)dictiter_traverse, /* tp_traverse */
dictiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)dictiter_iternextvalue, /* tp_iternext */
dictiter_iternextvalue, /* tp_iternext */
dictiter_methods, /* tp_methods */
0,
};
static PyObject *
dictiter_iternextitem(dictiterobject *di)
dictiter_iternextitem(PyObject *self)
{
dictiterobject *di = (dictiterobject *)self;
PyObject *key, *value, *result;
Py_ssize_t i;
PyDictObject *d = di->di_dict;
@ -4467,7 +4479,7 @@ PyTypeObject PyDictIterItem_Type = {
sizeof(dictiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dictiter_dealloc, /* tp_dealloc */
dictiter_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
@ -4484,12 +4496,12 @@ PyTypeObject PyDictIterItem_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)dictiter_traverse, /* tp_traverse */
dictiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)dictiter_iternextitem, /* tp_iternext */
dictiter_iternextitem, /* tp_iternext */
dictiter_methods, /* tp_methods */
0,
};
@ -4498,8 +4510,9 @@ PyTypeObject PyDictIterItem_Type = {
/* dictreviter */
static PyObject *
dictreviter_iternext(dictiterobject *di)
dictreviter_iternext(PyObject *self)
{
dictiterobject *di = (dictiterobject *)self;
PyDictObject *d = di->di_dict;
if (d == NULL) {
@ -4600,11 +4613,11 @@ PyTypeObject PyDictRevIterKey_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"dict_reversekeyiterator",
sizeof(dictiterobject),
.tp_dealloc = (destructor)dictiter_dealloc,
.tp_dealloc = dictiter_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_traverse = (traverseproc)dictiter_traverse,
.tp_traverse = dictiter_traverse,
.tp_iter = PyObject_SelfIter,
.tp_iternext = (iternextfunc)dictreviter_iternext,
.tp_iternext = dictreviter_iternext,
.tp_methods = dictiter_methods
};
@ -4624,8 +4637,9 @@ dict___reversed___impl(PyDictObject *self)
}
static PyObject *
dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored))
dictiter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
{
dictiterobject *di = (dictiterobject *)self;
/* copy the iterator state */
dictiterobject tmp = *di;
Py_XINCREF(tmp.di_dict);
@ -4641,11 +4655,11 @@ PyTypeObject PyDictRevIterItem_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"dict_reverseitemiterator",
sizeof(dictiterobject),
.tp_dealloc = (destructor)dictiter_dealloc,
.tp_dealloc = dictiter_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_traverse = (traverseproc)dictiter_traverse,
.tp_traverse = dictiter_traverse,
.tp_iter = PyObject_SelfIter,
.tp_iternext = (iternextfunc)dictreviter_iternext,
.tp_iternext = dictreviter_iternext,
.tp_methods = dictiter_methods
};
@ -4653,11 +4667,11 @@ PyTypeObject PyDictRevIterValue_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"dict_reversevalueiterator",
sizeof(dictiterobject),
.tp_dealloc = (destructor)dictiter_dealloc,
.tp_dealloc = dictiter_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_traverse = (traverseproc)dictiter_traverse,
.tp_traverse = dictiter_traverse,
.tp_iter = PyObject_SelfIter,
.tp_iternext = (iternextfunc)dictreviter_iternext,
.tp_iternext = dictreviter_iternext,
.tp_methods = dictiter_methods
};
@ -4668,8 +4682,9 @@ PyTypeObject PyDictRevIterValue_Type = {
/* The instance lay-out is the same for all three; but the type differs. */
static void
dictview_dealloc(_PyDictViewObject *dv)
dictview_dealloc(PyObject *self)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
/* bpo-31095: UnTrack is needed before calling any callbacks */
_PyObject_GC_UNTRACK(dv);
Py_XDECREF(dv->dv_dict);
@ -4677,15 +4692,17 @@ dictview_dealloc(_PyDictViewObject *dv)
}
static int
dictview_traverse(_PyDictViewObject *dv, visitproc visit, void *arg)
dictview_traverse(PyObject *self, visitproc visit, void *arg)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
Py_VISIT(dv->dv_dict);
return 0;
}
static Py_ssize_t
dictview_len(_PyDictViewObject *dv)
dictview_len(PyObject *self)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
Py_ssize_t len = 0;
if (dv->dv_dict != NULL)
len = dv->dv_dict->ma_used;
@ -4825,8 +4842,9 @@ dictview_richcompare(PyObject *self, PyObject *other, int op)
}
static PyObject *
dictview_repr(_PyDictViewObject *dv)
dictview_repr(PyObject *self)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
PyObject *seq;
PyObject *result = NULL;
Py_ssize_t rc;
@ -4850,8 +4868,9 @@ Done:
/*** dict_keys ***/
static PyObject *
dictkeys_iter(_PyDictViewObject *dv)
dictkeys_iter(PyObject *self)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
if (dv->dv_dict == NULL) {
Py_RETURN_NONE;
}
@ -4859,22 +4878,23 @@ dictkeys_iter(_PyDictViewObject *dv)
}
static int
dictkeys_contains(_PyDictViewObject *dv, PyObject *obj)
dictkeys_contains(PyObject *self, PyObject *obj)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
if (dv->dv_dict == NULL)
return 0;
return PyDict_Contains((PyObject *)dv->dv_dict, obj);
}
static PySequenceMethods dictkeys_as_sequence = {
(lenfunc)dictview_len, /* sq_length */
dictview_len, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)dictkeys_contains, /* sq_contains */
dictkeys_contains, /* sq_contains */
};
// Create a set object from dictviews object.
@ -4914,7 +4934,7 @@ dictviews_sub(PyObject *self, PyObject *other)
}
static int
dictitems_contains(_PyDictViewObject *dv, PyObject *obj);
dictitems_contains(PyObject *dv, PyObject *obj);
PyObject *
_PyDictView_Intersect(PyObject* self, PyObject *other)
@ -4924,7 +4944,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other)
PyObject *key;
Py_ssize_t len_self;
int rv;
int (*dict_contains)(_PyDictViewObject *, PyObject *);
objobjproc dict_contains;
/* Python interpreter swaps parameters when dict view
is on right side of & */
@ -4934,7 +4954,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other)
self = tmp;
}
len_self = dictview_len((_PyDictViewObject *)self);
len_self = dictview_len(self);
/* if other is a set and self is smaller than other,
reuse set intersection logic */
@ -4946,7 +4966,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other)
/* if other is another dict view, and it is bigger than self,
swap them */
if (PyDictViewSet_Check(other)) {
Py_ssize_t len_other = dictview_len((_PyDictViewObject *)other);
Py_ssize_t len_other = dictview_len(other);
if (len_other > len_self) {
PyObject *tmp = other;
other = self;
@ -4976,7 +4996,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other)
}
while ((key = PyIter_Next(it)) != NULL) {
rv = dict_contains((_PyDictViewObject *)self, key);
rv = dict_contains(self, key);
if (rv < 0) {
goto error;
}
@ -5150,7 +5170,7 @@ dictviews_isdisjoint(PyObject *self, PyObject *other)
PyObject *item = NULL;
if (self == other) {
if (dictview_len((_PyDictViewObject *)self) == 0)
if (dictview_len(self) == 0)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
@ -5159,7 +5179,7 @@ dictviews_isdisjoint(PyObject *self, PyObject *other)
/* Iterate over the shorter object (only if other is a set,
* because PySequence_Contains may be expensive otherwise): */
if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) {
Py_ssize_t len_self = dictview_len((_PyDictViewObject *)self);
Py_ssize_t len_self = dictview_len(self);
Py_ssize_t len_other = PyObject_Size(other);
if (len_other == -1)
return NULL;
@ -5197,15 +5217,15 @@ dictviews_isdisjoint(PyObject *self, PyObject *other)
PyDoc_STRVAR(isdisjoint_doc,
"Return True if the view and the given iterable have a null intersection.");
static PyObject* dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
static PyObject* dictkeys_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored));
PyDoc_STRVAR(reversed_keys_doc,
"Return a reverse iterator over the dict keys.");
static PyMethodDef dictkeys_methods[] = {
{"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O,
{"isdisjoint", dictviews_isdisjoint, METH_O,
isdisjoint_doc},
{"__reversed__", _PyCFunction_CAST(dictkeys_reversed), METH_NOARGS,
{"__reversed__", dictkeys_reversed, METH_NOARGS,
reversed_keys_doc},
{NULL, NULL} /* sentinel */
};
@ -5216,12 +5236,12 @@ PyTypeObject PyDictKeys_Type = {
sizeof(_PyDictViewObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dictview_dealloc, /* tp_dealloc */
dictview_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)dictview_repr, /* tp_repr */
dictview_repr, /* tp_repr */
&dictviews_as_number, /* tp_as_number */
&dictkeys_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
@ -5233,11 +5253,11 @@ PyTypeObject PyDictKeys_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)dictview_traverse, /* tp_traverse */
dictview_traverse, /* tp_traverse */
0, /* tp_clear */
dictview_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)dictkeys_iter, /* tp_iter */
dictkeys_iter, /* tp_iter */
0, /* tp_iternext */
dictkeys_methods, /* tp_methods */
.tp_getset = dictview_getset,
@ -5250,8 +5270,9 @@ dictkeys_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
}
static PyObject *
dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
dictkeys_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
if (dv->dv_dict == NULL) {
Py_RETURN_NONE;
}
@ -5261,8 +5282,9 @@ dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
/*** dict_items ***/
static PyObject *
dictitems_iter(_PyDictViewObject *dv)
dictitems_iter(PyObject *self)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
if (dv->dv_dict == NULL) {
Py_RETURN_NONE;
}
@ -5270,8 +5292,9 @@ dictitems_iter(_PyDictViewObject *dv)
}
static int
dictitems_contains(_PyDictViewObject *dv, PyObject *obj)
dictitems_contains(PyObject *self, PyObject *obj)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
int result;
PyObject *key, *value, *found;
if (dv->dv_dict == NULL)
@ -5289,25 +5312,25 @@ dictitems_contains(_PyDictViewObject *dv, PyObject *obj)
}
static PySequenceMethods dictitems_as_sequence = {
(lenfunc)dictview_len, /* sq_length */
dictview_len, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)dictitems_contains, /* sq_contains */
dictitems_contains, /* sq_contains */
};
static PyObject* dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
static PyObject* dictitems_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored));
PyDoc_STRVAR(reversed_items_doc,
"Return a reverse iterator over the dict items.");
static PyMethodDef dictitems_methods[] = {
{"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O,
{"isdisjoint", dictviews_isdisjoint, METH_O,
isdisjoint_doc},
{"__reversed__", (PyCFunction)dictitems_reversed, METH_NOARGS,
{"__reversed__", dictitems_reversed, METH_NOARGS,
reversed_items_doc},
{NULL, NULL} /* sentinel */
};
@ -5318,12 +5341,12 @@ PyTypeObject PyDictItems_Type = {
sizeof(_PyDictViewObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dictview_dealloc, /* tp_dealloc */
dictview_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)dictview_repr, /* tp_repr */
dictview_repr, /* tp_repr */
&dictviews_as_number, /* tp_as_number */
&dictitems_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
@ -5335,11 +5358,11 @@ PyTypeObject PyDictItems_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)dictview_traverse, /* tp_traverse */
dictview_traverse, /* tp_traverse */
0, /* tp_clear */
dictview_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)dictitems_iter, /* tp_iter */
dictitems_iter, /* tp_iter */
0, /* tp_iternext */
dictitems_methods, /* tp_methods */
.tp_getset = dictview_getset,
@ -5352,8 +5375,9 @@ dictitems_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
}
static PyObject *
dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
dictitems_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
if (dv->dv_dict == NULL) {
Py_RETURN_NONE;
}
@ -5363,8 +5387,9 @@ dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
/*** dict_values ***/
static PyObject *
dictvalues_iter(_PyDictViewObject *dv)
dictvalues_iter(PyObject *self)
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
if (dv->dv_dict == NULL) {
Py_RETURN_NONE;
}
@ -5372,7 +5397,7 @@ dictvalues_iter(_PyDictViewObject *dv)
}
static PySequenceMethods dictvalues_as_sequence = {
(lenfunc)dictview_len, /* sq_length */
dictview_len, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
@ -5382,13 +5407,13 @@ static PySequenceMethods dictvalues_as_sequence = {
(objobjproc)0, /* sq_contains */
};
static PyObject* dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
static PyObject* dictvalues_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored));
PyDoc_STRVAR(reversed_values_doc,
"Return a reverse iterator over the dict values.");
static PyMethodDef dictvalues_methods[] = {
{"__reversed__", (PyCFunction)dictvalues_reversed, METH_NOARGS,
{"__reversed__", dictvalues_reversed, METH_NOARGS,
reversed_values_doc},
{NULL, NULL} /* sentinel */
};
@ -5399,12 +5424,12 @@ PyTypeObject PyDictValues_Type = {
sizeof(_PyDictViewObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dictview_dealloc, /* tp_dealloc */
dictview_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)dictview_repr, /* tp_repr */
dictview_repr, /* tp_repr */
0, /* tp_as_number */
&dictvalues_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
@ -5416,11 +5441,11 @@ PyTypeObject PyDictValues_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)dictview_traverse, /* tp_traverse */
dictview_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)dictvalues_iter, /* tp_iter */
dictvalues_iter, /* tp_iter */
0, /* tp_iternext */
dictvalues_methods, /* tp_methods */
.tp_getset = dictview_getset,
@ -5433,8 +5458,9 @@ dictvalues_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
}
static PyObject *
dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
dictvalues_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
{
_PyDictViewObject *dv = (_PyDictViewObject *)self;
if (dv->dv_dict == NULL) {
Py_RETURN_NONE;
}