[pypy-commit] cffi default: Fix issue16: anonymous enums.

arigo noreply at buildbot.pypy.org
Fri Jul 27 17:04:20 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r724:18972b4e0db3
Date: 2012-07-27 17:04 +0200
http://bitbucket.org/cffi/cffi/changeset/18972b4e0db3/

Log:	Fix issue16: anonymous enums.

diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -817,6 +817,7 @@
         return CTypesFunctionPtr
 
     def new_enum_type(self, name, enumerators, enumvalues):
+        assert isinstance(name, str)
         mapping = dict(zip(enumerators, enumvalues))
         reverse_mapping = dict(reversed(zip(enumvalues, enumerators)))
         CTypesInt = self.ffi._get_cached_btype(model.PrimitiveType('int'))
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -383,11 +383,27 @@
                            "not immediately constant expression")
 
     def _get_enum_type(self, type):
+        # See _get_struct_or_union_type() for the reason of the
+        # complicated logic here.  This is still a simplified version,
+        # assuming that it's ok to assume the more complicated cases
+        # don't occur...
+        try:
+            return self._structnode2type[type]
+        except KeyError:
+            pass
         name = type.name
+        if name is None:
+            self._anonymous_counter += 1
+            explicit_name = '$%d' % self._anonymous_counter
+            key = None
+        else:
+            explicit_name = name
+            key = 'enum %s' % (name,)
+            tp = self._declarations.get(key, None)
+            if tp is not None:
+                return tp
+        #
         decls = type.values
-        key = 'enum %s' % (name,)
-        if key in self._declarations:
-            return self._declarations[key]
         if decls is not None:
             enumerators = [enum.name for enum in decls.enumerators]
             partial = False
@@ -403,11 +419,13 @@
                 enumvalues.append(nextenumvalue)
                 nextenumvalue += 1
             enumvalues = tuple(enumvalues) 
-            tp = model.EnumType(name, enumerators, enumvalues)
+            tp = model.EnumType(explicit_name, enumerators, enumvalues)
             tp.partial = partial
-            self._declare(key, tp)
+            if key is not None:
+                self._declare(key, tp)
         else:   # opaque enum
             enumerators = ()
             enumvalues = ()
-            tp = model.EnumType(name, (), ())
+            tp = model.EnumType(explicit_name, (), ())
+        self._structnode2type[type] = tp
         return tp
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -1179,3 +1179,11 @@
         assert ffi1.typeof("enum foo") is not ffi2.typeof("enum foo")
         # sanity check: twice 'ffi1'
         assert ffi1.typeof("struct foo*") is ffi1.typeof("struct foo *")
+
+    def test_anonymous_enum(self):
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("typedef enum { Value0 = 0 } e, *pe;\n"
+                 "typedef enum { Value1 = 1 } e1;")
+        assert ffi.getctype("e*") == 'enum $1 *'
+        assert ffi.getctype("pe") == 'enum $1 *'
+        assert ffi.getctype("e1*") == 'enum $2 *'


More information about the pypy-commit mailing list