port: advance VC6 typeobject frontier and preserve regression coverage
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check initialize_structseq_dict's C89 declarations and operation order."""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c")
|
||||
match = re.search(
|
||||
r"static int\ninitialize_structseq_dict\(.*?\) \{(.*?)\n\}",
|
||||
source.read_text(),
|
||||
re.S,
|
||||
)
|
||||
assert match, "initialize_structseq_dict definition not found"
|
||||
body = match.group(1)
|
||||
assert re.match(
|
||||
r"\s*PyObject \*v;\s*Py_ssize_t i, k;\s*PyObject\* keys;", body
|
||||
), "i, k, and uninitialized keys must precede all statements for C89"
|
||||
assert re.search(
|
||||
r"for \(i = k = 0; i < desc->n_in_sequence; \+\+i\) \{"
|
||||
r"\s*PyObject\* new_member;\s*if", body
|
||||
), "uninitialized new_member must precede the loop's unnamed-field check for C89"
|
||||
|
||||
expected = r"""
|
||||
PyObject *v;
|
||||
Py_ssize_t i, k;
|
||||
PyObject* keys;
|
||||
|
||||
#define SET_DICT_FROM_SIZE(key, value) \
|
||||
do { \
|
||||
v = PyLong_FromSsize_t(value); \
|
||||
if (v == NULL) { \
|
||||
return -1; \
|
||||
} \
|
||||
if (PyDict_SetItemString(dict, key, v) < 0) { \
|
||||
Py_DECREF(v); \
|
||||
return -1; \
|
||||
} \
|
||||
Py_DECREF(v); \
|
||||
} while (0)
|
||||
|
||||
SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
|
||||
SET_DICT_FROM_SIZE(real_length_key, n_members);
|
||||
SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
|
||||
|
||||
// Prepare and set __match_args__
|
||||
keys = PyTuple_New(desc->n_in_sequence);
|
||||
if (keys == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = k = 0; i < desc->n_in_sequence; ++i) {
|
||||
PyObject* new_member;
|
||||
if (desc->fields[i].name == PyStructSequence_UnnamedField) {
|
||||
continue;
|
||||
}
|
||||
new_member = PyUnicode_FromString(desc->fields[i].name);
|
||||
if (new_member == NULL) {
|
||||
goto error;
|
||||
}
|
||||
PyTuple_SET_ITEM(keys, k, new_member);
|
||||
k++;
|
||||
}
|
||||
|
||||
if (_PyTuple_Resize(&keys, k) == -1) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(dict, match_args_key, keys) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
Py_DECREF(keys);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Py_DECREF(keys);
|
||||
return -1;
|
||||
"""
|
||||
assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), (
|
||||
"preserve metadata writes and early returns before tuple allocation, skip "
|
||||
"unnamed fields before Unicode allocation, and preserve insertion, resize, "
|
||||
"match-args write, refcount, and cleanup order"
|
||||
)
|
||||
print("initialize_structseq_dict C89 declarations and operation order: PASS")
|
||||
Reference in New Issue
Block a user