From 6ec6ab02c33b1b879fef7058bcfecd4edaa66bd9 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Sun, 9 Jul 2006 21:19:29 +0000 Subject: [PATCH] Fix SF bug 1441486: bad unary minus folding in compiler. --- Lib/test/test_compile.py | 4 +++ Misc/NEWS | 3 ++ Python/ast.c | 73 +++++++++++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 7c24d1b5c57..bacec35766c 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -211,6 +211,10 @@ if 1: self.assertEqual(eval("-" + all_one_bits), -18446744073709551615L) else: self.fail("How many bits *does* this machine have???") + # Verify treatment of contant folding on -(sys.maxint+1) + # i.e. -2147483648 on 32 bit platforms. Should return int, not long. + self.assertTrue(isinstance(eval("%s" % (-sys.maxint - 1)), int)) + self.assertTrue(isinstance(eval("%s" % (-sys.maxint - 2)), long)) def test_sequence_unpacking_error(self): # Verify sequence packing/unpacking with "or". SF bug #757818 diff --git a/Misc/NEWS b/Misc/NEWS index f01aff2207e..bc34360ab7a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 2.5 beta 2? Core and builtins ----------------- +- Bug #1441486: The literal representation of -(sys.maxint - 1) + again evaluates to a int object, not a long. + - Bug #1501934: The scope of global variables that are locally assigned using augmented assignment is now correctly determined. diff --git a/Python/ast.c b/Python/ast.c index 6fd1ebe2c99..cd0649eb518 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1483,6 +1483,57 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) } } +static expr_ty +ast_for_factor(struct compiling *c, const node *n) +{ + node *pfactor, *ppower, *patom, *pnum; + expr_ty expression; + + /* If the unary - operator is applied to a constant, don't generate + a UNARY_NEGATIVE opcode. Just store the approriate value as a + constant. The peephole optimizer already does something like + this but it doesn't handle the case where the constant is + (sys.maxint - 1). In that case, we want a PyIntObject, not a + PyLongObject. + */ + if (TYPE(CHILD(n, 0)) == MINUS + && NCH(n) == 2 + && TYPE((pfactor = CHILD(n, 1))) == factor + && NCH(pfactor) == 1 + && TYPE((ppower = CHILD(pfactor, 0))) == power + && NCH(ppower) == 1 + && TYPE((patom = CHILD(ppower, 0))) == atom + && TYPE((pnum = CHILD(patom, 0))) == NUMBER) { + char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2); + if (s == NULL) + return NULL; + s[0] = '-'; + strcpy(s + 1, STR(pnum)); + PyObject_FREE(STR(pnum)); + STR(pnum) = s; + return ast_for_atom(c, patom); + } + + expression = ast_for_expr(c, CHILD(n, 1)); + if (!expression) + return NULL; + + switch (TYPE(CHILD(n, 0))) { + case PLUS: + return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset, + c->c_arena); + case MINUS: + return UnaryOp(USub, expression, LINENO(n), n->n_col_offset, + c->c_arena); + case TILDE: + return UnaryOp(Invert, expression, LINENO(n), + n->n_col_offset, c->c_arena); + } + PyErr_Format(PyExc_SystemError, "unhandled factor: %d", + TYPE(CHILD(n, 0))); + return NULL; +} + static expr_ty ast_for_power(struct compiling *c, const node *n) { @@ -1662,30 +1713,12 @@ ast_for_expr(struct compiling *c, const node *n) } return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena); } - case factor: { - expr_ty expression; - + case factor: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } - - expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - - switch (TYPE(CHILD(n, 0))) { - case PLUS: - return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset, c->c_arena); - case MINUS: - return UnaryOp(USub, expression, LINENO(n), n->n_col_offset, c->c_arena); - case TILDE: - return UnaryOp(Invert, expression, LINENO(n), n->n_col_offset, c->c_arena); - } - PyErr_Format(PyExc_SystemError, "unhandled factor: %d", - TYPE(CHILD(n, 0))); - break; - } + return ast_for_factor(c, n); case power: return ast_for_power(c, n); default: