@@ -331,7 +331,7 @@ def emit_line() -> None:
331331 if emitter .capi_version < (3 , 12 ):
332332 fields ["tp_dictoffset" ] = base_size
333333 fields ["tp_weaklistoffset" ] = weak_offset
334- elif cl .supports_weakref :
334+ elif cl .supports_weakref and emitter . capi_version < ( 3 , 12 ) :
335335 # __weakref__ lives right after the struct
336336 # TODO: It should get a member in the struct instead of doing this nonsense.
337337 emitter .emit_lines (
@@ -340,10 +340,11 @@ def emit_line() -> None:
340340 "{0}" ,
341341 "};" ,
342342 )
343- if emitter .capi_version < (3 , 12 ):
344- # versions >= 3.12 set Py_TPFLAGS_MANAGED_WEAKREF flag instead
345- # https://docs.python.org/3.12/extending/newtypes.html#weak-reference-support
346- fields ["tp_weaklistoffset" ] = base_size
343+ fields ["tp_members" ] = members_name
344+ fields ["tp_basicsize" ] = f"{ base_size } + sizeof(PyObject *)"
345+ # versions >= 3.12 set Py_TPFLAGS_MANAGED_WEAKREF flag instead
346+ # https://docs.python.org/3.12/extending/newtypes.html#weak-reference-support
347+ fields ["tp_weaklistoffset" ] = base_size
347348 else :
348349 fields ["tp_basicsize" ] = base_size
349350
@@ -902,6 +903,12 @@ def generate_traverse_for_class(cl: ClassIR, func_name: str, emitter: Emitter) -
902903 f"*((PyObject **)((char *)self + sizeof(PyObject *) + sizeof({ struct_name } )))" ,
903904 object_rprimitive ,
904905 )
906+ elif cl .supports_weakref and emitter .capi_version < (3 , 12 ):
907+ struct_name = cl .struct_name (emitter .names )
908+ # __weakref__ lives right after the struct
909+ emitter .emit_gc_visit (
910+ f"*((PyObject **)((char *)self + sizeof({ struct_name } )))" , object_rprimitive
911+ )
905912 emitter .emit_line ("return 0;" )
906913 emitter .emit_line ("}" )
907914
@@ -925,6 +932,12 @@ def generate_clear_for_class(cl: ClassIR, func_name: str, emitter: Emitter) -> N
925932 f"*((PyObject **)((char *)self + sizeof(PyObject *) + sizeof({ struct_name } )))" ,
926933 object_rprimitive ,
927934 )
935+ elif cl .supports_weakref and emitter .capi_version < (3 , 12 ):
936+ struct_name = cl .struct_name (emitter .names )
937+ # __weakref__ lives right after the struct
938+ emitter .emit_gc_clear (
939+ f"*((PyObject **)((char *)self + sizeof({ struct_name } )))" , object_rprimitive
940+ )
928941 emitter .emit_line ("return 0;" )
929942 emitter .emit_line ("}" )
930943
@@ -940,12 +953,7 @@ def generate_dealloc_for_class(
940953 emitter .emit_line (f"{ dealloc_func_name } ({ cl .struct_name (emitter .names )} *self)" )
941954 emitter .emit_line ("{" )
942955 if cl .supports_weakref :
943- if emitter .capi_version < (3 , 12 ):
944- emitter .emit_line ("if (self->weakreflist != NULL) {" )
945- emitter .emit_line ("PyObject_ClearWeakRefs((PyObject *) self);" )
946- emitter .emit_line ("}" )
947- else :
948- emitter .emit_line ("PyObject_ClearWeakRefs((PyObject *) self);" )
956+ emitter .emit_line ("PyObject_ClearWeakRefs((PyObject *) self);" )
949957 if has_tp_finalize :
950958 emitter .emit_line ("PyObject *type, *value, *traceback;" )
951959 emitter .emit_line ("PyErr_Fetch(&type, &value, &traceback);" )
0 commit comments