Coverage Report

Created: 2026-02-26 06:53

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