summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-09-07 08:45:55 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-09-07 08:45:55 (GMT)
commit51e2651b298cf59653133baf556f4cca3c569583 (patch)
treec2e498784340f340ce0809b2df18237955dca40a
parent9652de9d825f2e377c4238145cc914bd28fa7111 (diff)
downloadcpython-51e2651b298cf59653133baf556f4cca3c569583.zip
cpython-51e2651b298cf59653133baf556f4cca3c569583.tar.gz
cpython-51e2651b298cf59653133baf556f4cca3c569583.tar.bz2
SF bug [#458941] Looks like a unary minus bug.
com_factor(): when a unary minus is attached to a float or imaginary zero, don't optimize the UNARY_MINUS opcode away: the const dict can't distinguish between +0.0 and -0.0, so ended up treating both like the first one added to it. Optimizing UNARY_PLUS away isn't a problem. (BTW, I already uploaded the 2.2a3 Windows installer, and this isn't important enough to delay the release.)
-rw-r--r--Python/compile.c65
1 files changed, 49 insertions, 16 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 171fceb..ec7daaf 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1879,44 +1879,77 @@ com_invert_constant(struct compiling *c, node *n)
com_addbyte(c, UNARY_INVERT);
}
+static int
+is_float_zero(const char *p)
+{
+ int found_radix_point = 0;
+ int ch;
+ while ((ch = Py_CHARMASK(*p++)) != '\0') {
+ switch (ch) {
+ case '0':
+ /* no reason to believe it's not 0 -- continue */
+ break;
+
+ case 'e': case 'E': case 'j': case 'J':
+ /* If this was a hex constant, we already would have
+ returned 0 due to the 'x' or 'X', so 'e' or 'E'
+ must be an exponent marker, and we haven't yet
+ seen a non-zero digit, and it doesn't matter what
+ the exponent is then. For 'j' or 'J' similarly,
+ except that this is an imaginary 0 then. */
+ return 1;
+
+ case '.':
+ found_radix_point = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ return found_radix_point;
+}
+
static void
com_factor(struct compiling *c, node *n)
{
int childtype = TYPE(CHILD(n, 0));
+ node *pfactor, *ppower, *patom, *pnum;
REQ(n, factor);
/* If the unary +, -, or ~ operator is applied to a constant,
- don't generate a UNARY_xxx opcode. Just store the
+ don't generate a UNARY_xxx opcode. Just store the
approriate value as a constant. If the value is negative,
extend the string containing the constant and insert a
- negative in the 0th position.
+ negative in the 0th position -- unless we're doing unary minus
+ of a floating zero! In that case the sign is significant, but
+ the const dict can't distinguish +0.0 from -0.0.
*/
if ((childtype == PLUS || childtype == MINUS || childtype == TILDE)
&& NCH(n) == 2
- && TYPE(CHILD(n, 1)) == factor
- && NCH(CHILD(n, 1)) == 1
- && TYPE(CHILD(CHILD(n, 1), 0)) == power
- && NCH(CHILD(CHILD(n, 1), 0)) == 1
- && TYPE(CHILD(CHILD(CHILD(n, 1), 0), 0)) == atom
- && TYPE(CHILD(CHILD(CHILD(CHILD(n, 1), 0), 0), 0)) == NUMBER) {
- node *constant = CHILD(CHILD(CHILD(n, 1), 0), 0);
+ && 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
+ && !(childtype == MINUS && is_float_zero(STR(pnum)))) {
if (childtype == TILDE) {
- com_invert_constant(c, CHILD(constant, 0));
+ com_invert_constant(c, pnum);
return;
}
if (childtype == MINUS) {
- node *numnode = CHILD(constant, 0);
- char *s = malloc(strlen(STR(numnode)) + 2);
+ char *s = malloc(strlen(STR(pnum)) + 2);
if (s == NULL) {
com_error(c, PyExc_MemoryError, "");
com_addbyte(c, 255);
return;
}
s[0] = '-';
- strcpy(s + 1, STR(numnode));
- free(STR(numnode));
- STR(numnode) = s;
+ strcpy(s + 1, STR(pnum));
+ free(STR(pnum));
+ STR(pnum) = s;
}
- com_atom(c, constant);
+ com_atom(c, patom);
}
else if (childtype == PLUS) {
com_factor(c, CHILD(n, 1));