diff options
author | Neil Schemenauer <nascheme@enme.ucalgary.ca> | 2006-07-09 21:19:29 (GMT) |
---|---|---|
committer | Neil Schemenauer <nascheme@enme.ucalgary.ca> | 2006-07-09 21:19:29 (GMT) |
commit | 6ec6ab02c33b1b879fef7058bcfecd4edaa66bd9 (patch) | |
tree | 8774584d013bbdd1538b5ef8b9813805f2a8bf05 /Python | |
parent | 0e07b60a4e44129cfafaeacac765cf957e2ea219 (diff) | |
download | cpython-6ec6ab02c33b1b879fef7058bcfecd4edaa66bd9.zip cpython-6ec6ab02c33b1b879fef7058bcfecd4edaa66bd9.tar.gz cpython-6ec6ab02c33b1b879fef7058bcfecd4edaa66bd9.tar.bz2 |
Fix SF bug 1441486: bad unary minus folding in compiler.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ast.c | 73 |
1 files changed, 53 insertions, 20 deletions
diff --git a/Python/ast.c b/Python/ast.c index 6fd1ebe..cd0649e 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1484,6 +1484,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) { /* power: atom trailer* ('**' factor)* @@ -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: |