From: Mark Dickinson Date: Sun, 25 Nov 2012 17:11:33 +0000 (+0000) Subject: Issue #9011: AST creation no longer modifies CST for negated numeric literals. X-Git-Tag: v2.7.5~109^2~93 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b1cc6aa2df228572c5819091a18ac2c0ab6abe5a;p=python Issue #9011: AST creation no longer modifies CST for negated numeric literals. --- diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 93fbaeceea..12fa89cd46 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -567,6 +567,17 @@ class CompileTestCase(unittest.TestCase): st = parser.suite('a = u"\u1"') self.assertRaises(SyntaxError, parser.compilest, st) + def test_issue_9011(self): + # Issue 9011: compilation of an unary minus expression changed + # the meaning of the ST, so that a second compilation produced + # incorrect results. + st = parser.expr('-3') + code1 = parser.compilest(st) + self.assertEqual(eval(code1), -3) + code2 = parser.compilest(st) + self.assertEqual(eval(code2), -3) + + class ParserStackLimitTestCase(unittest.TestCase): """try to push the parser to/over it's limits. see http://bugs.python.org/issue1881 for a discussion diff --git a/Misc/NEWS b/Misc/NEWS index f69dd3c097..534661d9eb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ What's New in Python 2.7.4 Core and Builtins ----------------- +- Issue #9011: Fix hacky AST code that modified the CST when compiling + a negated numeric literal. + - Issue #16306: Fix multiple error messages when unknown command line parameters where passed to the interpreter. Patch by Hieu Nguyen. diff --git a/Python/ast.c b/Python/ast.c index 88e47450b6..fc6f002cde 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -930,7 +930,7 @@ ast_for_decorated(struct compiling *c, const node *n) return NULL; assert(TYPE(CHILD(n, 1)) == funcdef || - TYPE(CHILD(n, 1)) == classdef); + TYPE(CHILD(n, 1)) == classdef); if (TYPE(CHILD(n, 1)) == funcdef) { thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq); @@ -1744,14 +1744,19 @@ ast_for_factor(struct compiling *c, const node *n) NCH(ppower) == 1 && TYPE((patom = CHILD(ppower, 0))) == atom && TYPE((pnum = CHILD(patom, 0))) == NUMBER) { + PyObject *pynum; 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); + pynum = parsenumber(c, s); + PyObject_FREE(s); + if (!pynum) + return NULL; + + PyArena_AddPyObject(c->c_arena, pynum); + return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); } expression = ast_for_expr(c, CHILD(n, 1)); @@ -3292,8 +3297,8 @@ ast_for_stmt(struct compiling *c, const node *n) return ast_for_funcdef(c, ch, NULL); case classdef: return ast_for_classdef(c, ch, NULL); - case decorated: - return ast_for_decorated(c, ch); + case decorated: + return ast_for_decorated(c, ch); default: PyErr_Format(PyExc_SystemError, "unhandled small_stmt: TYPE=%d NCH=%d\n", @@ -3382,8 +3387,8 @@ decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, cons /* check for integer overflow */ if (len > PY_SIZE_MAX / 6) return NULL; - /* "" (2 bytes) may become "\U000000E4" (10 bytes), or 1:5 - "\ä" (3 bytes) may become "\u005c\U000000E4" (16 bytes), or ~1:6 */ + /* "" (2 bytes) may become "\U000000E4" (10 bytes), or 1:5 + "\ä" (3 bytes) may become "\u005c\U000000E4" (16 bytes), or ~1:6 */ u = PyString_FromStringAndSize((char *)NULL, len * 6); if (u == NULL) return NULL; @@ -3413,8 +3418,8 @@ decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, cons sprintf(p, "\\U%02x%02x%02x%02x", r[i + 0] & 0xFF, r[i + 1] & 0xFF, - r[i + 2] & 0xFF, - r[i + 3] & 0xFF); + r[i + 2] & 0xFF, + r[i + 3] & 0xFF); p += 10; } Py_DECREF(w);