[pypy-commit] cffi cffi-1.0: fixes for anonymous nested structs

arigo noreply at buildbot.pypy.org
Sat Apr 25 12:05:23 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1816:d92f0d7cfb50
Date: 2015-04-25 12:06 +0200
http://bitbucket.org/cffi/cffi/changeset/d92f0d7cfb50/

Log:	fixes for anonymous nested structs

diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py
--- a/_cffi1/recompiler.py
+++ b/_cffi1/recompiler.py
@@ -78,7 +78,7 @@
                 self._do_collect_type(tp.as_raw_function())
             elif isinstance(tp, model.StructOrUnion):
                 if tp.fldtypes is not None:
-                    for name1, tp1 in zip(tp.fldnames, tp.fldtypes):
+                    for name1, tp1, _ in tp.enumfields():
                         self._do_collect_type(self._field_type(tp, name1, tp1))
             else:
                 for _, x in tp._get_items():
@@ -448,14 +448,15 @@
     def _struct_ctx(self, tp, cname, approxname):
         type_index = self._typesdict[tp]
         flags = []
-        if tp.partial:
+        if tp.partial or tp.has_anonymous_struct_fields():
             flags.append('CT_CUSTOM_FIELD_POS')
         if isinstance(tp, model.UnionType):
             flags.append('CT_UNION')
         flags = ('|'.join(flags)) or '0'
         if tp.fldtypes is not None:
             c_field = [approxname]
-            for fldname, fldtype, fbitsize in tp.enumfields():
+            enumfields = list(tp.enumfields())
+            for fldname, fldtype, fbitsize in enumfields:
                 fldtype = self._field_type(tp, fldname, fldtype)
                 spaces = " " * len(fldname)
                 # cname is None for _add_missing_struct_unions() only
@@ -483,13 +484,13 @@
             if cname is None:  # unknown name, for _add_missing_struct_unions
                 size_align = (' (size_t)-2, -2, /* unnamed */\n' +
                     '    _cffi_FIELDS_FOR_%s, %d },' % (approxname,
-                                                        len(tp.fldtypes),))
+                                                        len(enumfields),))
             else:
                 size_align = ('\n' +
                     '    sizeof(%s),\n' % (cname,) +
                     '    offsetof(struct _cffi_align_%s, y),\n'% (approxname,) +
                     '    _cffi_FIELDS_FOR_%s, %d },' % (approxname,
-                                                        len(tp.fldtypes),))
+                                                        len(enumfields),))
         else:
             size_align = ' (size_t)-1, -1, -1, 0 /* opaque */ },'
         self._lsts["struct_union"].append(
diff --git a/_cffi1/test_verify1.py b/_cffi1/test_verify1.py
--- a/_cffi1/test_verify1.py
+++ b/_cffi1/test_verify1.py
@@ -1282,6 +1282,8 @@
     ffi.cdef("""
         struct foo_s { struct { int a; char b; }; union { char c, d; }; };
     """)
+    assert ffi.offsetof("struct foo_s", "c") == 2 * ffi.sizeof("int")
+    assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
     ffi.verify("""
         struct foo_s { struct { int a; char b; }; union { char c, d; }; };
     """)
@@ -1305,9 +1307,10 @@
     py.test.raises(VerificationError, ffi.verify, """
         struct foo_s { struct { int a; short b; }; union { char c, d; }; };
     """)
-    py.test.raises(VerificationError, ffi.verify, """
-        struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
-    """)
+    # works fine now
+    #py.test.raises(VerificationError, ffi.verify, """
+    #    struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
+    #""")
 
 def test_nested_anonymous_struct_inexact_1():
     ffi = FFI()
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -271,6 +271,12 @@
         self.fldbitsize = fldbitsize
         self.build_c_name_with_marker()
 
+    def has_anonymous_struct_fields(self):
+        for name, type in zip(self.fldnames, self.fldtypes):
+            if name == '' and isinstance(type, StructOrUnion):
+                return True
+        return False
+
     def enumfields(self):
         for name, type, bitsize in zip(self.fldnames, self.fldtypes,
                                        self.fldbitsize):


More information about the pypy-commit mailing list