Skip to content

Commit

Permalink
Revert b84710ae130a again. Ensure we get a warning for every opaque
Browse files Browse the repository at this point in the history
enum, but then fall back to 'unsigned int'.  See documentation for
motivation.
  • Loading branch information
arigo committed Oct 20, 2016
1 parent 8600e47 commit b4d02e9
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 26 deletions.
16 changes: 12 additions & 4 deletions cffi/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,10 +519,18 @@ def build_baseinttype(self, ffi, finishlist):
smallest_value = min(self.enumvalues)
largest_value = max(self.enumvalues)
else:
raise api.CDefError("%r has no values explicitly defined: "
"refusing to guess which integer type it is "
"meant to be (unsigned/signed, int/long)"
% self._get_c_name())
import warnings
try:
# XXX! The goal is to ensure that the warnings.warn()
# will not suppress the warning. We want to get it
# several times if we reach this point several times.
__warningregistry__.clear()
except NameError:
pass
warnings.warn("%r has no values explicitly defined; "
"guessing that it is equivalent to 'unsigned int'"
% self._get_c_name())
smallest_value = largest_value = 0
if smallest_value < 0: # needs a signed type
sign = 1
candidate1 = PrimitiveType("int")
Expand Down
22 changes: 7 additions & 15 deletions doc/source/whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ v1.8.4
in typedefs: ``typedef int foo_t[...];``. It was already supported
for global variables or structure fields.

* I turned in v1.8 a warning from ``cffi/model.py`` into an error:
``'enum xxx' has no values explicitly defined: refusing to guess which
integer type it is meant to be (unsigned/signed, int/long)``. Now I'm
turning it back to a warning again; it seems that guessing that the
enum has size ``int`` is a 99%-safe bet. (But not 100%, so it stays
as a warning.)


v1.8.3
======
Expand Down Expand Up @@ -61,21 +68,6 @@ v1.8
argument (in older versions, a copy would be made). This used to be
a CPython-only optimization.

* Turned a warning from ``cffi/model.py`` into an error: ``'enum xxx'
has no values explicitly defined: refusing to guess which integer type
it is meant to be (unsigned/signed, int/long)``. The problem is that
CFFI can't handle opaque enums. It can only handle enums as ``int``
or ``long`` integer types. That seems to be enough in almost all
cases, but strictly speaking, C code *can* handle opaque enums without
knowing whether it is an ``int`` or a ``long``---i.e. without knowing
its size. In this situation, in C you can pass pointers to such an
enum around, and that's about it. CFFI can't do that so far. There
is no fits-all solution, but try adding to the cdef: ``enum foo {
FOO_MAX_VALUE=1 };``; and, if using API mode, add ``#define
FOO_MAX_VALUE 1`` in the ``set_source()``. Replace ``1`` with
``9999999999`` in both places in the rare case where the enum needs to
fit values larger than an int.


v1.7
====
Expand Down
14 changes: 7 additions & 7 deletions testing/cffi0/backend_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,15 +1355,15 @@ def test_anonymous_enum(self):
assert ffi.getctype("e1*") == 'e1 *'

def test_opaque_enum(self):
import warnings
ffi = FFI(backend=self.Backend())
ffi.cdef("enum foo;")
from cffi import __version_info__
if __version_info__ < (1, 8):
py.test.skip("re-enable me in version 1.8")
e = py.test.raises(CDefError, ffi.cast, "enum foo", -1)
assert str(e.value) == (
"'enum foo' has no values explicitly defined: refusing to guess "
"which integer type it is meant to be (unsigned/signed, int/long)")
with warnings.catch_warnings(record=True) as log:
n = ffi.cast("enum foo", -1)
assert int(n) == 0xffffffff
assert str(log[0].message) == (
"'enum foo' has no values explicitly defined; "
"guessing that it is equivalent to 'unsigned int'")

def test_new_ctype(self):
ffi = FFI(backend=self.Backend())
Expand Down

0 comments on commit b4d02e9

Please sign in to comment.