52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Check the slow-path MRO result declaration and allocation order for C89."""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
source = Path("cpython/Objects/typeobject.c").read_text()
|
|
match = re.search(
|
|
r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}",
|
|
source,
|
|
re.S,
|
|
)
|
|
assert match, "mro_implementation definition missing"
|
|
body = match.group(1)
|
|
opening = body.split("if (!_PyType_IsReady(type))", 1)[0]
|
|
assert re.search(r"\bPyObject \*result;", opening), (
|
|
"mro_implementation: PyObject *result; must precede statements (C89)"
|
|
)
|
|
assert len(re.findall(r"\bPyObject \*result;", body)) == 1, (
|
|
"declare the slow-path result exactly once without initialization"
|
|
)
|
|
expected = """
|
|
for (i = 0; i < n; i++) {
|
|
PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i));
|
|
to_merge[i] = base->tp_mro;
|
|
}
|
|
to_merge[n] = bases;
|
|
|
|
result = PyList_New(1);
|
|
if (result == NULL) {
|
|
PyMem_Free(to_merge);
|
|
return NULL;
|
|
}
|
|
|
|
Py_INCREF(type);
|
|
PyList_SET_ITEM(result, 0, (PyObject *)type);
|
|
if (pmerge(result, to_merge, n + 1) < 0) {
|
|
Py_CLEAR(result);
|
|
}
|
|
PyMem_Free(to_merge);
|
|
|
|
return result;
|
|
"""
|
|
tail = body[body.index(" for (i = 0; i < n; i++)", body.index("to_merge = PyMem_New")):]
|
|
assert tail.split() == expected.split(), (
|
|
"preserve result allocation after merge-array population and all subsequent control flow"
|
|
)
|
|
assert body.count("PyList_New(1)") == 1, "allocate the slow-path result exactly once"
|
|
assert "PyObject *result = PyTuple_New(k + 1);" in body, (
|
|
"preserve the separate fast-path result initialization"
|
|
)
|
|
print("mro_implementation result C89 declaration and unchanged allocation order: PASS")
|