[3.11] GH-95921: Fix positions for some chained comparisons (GH-96968) (GH-96973)

(cherry picked from commit dfc73b5724)

Automerge-Triggered-By: GH:brandtbucher
This commit is contained in:
Brandt Bucher 2022-09-20 14:56:38 -07:00 committed by GitHub
parent 32d80decbf
commit 0e61d2b557
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 0 deletions

View file

@ -1039,6 +1039,32 @@ if 1:
for instr in dis.Bytecode(while_not_chained): for instr in dis.Bytecode(while_not_chained):
self.assertNotEqual(instr.opname, "EXTENDED_ARG") self.assertNotEqual(instr.opname, "EXTENDED_ARG")
def test_compare_positions(self):
for opname, op in [
("COMPARE_OP", "<"),
("COMPARE_OP", "<="),
("COMPARE_OP", ">"),
("COMPARE_OP", ">="),
("CONTAINS_OP", "in"),
("CONTAINS_OP", "not in"),
("IS_OP", "is"),
("IS_OP", "is not"),
]:
expr = f'a {op} b {op} c'
expected_positions = 2 * [(2, 2, 0, len(expr))]
for source in [
f"\\\n{expr}", f'if \\\n{expr}: x', f"x if \\\n{expr} else y"
]:
code = compile(source, "<test>", "exec")
actual_positions = [
instruction.positions
for instruction in dis.get_instructions(code)
if instruction.opname == opname
]
with self.subTest(source):
self.assertEqual(actual_positions, expected_positions)
@requires_debug_ranges() @requires_debug_ranges()
class TestSourcePositions(unittest.TestCase): class TestSourcePositions(unittest.TestCase):
# Ensure that compiled code snippets have correct line and column numbers # Ensure that compiled code snippets have correct line and column numbers

View file

@ -0,0 +1,2 @@
Fix overly-broad source position information for chained comparisons used as
branching conditions.

View file

@ -2930,6 +2930,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
return 1; return 1;
} }
case Compare_kind: { case Compare_kind: {
SET_LOC(c, e);
Py_ssize_t i, n = asdl_seq_LEN(e->v.Compare.ops) - 1; Py_ssize_t i, n = asdl_seq_LEN(e->v.Compare.ops) - 1;
if (n > 0) { if (n > 0) {
if (!check_compare(c, e)) { if (!check_compare(c, e)) {