Commit 2b90042f authored by Armin Rigo's avatar Armin Rigo
Browse files

Fix PyLong_FromVoidPtr to return int/long like CPython.

Hopefully fix a translation failure on 32-bit too.
parent f133ee180e4f
......@@ -6,7 +6,6 @@ from pypy.objspace.std.longobject import W_LongObject
from pypy.interpreter.error import OperationError
from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask
from rpython.rlib.rbigint import rbigint
from rpython.rlib.rarithmetic import widen
PyLong_Check, PyLong_CheckExact = build_type_checkers("Long")
......@@ -28,25 +27,25 @@ def PyLong_FromSize_t(space, val):
"""Return a new PyLongObject object from a C size_t, or NULL on
failure.
"""
return space.wrap(val)
return space.newlong_from_rarith_int(val)
@cpython_api([rffi.LONGLONG], PyObject)
def PyLong_FromLongLong(space, val):
"""Return a new PyLongObject object from a C long long, or NULL
on failure."""
return space.newlong(val)
return space.newlong_from_rarith_int(val)
@cpython_api([rffi.ULONG], PyObject)
def PyLong_FromUnsignedLong(space, val):
"""Return a new PyLongObject object from a C unsigned long, or
NULL on failure."""
return space.wrap(val)
return space.newlong_from_rarith_int(val)
@cpython_api([rffi.ULONGLONG], PyObject)
def PyLong_FromUnsignedLongLong(space, val):
"""Return a new PyLongObject object from a C unsigned long long,
or NULL on failure."""
return space.wrap(val)
return space.newlong_from_rarith_int(val)
@cpython_api([PyObject], rffi.ULONG, error=-1)
def PyLong_AsUnsignedLong(space, w_long):
......@@ -203,7 +202,10 @@ def PyLong_FromVoidPtr(space, p):
can be retrieved from the resulting value using PyLong_AsVoidPtr().
If the integer is larger than LONG_MAX, a positive long integer is returned."""
return space.newlong(rffi.cast(ADDR, p))
value = rffi.cast(ADDR, p) # signed integer
if value < 0:
return space.newlong_from_rarith_int(rffi.cast(lltype.Unsigned, p))
return space.wrap(value)
@cpython_api([PyObject], rffi.VOIDP, error=lltype.nullptr(rffi.VOIDP.TO))
def PyLong_AsVoidPtr(space, w_long):
......
import sys, py
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.rarithmetic import maxint
from pypy.objspace.std.intobject import W_IntObject
from pypy.objspace.std.longobject import W_LongObject
from pypy.module.cpyext.test.test_api import BaseApiTest
......@@ -108,10 +109,26 @@ class TestLongObject(BaseApiTest):
lltype.free(overflow, flavor='raw')
def test_as_voidptr(self, space, api):
# CPython returns an int (not a long) depending on the value
# passed to PyLong_FromVoidPtr(). In all cases, NULL becomes
# the int 0.
w_l = api.PyLong_FromVoidPtr(lltype.nullptr(rffi.VOIDP.TO))
assert isinstance(w_l, W_LongObject)
assert space.unwrap(w_l) == 0L
assert space.is_w(space.type(w_l), space.w_int)
assert space.unwrap(w_l) == 0
assert api.PyLong_AsVoidPtr(w_l) == lltype.nullptr(rffi.VOIDP.TO)
# Positive values also return an int (assuming, like always in
# PyPy, that an int is big enough to store any pointer).
p = rffi.cast(rffi.VOIDP, maxint)
w_l = api.PyLong_FromVoidPtr(p)
assert space.is_w(space.type(w_l), space.w_int)
assert space.unwrap(w_l) == maxint
assert api.PyLong_AsVoidPtr(w_l) == p
# Negative values always return a long.
p = rffi.cast(rffi.VOIDP, -maxint-1)
w_l = api.PyLong_FromVoidPtr(p)
assert space.is_w(space.type(w_l), space.w_long)
assert space.unwrap(w_l) == maxint+1
assert api.PyLong_AsVoidPtr(w_l) == p
def test_sign_and_bits(self, space, api):
if space.is_true(space.lt(space.sys.get('version_info'),
......
......@@ -270,6 +270,9 @@ class StdObjSpace(ObjSpace):
return W_SmallLongObject.fromint(val)
return W_LongObject.fromint(self, val)
def newlong_from_rarith_int(self, val): # val is an rarithmetic type
return W_LongObject.fromrarith_int(val)
def newlong_from_rbigint(self, val):
return newlong(self, val)
......
......@@ -25,7 +25,6 @@ class TestW_LongObject:
space.raises_w(space.w_OverflowError, space.float_w, w_big)
def test_rint_variants(self):
py.test.skip("XXX broken!")
from rpython.rtyper.tool.rfficache import platform
space = self.space
for r in platform.numbertype_to_rclass.values():
......@@ -36,8 +35,8 @@ class TestW_LongObject:
for x in values:
if not r.SIGNED:
x &= r.MASK
w_obj = space.wrap(r(x))
assert space.bigint_w(w_obj).eq(rbigint.fromint(x))
w_obj = space.newlong_from_rarith_int(r(x))
assert space.bigint_w(w_obj).eq(rbigint.fromlong(x))
class AppTestLong:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment