mirror of
https://github.com/python/cpython.git
synced 2025-11-14 07:49:28 +00:00
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.)
This commit is contained in:
parent
9652de9d82
commit
51e2651b29
1 changed files with 49 additions and 16 deletions
|
|
@ -1879,44 +1879,77 @@ com_invert_constant(struct compiling *c, node *n)
|
||||||
com_addbyte(c, UNARY_INVERT);
|
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
|
static void
|
||||||
com_factor(struct compiling *c, node *n)
|
com_factor(struct compiling *c, node *n)
|
||||||
{
|
{
|
||||||
int childtype = TYPE(CHILD(n, 0));
|
int childtype = TYPE(CHILD(n, 0));
|
||||||
|
node *pfactor, *ppower, *patom, *pnum;
|
||||||
REQ(n, factor);
|
REQ(n, factor);
|
||||||
/* If the unary +, -, or ~ operator is applied to a constant,
|
/* 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,
|
approriate value as a constant. If the value is negative,
|
||||||
extend the string containing the constant and insert a
|
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)
|
if ((childtype == PLUS || childtype == MINUS || childtype == TILDE)
|
||||||
&& NCH(n) == 2
|
&& NCH(n) == 2
|
||||||
&& TYPE(CHILD(n, 1)) == factor
|
&& TYPE((pfactor = CHILD(n, 1))) == factor
|
||||||
&& NCH(CHILD(n, 1)) == 1
|
&& NCH(pfactor) == 1
|
||||||
&& TYPE(CHILD(CHILD(n, 1), 0)) == power
|
&& TYPE((ppower = CHILD(pfactor, 0))) == power
|
||||||
&& NCH(CHILD(CHILD(n, 1), 0)) == 1
|
&& NCH(ppower) == 1
|
||||||
&& TYPE(CHILD(CHILD(CHILD(n, 1), 0), 0)) == atom
|
&& TYPE((patom = CHILD(ppower, 0))) == atom
|
||||||
&& TYPE(CHILD(CHILD(CHILD(CHILD(n, 1), 0), 0), 0)) == NUMBER) {
|
&& TYPE((pnum = CHILD(patom, 0))) == NUMBER
|
||||||
node *constant = CHILD(CHILD(CHILD(n, 1), 0), 0);
|
&& !(childtype == MINUS && is_float_zero(STR(pnum)))) {
|
||||||
if (childtype == TILDE) {
|
if (childtype == TILDE) {
|
||||||
com_invert_constant(c, CHILD(constant, 0));
|
com_invert_constant(c, pnum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (childtype == MINUS) {
|
if (childtype == MINUS) {
|
||||||
node *numnode = CHILD(constant, 0);
|
char *s = malloc(strlen(STR(pnum)) + 2);
|
||||||
char *s = malloc(strlen(STR(numnode)) + 2);
|
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
com_error(c, PyExc_MemoryError, "");
|
com_error(c, PyExc_MemoryError, "");
|
||||||
com_addbyte(c, 255);
|
com_addbyte(c, 255);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s[0] = '-';
|
s[0] = '-';
|
||||||
strcpy(s + 1, STR(numnode));
|
strcpy(s + 1, STR(pnum));
|
||||||
free(STR(numnode));
|
free(STR(pnum));
|
||||||
STR(numnode) = s;
|
STR(pnum) = s;
|
||||||
}
|
}
|
||||||
com_atom(c, constant);
|
com_atom(c, patom);
|
||||||
}
|
}
|
||||||
else if (childtype == PLUS) {
|
else if (childtype == PLUS) {
|
||||||
com_factor(c, CHILD(n, 1));
|
com_factor(c, CHILD(n, 1));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue