Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Objects/classobject.c
Line
Count
Source (jump to first uncovered line)
1
/* Class object implementation (dead now except for methods) */
2
3
#include "Python.h"
4
#include "pycore_call.h"          // _PyObject_VectorcallTstate()
5
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
6
#include "pycore_freelist.h"
7
#include "pycore_object.h"
8
#include "pycore_pyerrors.h"
9
#include "pycore_pystate.h"       // _PyThreadState_GET()
10
#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
11
12
13
#include "clinic/classobject.c.h"
14
15
23.4M
#define _PyMethodObject_CAST(op) _Py_CAST(PyMethodObject*, (op))
16
0
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
17
18
/*[clinic input]
19
class method "PyMethodObject *" "&PyMethod_Type"
20
[clinic start generated code]*/
21
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b16e47edf6107c23]*/
22
23
24
PyObject *
25
PyMethod_Function(PyObject *im)
26
0
{
27
0
    if (!PyMethod_Check(im)) {
28
0
        PyErr_BadInternalCall();
29
0
        return NULL;
30
0
    }
31
0
    return ((PyMethodObject *)im)->im_func;
32
0
}
33
34
PyObject *
35
PyMethod_Self(PyObject *im)
36
0
{
37
0
    if (!PyMethod_Check(im)) {
38
0
        PyErr_BadInternalCall();
39
0
        return NULL;
40
0
    }
41
0
    return ((PyMethodObject *)im)->im_self;
42
0
}
43
44
45
static PyObject *
46
method_vectorcall(PyObject *method, PyObject *const *args,
47
                  size_t nargsf, PyObject *kwnames)
48
22.4M
{
49
22.4M
    assert(Py_IS_TYPE(method, &PyMethod_Type));
50
51
22.4M
    PyThreadState *tstate = _PyThreadState_GET();
52
22.4M
    PyObject *self = PyMethod_GET_SELF(method);
53
22.4M
    PyObject *func = PyMethod_GET_FUNCTION(method);
54
22.4M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
55
22.4M
    assert(nargs == 0 || args[nargs-1]);
56
57
22.4M
    PyObject *result;
58
22.4M
    if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
59
        /* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */
60
719k
        PyObject **newargs = (PyObject**)args - 1;
61
719k
        nargs += 1;
62
719k
        PyObject *tmp = newargs[0];
63
719k
        newargs[0] = self;
64
719k
        assert(newargs[nargs-1]);
65
719k
        result = _PyObject_VectorcallTstate(tstate, func, newargs,
66
719k
                                            nargs, kwnames);
67
719k
        newargs[0] = tmp;
68
719k
    }
69
21.7M
    else {
70
21.7M
        Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
71
21.7M
        Py_ssize_t totalargs = nargs + nkwargs;
72
21.7M
        if (totalargs == 0) {
73
4
            return _PyObject_VectorcallTstate(tstate, func, &self, 1, NULL);
74
4
        }
75
76
21.7M
        PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK];
77
21.7M
        PyObject **newargs;
78
21.7M
        if (totalargs <= (Py_ssize_t)Py_ARRAY_LENGTH(newargs_stack) - 1) {
79
21.7M
            newargs = newargs_stack;
80
21.7M
        }
81
1.53k
        else {
82
1.53k
            newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
83
1.53k
            if (newargs == NULL) {
84
0
                _PyErr_NoMemory(tstate);
85
0
                return NULL;
86
0
            }
87
1.53k
        }
88
        /* use borrowed references */
89
21.7M
        newargs[0] = self;
90
        /* bpo-37138: since totalargs > 0, it's impossible that args is NULL.
91
         * We need this, since calling memcpy() with a NULL pointer is
92
         * undefined behaviour. */
93
21.7M
        assert(args != NULL);
94
21.7M
        memcpy(newargs + 1, args, totalargs * sizeof(PyObject *));
95
21.7M
        result = _PyObject_VectorcallTstate(tstate, func,
96
21.7M
                                            newargs, nargs+1, kwnames);
97
21.7M
        if (newargs != newargs_stack) {
98
1.53k
            PyMem_Free(newargs);
99
1.53k
        }
100
21.7M
    }
101
22.4M
    return result;
102
22.4M
}
103
104
105
/* Method objects are used for bound instance methods returned by
106
   instancename.methodname. ClassName.methodname returns an ordinary
107
   function.
108
*/
109
110
PyObject *
111
PyMethod_New(PyObject *func, PyObject *self)
112
23.2M
{
113
23.2M
    if (self == NULL) {
114
0
        PyErr_BadInternalCall();
115
0
        return NULL;
116
0
    }
117
23.2M
    PyMethodObject *im = _Py_FREELIST_POP(PyMethodObject, pymethodobjects);
118
23.2M
    if (im == NULL) {
119
120k
        im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
120
120k
        if (im == NULL) {
121
0
            return NULL;
122
0
        }
123
120k
    }
124
23.2M
    im->im_weakreflist = NULL;
125
23.2M
    im->im_func = Py_NewRef(func);
126
23.2M
    im->im_self = Py_NewRef(self);
127
23.2M
    im->vectorcall = method_vectorcall;
128
23.2M
    _PyObject_GC_TRACK(im);
129
23.2M
    return (PyObject *)im;
130
23.2M
}
131
132
/*[clinic input]
133
method.__reduce__
134
[clinic start generated code]*/
135
136
static PyObject *
137
method___reduce___impl(PyMethodObject *self)
138
/*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/
139
0
{
140
0
    PyObject *funcself = PyMethod_GET_SELF(self);
141
0
    PyObject *func = PyMethod_GET_FUNCTION(self);
142
0
    PyObject *funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
143
0
    if (funcname == NULL) {
144
0
        return NULL;
145
0
    }
146
0
    return Py_BuildValue(
147
0
            "N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname);
148
0
}
149
150
static PyMethodDef method_methods[] = {
151
    METHOD___REDUCE___METHODDEF
152
    {NULL, NULL}
153
};
154
155
/* Descriptors for PyMethod attributes */
156
157
/* im_func and im_self are stored in the PyMethod object */
158
159
#define MO_OFF(x) offsetof(PyMethodObject, x)
160
161
static PyMemberDef method_memberlist[] = {
162
    {"__func__", _Py_T_OBJECT, MO_OFF(im_func), Py_READONLY,
163
     "the function (or other callable) implementing a method"},
164
    {"__self__", _Py_T_OBJECT, MO_OFF(im_self), Py_READONLY,
165
     "the instance to which a method is bound"},
166
    {NULL}      /* Sentinel */
167
};
168
169
/* Christian Tismer argued convincingly that method attributes should
170
   (nearly) always override function attributes.
171
   The one exception is __doc__; there's a default __doc__ which
172
   should only be used for the class, not for instances */
173
174
static PyObject *
175
method_get_doc(PyObject *self, void *context)
176
0
{
177
0
    PyMethodObject *im = _PyMethodObject_CAST(self);
178
0
    return PyObject_GetAttr(im->im_func, &_Py_ID(__doc__));
179
0
}
180
181
static PyGetSetDef method_getset[] = {
182
    {"__doc__", method_get_doc, NULL, NULL},
183
    {0}
184
};
185
186
static PyObject *
187
method_getattro(PyObject *obj, PyObject *name)
188
0
{
189
0
    PyMethodObject *im = (PyMethodObject *)obj;
190
0
    PyTypeObject *tp = Py_TYPE(obj);
191
0
    PyObject *descr = NULL;
192
193
0
    {
194
0
        if (!_PyType_IsReady(tp)) {
195
0
            if (PyType_Ready(tp) < 0)
196
0
                return NULL;
197
0
        }
198
0
        descr = _PyType_LookupRef(tp, name);
199
0
    }
200
201
0
    if (descr != NULL) {
202
0
        descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
203
0
        if (f != NULL) {
204
0
            PyObject *res = f(descr, obj, (PyObject *)Py_TYPE(obj));
205
0
            Py_DECREF(descr);
206
0
            return res;
207
0
        }
208
0
        else {
209
0
            return descr;
210
0
        }
211
0
    }
212
213
0
    return PyObject_GetAttr(im->im_func, name);
214
0
}
215
216
/*[clinic input]
217
@classmethod
218
method.__new__ as method_new
219
    function: object
220
    instance: object
221
    /
222
223
Create a bound instance method object.
224
[clinic start generated code]*/
225
226
static PyObject *
227
method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance)
228
/*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/
229
0
{
230
0
    if (!PyCallable_Check(function)) {
231
0
        PyErr_SetString(PyExc_TypeError,
232
0
                        "first argument must be callable");
233
0
        return NULL;
234
0
    }
235
0
    if (instance == NULL || instance == Py_None) {
236
0
        PyErr_SetString(PyExc_TypeError,
237
0
            "instance must not be None");
238
0
        return NULL;
239
0
    }
240
241
0
    return PyMethod_New(function, instance);
242
0
}
243
244
static void
245
method_dealloc(PyObject *self)
246
23.2M
{
247
23.2M
    PyMethodObject *im = _PyMethodObject_CAST(self);
248
23.2M
    _PyObject_GC_UNTRACK(im);
249
23.2M
    FT_CLEAR_WEAKREFS(self, im->im_weakreflist);
250
23.2M
    Py_DECREF(im->im_func);
251
23.2M
    Py_XDECREF(im->im_self);
252
23.2M
    assert(Py_IS_TYPE(self, &PyMethod_Type));
253
23.2M
    _Py_FREELIST_FREE(pymethodobjects, (PyObject *)im, PyObject_GC_Del);
254
23.2M
}
255
256
static PyObject *
257
method_richcompare(PyObject *self, PyObject *other, int op)
258
0
{
259
0
    PyMethodObject *a, *b;
260
0
    PyObject *res;
261
0
    int eq;
262
263
0
    if ((op != Py_EQ && op != Py_NE) ||
264
0
        !PyMethod_Check(self) ||
265
0
        !PyMethod_Check(other))
266
0
    {
267
0
        Py_RETURN_NOTIMPLEMENTED;
268
0
    }
269
0
    a = (PyMethodObject *)self;
270
0
    b = (PyMethodObject *)other;
271
0
    eq = PyObject_RichCompareBool(a->im_func, b->im_func, Py_EQ);
272
0
    if (eq == 1) {
273
0
        eq = (a->im_self == b->im_self);
274
0
    }
275
0
    else if (eq < 0)
276
0
        return NULL;
277
0
    if (op == Py_EQ)
278
0
        res = eq ? Py_True : Py_False;
279
0
    else
280
0
        res = eq ? Py_False : Py_True;
281
0
    return Py_NewRef(res);
282
0
}
283
284
static PyObject *
285
method_repr(PyObject *op)
286
0
{
287
0
    PyMethodObject *a = _PyMethodObject_CAST(op);
288
0
    PyObject *self = a->im_self;
289
0
    PyObject *func = a->im_func;
290
0
    PyObject *funcname, *result;
291
0
    const char *defname = "?";
292
293
0
    if (PyObject_GetOptionalAttr(func, &_Py_ID(__qualname__), &funcname) < 0 ||
294
0
        (funcname == NULL &&
295
0
         PyObject_GetOptionalAttr(func, &_Py_ID(__name__), &funcname) < 0))
296
0
    {
297
0
        return NULL;
298
0
    }
299
300
0
    if (funcname != NULL && !PyUnicode_Check(funcname)) {
301
0
        Py_SETREF(funcname, NULL);
302
0
    }
303
304
    /* XXX Shouldn't use repr()/%R here! */
305
0
    result = PyUnicode_FromFormat("<bound method %V of %R>",
306
0
                                  funcname, defname, self);
307
308
0
    Py_XDECREF(funcname);
309
0
    return result;
310
0
}
311
312
static Py_hash_t
313
method_hash(PyObject *self)
314
0
{
315
0
    PyMethodObject *a = _PyMethodObject_CAST(self);
316
0
    Py_hash_t x = PyObject_GenericHash(a->im_self);
317
0
    Py_hash_t y = PyObject_Hash(a->im_func);
318
0
    if (y == -1) {
319
0
        return -1;
320
0
    }
321
322
0
    x = x ^ y;
323
0
    if (x == -1) {
324
0
        x = -2;
325
0
    }
326
0
    return x;
327
0
}
328
329
static int
330
method_traverse(PyObject *self, visitproc visit, void *arg)
331
279k
{
332
279k
    PyMethodObject *im = _PyMethodObject_CAST(self);
333
279k
    Py_VISIT(im->im_func);
334
279k
    Py_VISIT(im->im_self);
335
279k
    return 0;
336
279k
}
337
338
static PyObject *
339
method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)
340
11
{
341
11
    Py_INCREF(meth);
342
11
    return meth;
343
11
}
344
345
PyTypeObject PyMethod_Type = {
346
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
347
    .tp_name = "method",
348
    .tp_basicsize = sizeof(PyMethodObject),
349
    .tp_dealloc = method_dealloc,
350
    .tp_vectorcall_offset = offsetof(PyMethodObject, vectorcall),
351
    .tp_repr = method_repr,
352
    .tp_hash = method_hash,
353
    .tp_call = PyVectorcall_Call,
354
    .tp_getattro = method_getattro,
355
    .tp_setattro = PyObject_GenericSetAttr,
356
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
357
                Py_TPFLAGS_HAVE_VECTORCALL,
358
    .tp_doc = method_new__doc__,
359
    .tp_traverse = method_traverse,
360
    .tp_richcompare = method_richcompare,
361
    .tp_weaklistoffset = offsetof(PyMethodObject, im_weakreflist),
362
    .tp_methods = method_methods,
363
    .tp_members = method_memberlist,
364
    .tp_getset = method_getset,
365
    .tp_descr_get = method_descr_get,
366
    .tp_new = method_new,
367
};
368
369
/* ------------------------------------------------------------------------
370
 * instance method
371
 */
372
373
/*[clinic input]
374
class instancemethod "PyInstanceMethodObject *" "&PyInstanceMethod_Type"
375
[clinic start generated code]*/
376
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28c9762a9016f4d2]*/
377
378
PyObject *
379
0
PyInstanceMethod_New(PyObject *func) {
380
0
    PyInstanceMethodObject *method;
381
0
    method = PyObject_GC_New(PyInstanceMethodObject,
382
0
                             &PyInstanceMethod_Type);
383
0
    if (method == NULL) return NULL;
384
0
    method->func = Py_NewRef(func);
385
0
    _PyObject_GC_TRACK(method);
386
0
    return (PyObject *)method;
387
0
}
388
389
PyObject *
390
PyInstanceMethod_Function(PyObject *im)
391
0
{
392
0
    if (!PyInstanceMethod_Check(im)) {
393
0
        PyErr_BadInternalCall();
394
0
        return NULL;
395
0
    }
396
0
    return PyInstanceMethod_GET_FUNCTION(im);
397
0
}
398
399
#define IMO_OFF(x) offsetof(PyInstanceMethodObject, x)
400
401
static PyMemberDef instancemethod_memberlist[] = {
402
    {"__func__", _Py_T_OBJECT, IMO_OFF(func), Py_READONLY,
403
     "the function (or other callable) implementing a method"},
404
    {NULL}      /* Sentinel */
405
};
406
407
static PyObject *
408
instancemethod_get_doc(PyObject *self, void *context)
409
0
{
410
0
    return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self),
411
0
                            &_Py_ID(__doc__));
412
0
}
413
414
static PyGetSetDef instancemethod_getset[] = {
415
    {"__doc__", instancemethod_get_doc, NULL, NULL},
416
    {0}
417
};
418
419
static PyObject *
420
instancemethod_getattro(PyObject *self, PyObject *name)
421
0
{
422
0
    PyTypeObject *tp = Py_TYPE(self);
423
0
    PyObject *descr = NULL;
424
425
0
    if (!_PyType_IsReady(tp)) {
426
0
        if (PyType_Ready(tp) < 0)
427
0
            return NULL;
428
0
    }
429
0
    descr = _PyType_LookupRef(tp, name);
430
431
0
    if (descr != NULL) {
432
0
        descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
433
0
        if (f != NULL) {
434
0
            PyObject *res = f(descr, self, (PyObject *)Py_TYPE(self));
435
0
            Py_DECREF(descr);
436
0
            return res;
437
0
        }
438
0
        else {
439
0
            return descr;
440
0
        }
441
0
    }
442
443
0
    return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), name);
444
0
}
445
446
static void
447
0
instancemethod_dealloc(PyObject *self) {
448
0
    _PyObject_GC_UNTRACK(self);
449
0
    Py_DECREF(PyInstanceMethod_GET_FUNCTION(self));
450
0
    PyObject_GC_Del(self);
451
0
}
452
453
static int
454
0
instancemethod_traverse(PyObject *self, visitproc visit, void *arg) {
455
0
    Py_VISIT(PyInstanceMethod_GET_FUNCTION(self));
456
0
    return 0;
457
0
}
458
459
static PyObject *
460
instancemethod_call(PyObject *self, PyObject *arg, PyObject *kw)
461
0
{
462
0
    return PyObject_Call(PyInstanceMethod_GET_FUNCTION(self), arg, kw);
463
0
}
464
465
static PyObject *
466
0
instancemethod_descr_get(PyObject *descr, PyObject *obj, PyObject *type) {
467
0
    PyObject *func = PyInstanceMethod_GET_FUNCTION(descr);
468
0
    if (obj == NULL) {
469
0
        return Py_NewRef(func);
470
0
    }
471
0
    else
472
0
        return PyMethod_New(func, obj);
473
0
}
474
475
static PyObject *
476
instancemethod_richcompare(PyObject *self, PyObject *other, int op)
477
0
{
478
0
    PyInstanceMethodObject *a, *b;
479
0
    PyObject *res;
480
0
    int eq;
481
482
0
    if ((op != Py_EQ && op != Py_NE) ||
483
0
        !PyInstanceMethod_Check(self) ||
484
0
        !PyInstanceMethod_Check(other))
485
0
    {
486
0
        Py_RETURN_NOTIMPLEMENTED;
487
0
    }
488
0
    a = (PyInstanceMethodObject *)self;
489
0
    b = (PyInstanceMethodObject *)other;
490
0
    eq = PyObject_RichCompareBool(a->func, b->func, Py_EQ);
491
0
    if (eq < 0)
492
0
        return NULL;
493
0
    if (op == Py_EQ)
494
0
        res = eq ? Py_True : Py_False;
495
0
    else
496
0
        res = eq ? Py_False : Py_True;
497
0
    return Py_NewRef(res);
498
0
}
499
500
static PyObject *
501
instancemethod_repr(PyObject *self)
502
0
{
503
0
    PyObject *func = PyInstanceMethod_Function(self);
504
0
    PyObject *funcname, *result;
505
0
    const char *defname = "?";
506
507
0
    if (func == NULL) {
508
0
        PyErr_BadInternalCall();
509
0
        return NULL;
510
0
    }
511
512
0
    if (PyObject_GetOptionalAttr(func, &_Py_ID(__name__), &funcname) < 0) {
513
0
        return NULL;
514
0
    }
515
0
    if (funcname != NULL && !PyUnicode_Check(funcname)) {
516
0
        Py_SETREF(funcname, NULL);
517
0
    }
518
519
0
    result = PyUnicode_FromFormat("<instancemethod %V at %p>",
520
0
                                  funcname, defname, self);
521
522
0
    Py_XDECREF(funcname);
523
0
    return result;
524
0
}
525
526
/*[clinic input]
527
@classmethod
528
instancemethod.__new__ as instancemethod_new
529
    function: object
530
    /
531
532
Bind a function to a class.
533
[clinic start generated code]*/
534
535
static PyObject *
536
instancemethod_new_impl(PyTypeObject *type, PyObject *function)
537
/*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/
538
0
{
539
0
    if (!PyCallable_Check(function)) {
540
0
        PyErr_SetString(PyExc_TypeError,
541
0
                        "first argument must be callable");
542
0
        return NULL;
543
0
    }
544
545
0
    return PyInstanceMethod_New(function);
546
0
}
547
548
PyTypeObject PyInstanceMethod_Type = {
549
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
550
    .tp_name = "instancemethod",
551
    .tp_basicsize = sizeof(PyInstanceMethodObject),
552
    .tp_dealloc = instancemethod_dealloc,
553
    .tp_repr = instancemethod_repr,
554
    .tp_call = instancemethod_call,
555
    .tp_getattro = instancemethod_getattro,
556
    .tp_setattro = PyObject_GenericSetAttr,
557
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
558
    .tp_doc = instancemethod_new__doc__,
559
    .tp_traverse = instancemethod_traverse,
560
    .tp_richcompare = instancemethod_richcompare,
561
    .tp_members = instancemethod_memberlist,
562
    .tp_getset = instancemethod_getset,
563
    .tp_descr_get = instancemethod_descr_get,
564
    .tp_new = instancemethod_new,
565
};