port: advance VC6 typeobject frontier and preserve regression coverage

This commit is contained in:
RayPals
2026-10-26 18:09:33 +00:00
parent 35caf1a558
commit 5ab291a68c
162 changed files with 15675 additions and 85 deletions
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""Check tupledealloc's C89 declaration and exact teardown evaluation order."""
import re
import sys
from pathlib import Path
source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c")
match = re.search(
r"static void\ntupledealloc\(PyTupleObject \*op\)\n\{(.*?)\n\}",
source.read_text(),
re.S,
)
assert match, "tupledealloc definition not found"
body = match.group(1)
assert re.match(r"\s*Py_ssize_t i;", body), (
"tupledealloc: i must be declared without initializer before the empty "
"tuple check; declaration after Py_TRASHCAN_BEGIN is not C89 compatible"
)
expected = """
Py_ssize_t i;
if (Py_SIZE(op) == 0) {
/* The empty tuple is statically allocated. */
if (op == &_Py_SINGLETON(tuple_empty)) {
#ifdef Py_DEBUG
_Py_FatalRefcountError("deallocating the empty tuple singleton");
#else
return;
#endif
}
#ifdef Py_DEBUG
/* tuple subclasses have their own empty instances. */
assert(!PyTuple_CheckExact(op));
#endif
}
PyObject_GC_UnTrack(op);
Py_TRASHCAN_BEGIN(op, tupledealloc)
i = Py_SIZE(op);
while (--i >= 0) {
Py_XDECREF(op->ob_item[i]);
}
// This will abort on the empty singleton (if there is one).
if (!maybe_freelist_push(op)) {
Py_TYPE(op)->tp_free((PyObject *)op);
}
Py_TRASHCAN_END
"""
assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), (
"preserve empty-tuple guards, GC untracking, size assignment immediately "
"after trashcan entry, reverse item decrefs, freelist/free, and trashcan exit"
)
print("tupledealloc C89 declaration and exact teardown evaluation order: PASS")