Implement stage B0 of PEP 237: add warnings for operations that
currently return inconsistent results for ints and longs; in particular: hex/oct/%u/%o/%x/%X of negative short ints, and x<<n that either loses bits or changes sign. (No warnings for repr() of a long, though that will also change to lose the trailing 'L' eventually.) This introduces some warnings in the test suite; I'll take care of those later.
This commit is contained in:
parent
d92ae840e9
commit
078151da90
|
@ -659,7 +659,7 @@ int_invert(PyIntObject *v)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
int_lshift(PyIntObject *v, PyIntObject *w)
|
int_lshift(PyIntObject *v, PyIntObject *w)
|
||||||
{
|
{
|
||||||
register long a, b;
|
long a, b, c;
|
||||||
CONVERT_TO_LONG(v, a);
|
CONVERT_TO_LONG(v, a);
|
||||||
CONVERT_TO_LONG(w, b);
|
CONVERT_TO_LONG(w, b);
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
|
@ -669,10 +669,20 @@ int_lshift(PyIntObject *v, PyIntObject *w)
|
||||||
if (a == 0 || b == 0)
|
if (a == 0 || b == 0)
|
||||||
return int_pos(v);
|
return int_pos(v);
|
||||||
if (b >= LONG_BIT) {
|
if (b >= LONG_BIT) {
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"x<<y losing bits or changing sign "
|
||||||
|
"will return a long in Python 2.4 and up") < 0)
|
||||||
|
return NULL;
|
||||||
return PyInt_FromLong(0L);
|
return PyInt_FromLong(0L);
|
||||||
}
|
}
|
||||||
a = (long)((unsigned long)a << b);
|
c = (long)((unsigned long)a << b);
|
||||||
return PyInt_FromLong(a);
|
if ((c >> b) != a || (c < 0 && a > 0)) {
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"x<<y losing bits or changing sign "
|
||||||
|
"will return a long in Python 2.4 and up") < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyInt_FromLong(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -761,6 +771,12 @@ int_oct(PyIntObject *v)
|
||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100];
|
||||||
long x = v -> ob_ival;
|
long x = v -> ob_ival;
|
||||||
|
if (x < 0) {
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"hex()/oct() of negative int will return "
|
||||||
|
"a signed string in Python 2.4 and up") < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
strcpy(buf, "0");
|
strcpy(buf, "0");
|
||||||
else
|
else
|
||||||
|
@ -773,6 +789,12 @@ int_hex(PyIntObject *v)
|
||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100];
|
||||||
long x = v -> ob_ival;
|
long x = v -> ob_ival;
|
||||||
|
if (x < 0) {
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"hex()/oct() of negative int will return "
|
||||||
|
"a signed string in Python 2.4 and up") < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
PyOS_snprintf(buf, sizeof(buf), "0x%lx", x);
|
PyOS_snprintf(buf, sizeof(buf), "0x%lx", x);
|
||||||
return PyString_FromString(buf);
|
return PyString_FromString(buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3311,6 +3311,12 @@ formatint(char *buf, size_t buflen, int flags,
|
||||||
PyErr_SetString(PyExc_TypeError, "int argument required");
|
PyErr_SetString(PyExc_TypeError, "int argument required");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (x < 0 && type != 'd' && type != 'i') {
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"%u/%o/%x/%X of negative int will return "
|
||||||
|
"a signed string in Python 2.4 and up") < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (prec < 0)
|
if (prec < 0)
|
||||||
prec = 1;
|
prec = 1;
|
||||||
|
|
||||||
|
|
|
@ -5219,6 +5219,10 @@ int usprintf(register Py_UNICODE *buffer, char *format, ...)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX To save some code duplication, formatfloat/long/int could have been
|
||||||
|
shared with stringobject.c, converting from 8-bit to Unicode after the
|
||||||
|
formatting is done. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
formatfloat(Py_UNICODE *buf,
|
formatfloat(Py_UNICODE *buf,
|
||||||
size_t buflen,
|
size_t buflen,
|
||||||
|
@ -5294,6 +5298,12 @@ formatint(Py_UNICODE *buf,
|
||||||
x = PyInt_AsLong(v);
|
x = PyInt_AsLong(v);
|
||||||
if (x == -1 && PyErr_Occurred())
|
if (x == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
|
if (x < 0 && type != 'd' && type != 'i') {
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"%u/%o/%x/%X of negative int will return "
|
||||||
|
"a signed string in Python 2.4 and up") < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (prec < 0)
|
if (prec < 0)
|
||||||
prec = 1;
|
prec = 1;
|
||||||
|
|
||||||
|
|
|
@ -1154,8 +1154,16 @@ parsenumber(struct compiling *co, char *s)
|
||||||
#endif
|
#endif
|
||||||
if (*end == 'l' || *end == 'L')
|
if (*end == 'l' || *end == 'L')
|
||||||
return PyLong_FromString(s, (char **)0, 0);
|
return PyLong_FromString(s, (char **)0, 0);
|
||||||
if (s[0] == '0')
|
if (s[0] == '0') {
|
||||||
x = (long) PyOS_strtoul(s, &end, 0);
|
x = (long) PyOS_strtoul(s, &end, 0);
|
||||||
|
if (x < 0 && errno == 0) {
|
||||||
|
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||||
|
"hex/oct constants > sys.maxint "
|
||||||
|
"will return positive values "
|
||||||
|
"in Python 2.4 and up") < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
x = PyOS_strtol(s, &end, 0);
|
x = PyOS_strtol(s, &end, 0);
|
||||||
if (*end == '\0') {
|
if (*end == '\0') {
|
||||||
|
|
Loading…
Reference in New Issue