Author: Armin Rigo <ar...@tunes.org>
Branch: release-1.0
Changeset: r2074:b29ad54a7e0e
Date: 2015-05-21 11:27 +0200
http://bitbucket.org/cffi/cffi/changeset/b29ad54a7e0e/

Log:    hg merge default

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -6050,7 +6050,7 @@
     if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0)
         INITERROR;
 
-    v = PyText_FromString("1.0.0");
+    v = PyText_FromString("1.0.1");
     if (v == NULL || PyModule_AddObject(m, "__version__", v) < 0)
         INITERROR;
 
diff --git a/c/misc_win32.h b/c/misc_win32.h
--- a/c/misc_win32.h
+++ b/c/misc_win32.h
@@ -218,8 +218,7 @@
 
 static int dlclose(void *handle)
 {
-    FreeLibrary((HMODULE)handle);
-    return 0;
+    return !FreeLibrary((HMODULE)handle);
 }
 
 static const char *dlerror(void)
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -3346,4 +3346,4 @@
 
 def test_version():
     # this test is here mostly for PyPy
-    assert __version__ == "1.0.0"
+    assert __version__ == "1.0.1"
diff --git a/cffi/__init__.py b/cffi/__init__.py
--- a/cffi/__init__.py
+++ b/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.0.0"
-__version_info__ = (1, 0, 0)
+__version__ = "1.0.1"
+__version_info__ = (1, 0, 1)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -109,6 +109,11 @@
             if override:
                 for cache in self._function_caches:
                     cache.clear()
+            finishlist = self._parser._recomplete
+            if finishlist:
+                self._parser._recomplete = []
+                for tp in finishlist:
+                    tp.finish_backend_type(self, finishlist)
 
     def dlopen(self, name, flags=0):
         """Load and return a dynamic library identified by 'name'.
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -101,6 +101,7 @@
         self._override = False
         self._packed = False
         self._int_constants = {}
+        self._recomplete = []
 
     def _parse(self, csource):
         csource, macros = _preprocess(csource)
@@ -555,6 +556,9 @@
                 raise NotImplementedError("%s: using both bitfields and '...;'"
                                           % (tp,))
         tp.packed = self._packed
+        if tp.completed:    # must be re-completed: it is not opaque any more
+            tp.completed = 0
+            self._recomplete.append(tp)
         return tp
 
     def _make_partial(self, tp, nested):
@@ -604,19 +608,21 @@
 
     def _build_enum_type(self, explicit_name, decls):
         if decls is not None:
-            enumerators1 = [enum.name for enum in decls.enumerators]
-            enumerators = [s for s in enumerators1
-                             if not _r_enum_dotdotdot.match(s)]
-            partial = len(enumerators) < len(enumerators1)
-            enumerators = tuple(enumerators)
+            partial = False
+            enumerators = []
             enumvalues = []
             nextenumvalue = 0
-            for enum in decls.enumerators[:len(enumerators)]:
+            for enum in decls.enumerators:
+                if _r_enum_dotdotdot.match(enum.name):
+                    partial = True
+                    continue
                 if enum.value is not None:
                     nextenumvalue = self._parse_constant(enum.value)
+                enumerators.append(enum.name)
                 enumvalues.append(nextenumvalue)
                 self._add_constants(enum.name, nextenumvalue)
                 nextenumvalue += 1
+            enumerators = tuple(enumerators)
             enumvalues = tuple(enumvalues)
             tp = model.EnumType(explicit_name, enumerators, enumvalues)
             tp.partial = partial
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -293,7 +293,7 @@
 
 class StructOrUnion(StructOrUnionOrEnum):
     fixedlayout = None
-    completed = False
+    completed = 0
     partial = False
     packed = False
 
@@ -351,12 +351,13 @@
                                           "for '%s'" % (self.name,))
             return
         BType = ffi._cached_btypes[self]
-        if self.fldtypes is None:
-            return    # not completing it: it's an opaque struct
         #
         self.completed = 1
         #
-        if self.fixedlayout is None:
+        if self.fldtypes is None:
+            pass    # not completing it: it's an opaque struct
+            #
+        elif self.fixedlayout is None:
             fldtypes = [tp.get_cached_btype(ffi, finishlist)
                         for tp in self.fldtypes]
             lst = list(zip(self.fldnames, fldtypes, self.fldbitsize))
diff --git a/cffi/setuptools_ext.py b/cffi/setuptools_ext.py
--- a/cffi/setuptools_ext.py
+++ b/cffi/setuptools_ext.py
@@ -76,7 +76,7 @@
     from cffi import recompiler
 
     allsources = ['$PLACEHOLDER']
-    allsources.extend(kwds.get('sources', []))
+    allsources.extend(kwds.pop('sources', []))
     ext = Extension(name=module_name, sources=allsources, **kwds)
 
     def make_mod(tmpdir):
diff --git a/doc/source/cdef.rst b/doc/source/cdef.rst
--- a/doc/source/cdef.rst
+++ b/doc/source/cdef.rst
@@ -5,7 +5,9 @@
 There are three or four different ways to use CFFI in a project.
 In order of complexity:
 
-* The **"in-line", "ABI mode"**::
+* The **"in-line", "ABI mode"**:
+
+  .. code-block:: python
 
     import cffi
 
@@ -18,7 +20,9 @@
 .. _out-of-line-abi:
 
 * The **"out-of-line",** but still **"ABI mode",** useful to organize
-  the code and reduce the import time::
+  the code and reduce the import time:
+
+  .. code-block:: python
 
     # in a separate file "package/foo_build.py"
     import cffi
@@ -31,7 +35,9 @@
         ffi.compile()
 
   Running ``python foo_build.py`` produces a file ``_foo.py``, which
-  can then be imported in the main program::
+  can then be imported in the main program:
+
+  .. code-block:: python
 
     from package._foo import ffi
     lib = ffi.dlopen("libpath")
@@ -42,7 +48,9 @@
 
 * The **"out-of-line", "API mode"** gives you the most flexibility to
   access a C library at the level of C, instead of at the binary
-  level::
+  level:
+
+  .. code-block:: python
 
     # in a separate file "package/foo_build.py"
     import cffi
@@ -57,7 +65,9 @@
   Running ``python foo_build.py`` produces a file ``_foo.c`` and
   invokes the C compiler to turn it into a file ``_foo.so`` (or
   ``_foo.pyd`` or ``_foo.dylib``).  It is a C extension module which
-  can be imported in the main program::
+  can be imported in the main program:
+
+  .. code-block:: python
 
     from package._foo import ffi, lib
     # no ffi.dlopen()
@@ -68,7 +78,9 @@
 
 * Finally, you can (but don't have to) use CFFI's **Distutils** or
   **Setuptools integration** when writing a ``setup.py``.  For
-  Distutils (only in out-of-line API mode)::
+  Distutils (only in out-of-line API mode):
+
+  .. code-block:: python
 
     # setup.py (requires CFFI to be installed first)
     from distutils.core import setup
@@ -81,7 +93,9 @@
     )
 
   For Setuptools (out-of-line, but works in ABI or API mode;
-  recommended)::
+  recommended):
+
+  .. code-block:: python
 
     # setup.py (with automatic dependency tracking)
     from setuptools import setup
@@ -95,8 +109,8 @@
 
 Note that CFFI actually contains two different ``FFI`` classes.  The
 page `Using the ffi/lib objects`_ describes the common functionality.
-This minimum is what you get in the ``from package._foo import ffi``
-lines above.  The extended ``FFI`` class is the one you get from
+It is what you get in the ``from package._foo import ffi`` lines above.
+On the other hand, the extended ``FFI`` class is the one you get from
 ``import cffi; ffi = cffi.FFI()``.  It has the same functionality (for
 in-line use), but also the extra methods described below (to prepare
 the FFI).
@@ -111,6 +125,15 @@
 split into a different PyPI package that only installs
 ``_cffi_backend``.)
 
+Note that a few small differences do exist: notably, ``from _foo import
+ffi`` returns an object of a type written in C, which does not let you
+add random attributes to it (nor does it have all the
+underscore-prefixed internal attributes of the Python version).
+Similarly, the ``lib`` objects returned by the C version are read-only,
+apart from writes to global variables.  Also, ``lib.__dict__`` no
+longer works (it now tries to look up a hypothetical symbol
+``__dict__`` from the C library); use instead ``dir(lib)``.
+
 
 ffi.cdef(): declaring types and functions
 -----------------------------------------
@@ -277,6 +300,7 @@
 like definitions for custom "wrapper" C functions.  The goal is that
 the .c file can be generated like this::
 
+    // C file "module_name.c"
     #include <Python.h>
 
     ...c_header_source...
@@ -297,7 +321,7 @@
 least ``libraries=['foo']`` in order to link with ``libfoo.so`` or
 ``libfoo.so.X.Y``, or ``foo.dll`` on Windows.  The ``sources`` is a
 list of extra .c files compiled and linked together (the file
-``module_name.c`` is always generated and automatically added as the
+``module_name.c`` shown above is always generated and automatically added as 
the
 first argument to ``sources``).  See the distutils documentations for
 `more information about the other arguments`__.
 
@@ -309,7 +333,9 @@
 ``source_extension``, defaulting to ``".c"``.  The file generated will
 be actually called ``module_name + source_extension``.  Example for
 C++ (but note that there are still a few known issues of C-versus-C++
-compatibility)::
+compatibility):
+
+.. code-block:: python
 
     ffi.set_source("mymodule", '''
     extern "C" {
@@ -456,6 +482,12 @@
 for large projects where one CFFI-based interface depends on some
 types declared in a different CFFI-based interface.
 
+*Note that you should only use one ffi object per library; the intended
+usage of ffi.include() is if you want to interface with several
+inter-dependent libraries.*  For only one library, make one ``ffi``
+object.  (You can write several ``cdef()`` calls over the same ``ffi``
+from several Python files, if one file would be too large.)
+
 For out-of-line modules, the ``ffi.include(other_ffi)`` line should
 occur in the build script, and the ``other_ffi`` argument should be
 another FFI that comes from another build script.  When the two build
@@ -474,11 +506,6 @@
 In ABI mode, these must be accessed via the original ``other_lib``
 object returned by the ``dlopen()`` method on ``other_ffi``.
 
-*Note that you should only use one ffi object per library; the
-intended usage of ffi.include() is if you want to interface with
-several inter-dependent libraries.*  For only one library, make one
-``ffi`` object.
-
 
 ffi.cdef() limitations
 ----------------------
@@ -571,7 +598,9 @@
 One remaining use case for ``ffi.verify()`` would be the following
 hack to find explicitly the size of any type, in bytes, and have it
 available in Python immediately (e.g. because it is needed in order to
-write the rest of the build script)::
+write the rest of the build script):
+
+.. code-block:: python
 
     ffi = cffi.FFI()
     ffi.cdef("const int mysize;")
@@ -652,7 +681,9 @@
 consider moving to the out-of-line approach new in 1.0.  Here are the
 steps.
 
-**ABI mode:** if your CFFI project uses::
+**ABI mode** if your CFFI project uses ``ffi.dlopen()``:
+
+.. code-block:: python
 
     import cffi
 
@@ -668,7 +699,9 @@
 .. __: distutils-setuptools_
 
 
-**API mode:** if your CFFI project uses::
+**API mode** if your CFFI project uses ``ffi.verify()``:
+
+.. code-block:: python
 
     import cffi
 
@@ -689,7 +722,9 @@
 
 The following example should work both with old (pre-1.0) and new
 versions of CFFI---supporting both is important to run on PyPy,
-because CFFI 1.0 does not work in PyPy < 2.6::
+because CFFI 1.0 does not work in PyPy < 2.6:
+
+.. code-block:: python
 
     # in a separate file "package/foo_build.py"
     import cffi
@@ -710,7 +745,9 @@
     if __name__ == "__main__":
         ffi.compile()
 
-And in the main program::
+And in the main program:
+
+.. code-block:: python
 
     try:
         from package._foo import ffi, lib
@@ -723,7 +760,9 @@
 
 Writing a ``setup.py`` script that works both with CFFI 0.9 and 1.0
 requires explicitly checking the version of CFFI that we can have---it
-is hard-coded as a built-in module in PyPy::
+is hard-coded as a built-in module in PyPy:
+
+.. code-block:: python
 
     if '_cffi_backend' in sys.builtin_module_names:   # PyPy
         import _cffi_backend
@@ -732,7 +771,9 @@
         requires_cffi = "cffi>=1.0.0"
 
 Then we use the ``requires_cffi`` variable to give different arguments to
-``setup()`` as needed, e.g.::
+``setup()`` as needed, e.g.:
+
+.. code-block:: python
 
     if requires_cffi.startswith("cffi==0."):
         # backward compatibility: we have "cffi==0.*"
diff --git a/doc/source/conf.py b/doc/source/conf.py
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -47,7 +47,7 @@
 # The short X.Y version.
 version = '1.0'
 # The full version, including alpha/beta/rc tags.
-release = '1.0.0'
+release = '1.0.1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -120,7 +120,7 @@
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+#html_static_path = ['_static']
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
diff --git a/doc/source/installation.rst b/doc/source/installation.rst
--- a/doc/source/installation.rst
+++ b/doc/source/installation.rst
@@ -51,13 +51,13 @@
 
 Download and Installation:
 
-* http://pypi.python.org/packages/source/c/cffi/cffi-1.0.0.tar.gz
+* http://pypi.python.org/packages/source/c/cffi/cffi-1.0.1.tar.gz
 
    - Or grab the most current version by following the instructions below.
 
-   - MD5: e0a938e4880fe60b8d0200e8370f8940
+   - MD5: ...
 
-   - SHA: c97ff6f3dfc41ba3a762feea8ac13cdafa76a475
+   - SHA: ...
 
 * Or get it from the `Bitbucket page`_:
   ``hg clone https://bitbucket.org/cffi/cffi``
diff --git a/doc/source/overview.rst b/doc/source/overview.rst
--- a/doc/source/overview.rst
+++ b/doc/source/overview.rst
@@ -83,7 +83,9 @@
 For distribution purposes, remember that there is a new
 ``_simple_example.py`` file generated.  You can either include it
 statically within your project's source files, or, with Setuptools,
-you can say in the ``setup.py``::
+you can say in the ``setup.py``:
+
+.. code-block:: python
 
     from setuptools import setup
 
@@ -196,6 +198,53 @@
 .. _array: http://docs.python.org/library/array.html
 
 
+.. _performance:
+
+Purely for performance (API level, out-of-line)
+-----------------------------------------------
+
+A variant of the `section above`__ where the goal is not to call an
+existing C library, but to compile and call some C function written
+directly in the build script:
+
+.. __: real-example_
+
+.. code-block:: python
+
+    # file "example_build.py"
+
+    from cffi import FFI
+    ffi = FFI()
+
+    ffi.cdef("int foo(int *, int *, int);")
+
+    ffi.set_source("_example",
+    """
+        static int foo(int *buffer_in, int *buffer_out, int x)
+        {
+            /* some algorithm that is seriously faster in C than in Python */
+        }
+    """)
+
+    if __name__ == "__main__":
+        ffi.compile()
+
+.. code-block:: python
+
+    # file "example.py"
+
+    from _example import ffi, lib
+
+    buffer_in = ffi.new("int[]", 1000)
+    # initialize buffer_in here...
+
+    # easier to do all buffer allocations in Python and pass them to C,
+    # even for output-only arguments
+    buffer_out = ffi.new("int[]", 1000)
+
+    result = lib.foo(buffer_in, buffer_out, 1000)
+
+
 What actually happened?
 -----------------------
 
@@ -256,12 +305,20 @@
 errors, as usual e.g. if you misdeclare some function's signature.
 
 Note that the ``C header`` part can contain arbitrary C code.  You can
-use it to declare some more helpers written in C.  To export these
-helpers to Python, put their signature in the ``cdef()`` too.  This
-can be used for example to wrap "crazy" macros into more standard C
-functions.  (If all you need is to call "non-crazy" macros, then you
-can directly declare them in the ``cdef()`` as if they were
-functions.)
+use it to declare some more helper functions written in C.  To export
+these helpers to Python, put their signature in the ``cdef()`` too.
+(You can use the ``static`` C keyword, as in ``static int
+myhelper(int x) { real_code_here; }``, because these helpers are only
+referenced from the "magic" C code that is generated afterwards in the
+same C file.)
+
+This can be used for example to wrap "crazy" macros into more standard
+C functions.  The extra layer of C can be useful for other reasons
+too, like calling functions that expect some complicated argument
+structures that you prefer to build in C rather than in Python.  On
+the other hand, if all you need is to call "function-like" macros,
+then you can directly declare them in the ``cdef()`` as if they were
+functions.
 
 The generated piece of C code should be the same independently on the
 platform on which you run it, so in simple cases you can simply
diff --git a/doc/source/using.rst b/doc/source/using.rst
--- a/doc/source/using.rst
+++ b/doc/source/using.rst
@@ -57,7 +57,9 @@
 ownership, so you must keep it alive.  As soon as you forget it, then
 the casted pointer will point to garbage!  In other words, the ownership
 rules are attached to the *wrapper* cdata objects: they are not, and
-cannot, be attached to the underlying raw memory.)  Example::
+cannot, be attached to the underlying raw memory.)  Example:
+
+.. code-block:: python
 
     global_weakkeydict = weakref.WeakKeyDictionary()
 
@@ -102,7 +104,9 @@
 place to keep alive the original pointer object (returned by
 ``ffi.new()``).
 
-Example::
+Example:
+
+.. code-block:: python
 
     # void somefunction(int *);
 
@@ -184,7 +188,9 @@
 it all the time.
 
 The C99 variable-sized structures are supported too, as long as the
-initializer says how long the array should be::
+initializer says how long the array should be:
+
+.. code-block:: python
 
     # typedef struct { int x; int y[]; } foo_t;
 
@@ -267,7 +273,9 @@
 
 When calling C functions, passing arguments follows mostly the same
 rules as assigning to structure fields, and the return value follows the
-same rules as reading a structure field.  For example::
+same rules as reading a structure field.  For example:
+
+.. code-block:: python
 
     # int foo(short a, int b);
 
@@ -276,7 +284,9 @@
 
 You can pass to ``char *`` arguments a normal Python string (but don't
 pass a normal Python string to functions that take a ``char *``
-argument and may mutate it!)::
+argument and may mutate it!):
+
+.. code-block:: python
 
     # size_t strlen(const char *);
 
@@ -286,14 +296,18 @@
 in general, there is no difference between C argument declarations that
 use ``type *`` or ``type[]``.  For example, ``int *`` is fully
 equivalent to ``int[]`` or ``int[5]``.  So you can pass an ``int *`` as
-a list of integers::
+a list of integers:
+
+.. code-block:: python
 
     # void do_something_with_array(int *array);
 
     lib.do_something_with_array([1, 2, 3, 4, 5])
 
 CFFI supports passing and returning structs to functions and callbacks.
-Example::
+Example:
+
+.. code-block:: python
 
     # struct foo_s { int a, b; };
     # struct foo_s function_returning_a_struct(void);
@@ -319,7 +333,9 @@
 function>``).  This means you cannot e.g. pass them to some other C
 function expecting a function pointer argument.  Only ``ffi.typeof()``
 works on them.  If you really need a cdata pointer to the function,
-use the following workaround::
+use the following workaround:
+
+.. code-block:: python
   
     ffi.cdef(""" int (*foo)(int a, int b); """)
 
@@ -335,18 +351,22 @@
 all the arguments passed in the variable part *must* be cdata objects.
 This is because it would not be possible to guess, if you wrote this::
 
-    lib.printf("hello, %d\n", 42)
+    lib.printf("hello, %d\n", 42)   # doesn't work!
 
 that you really meant the 42 to be passed as a C ``int``, and not a
 ``long`` or ``long long``.  The same issue occurs with ``float`` versus
 ``double``.  So you have to force cdata objects of the C type you want,
-if necessary with ``ffi.cast()``::
+if necessary with ``ffi.cast()``:
+
+.. code-block:: python
   
     lib.printf("hello, %d\n", ffi.cast("int", 42))
     lib.printf("hello, %ld\n", ffi.cast("long", 42))
     lib.printf("hello, %f\n", ffi.cast("double", 42))
 
-But of course::
+But of course:
+
+.. code-block:: python
 
     lib.printf("hello, %s\n", ffi.new("char[]", "world"))
 
@@ -400,7 +420,9 @@
 Note that callbacks of a variadic function type are not supported.  A
 workaround is to add custom C code.  In the following example, a
 callback gets a first argument that counts how many extra ``int``
-arguments are passed::
+arguments are passed:
+
+.. code-block:: python
 
     # file "example_build.py"
 
@@ -427,7 +449,7 @@
         }
     """)
 
-::
+.. code-block:: python
     
     # file "example.py"
 
@@ -450,7 +472,9 @@
 and the C-level callback is made to return a default value.
 
 The returned value in case of errors is 0 or null by default, but can be
-specified with the ``error`` keyword argument to ``ffi.callback()``::
+specified with the ``error`` keyword argument to ``ffi.callback()``:
+
+.. code-block:: python
 
     @ffi.callback("int(int, int)", error=-1)
 
@@ -588,7 +612,9 @@
 accepts a C type can receive either a string or a pre-parsed ``ctype``
 object (and because of caching of the string, there is no real
 performance difference).  It can still be useful in writing typechecks,
-e.g.::
+e.g.:
+
+.. code-block:: python
   
     def myfunction(ptr):
         assert ffi.typeof(ptr) is ffi.typeof("foo_t*")
diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst
--- a/doc/source/whatsnew.rst
+++ b/doc/source/whatsnew.rst
@@ -3,6 +3,19 @@
 ======================
 
 
+1.0.1
+=====
+
+* ``ffi.set_source()`` crashed if passed a ``sources=[..]`` argument.
+  Fixed by chrippa on pull request #60.
+
+* Issue #193: if we use a struct between the first cdef() where it is
+  declared and another cdef() where its fields are defined, then this
+  definition was ignored.
+
+* Enums were buggy if you used too many "..." in their definition.
+
+
 1.0.0
 =====
 
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -143,7 +143,7 @@
 
 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
 """,
-        version='1.0.0',
+        version='1.0.1',
         packages=['cffi'],
         package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h']},
         zip_safe=False,
diff --git a/testing/cffi0/backend_tests.py b/testing/cffi0/backend_tests.py
--- a/testing/cffi0/backend_tests.py
+++ b/testing/cffi0/backend_tests.py
@@ -1703,3 +1703,13 @@
         assert lib.DOT_HEX == 0x100
         assert lib.DOT_HEX2 == 0x10
         assert lib.DOT_UL == 1000
+
+    def test_opaque_struct_becomes_nonopaque(self):
+        # Issue #193: if we use a struct between the first cdef() where it is
+        # declared and another cdef() where its fields are defined, then the
+        # definition was ignored.
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("struct foo_s;")
+        py.test.raises(TypeError, ffi.new, "struct foo_s *")
+        ffi.cdef("struct foo_s { int x; };")
+        ffi.new("struct foo_s *")
diff --git a/testing/cffi0/test_verify.py b/testing/cffi0/test_verify.py
--- a/testing/cffi0/test_verify.py
+++ b/testing/cffi0/test_verify.py
@@ -764,6 +764,11 @@
     assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4'
     assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5'
 
+def test_nonfull_enum_bug3():
+    ffi = FFI()
+    ffi.cdef("enum ee2 { EE4=..., EE5=... };")
+    ffi.cdef("enum ee6 { EE7=10, EE8=..., EE9=... };")
+
 def test_get_set_errno():
     ffi = FFI()
     ffi.cdef("int foo(int);")
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to