1. Jeremy Thurgood
  2. cffi

Commits

Armin Rigo  committed 8e0c963

in-progress

  • Participants
  • Parent commits 9391831
  • Branches default

Comments (0)

Files changed (3)

File cffi/model.py

View file
  • Ignore whitespace
         self.fldtypes = fldtypes
         self.fldbitsize = fldbitsize
 
+    def enumfields(self):
+        for name, type, bitsize in zip(self.fldnames, self.fldtypes,
+                                       self.fldbitsize):
+            if name == '' and isinstance(type, StructOrUnion):
+                # nested anonymous struct/union
+                for result in type.enumfields():
+                    yield result
+            else:
+                yield (name, type, bitsize)
+
     def finish_backend_type(self, ffi):
         BType = self.new_btype(ffi)
         ffi._cached_btypes[self] = BType
                     if nrest != 0:
                         self._verification_error(
                             "field '%s.%s' has a bogus size?" % (
-                            self.name, self.fldnames[i]))
+                            self.name, self.fldnames[i] or '{}'))
                     ftype = ftype.resolve_length(nlen)
                     self.fldtypes = (self.fldtypes[:i] + (ftype,) +
                                      self.fldtypes[i+1:])
                 if bitemsize != fsize:
                     self._verification_error(
                         "field '%s.%s' is declared as %d bytes, but is "
-                        "really %d bytes" % (self.name, self.fldnames[i],
+                        "really %d bytes" % (self.name,
+                                             self.fldnames[i] or '{}',
                                              bitemsize, fsize))
             lst = list(zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs))
             ffi._backend.complete_struct_or_union(BType, lst, self,

File cffi/vengine_cpy.py

View file
  • Ignore whitespace
         prnt('static void %s(%s *p)' % (checkfuncname, cname))
         prnt('{')
         prnt('  /* only to generate compile-time warnings or errors */')
-        for i in range(len(tp.fldnames)):
-            fname = tp.fldnames[i]
-            ftype = tp.fldtypes[i]
+        for fname, ftype, _ in tp.enumfields():
             if (isinstance(ftype, model.PrimitiveType)
                 and ftype.is_integer_type()):
                 # accept all integers, but complain on float or double
             prnt('  static Py_ssize_t nums[] = {')
             prnt('    sizeof(%s),' % cname)
             prnt('    offsetof(struct _cffi_aligncheck, y),')
-            for fname in tp.fldnames:
+            for fname, _, _ in tp.enumfields():
                 prnt('    offsetof(%s, %s),' % (cname, fname))
                 prnt('    sizeof(((%s *)0)->%s),' % (cname, fname))
             prnt('    -1')
                 'sizeof(%s) != %d' % (cname, ffi.sizeof(BStruct)),
                 'offsetof(struct _cffi_aligncheck, y) != %d' % (
                     ffi.alignof(BStruct),)]
-            for fname, ftype in zip(tp.fldnames, tp.fldtypes):
+            for fname, ftype, _ in tp.enumfields():
                 BField = ffi._get_cached_btype(ftype)
                 conditions += [
                     'offsetof(%s, %s) != %d' % (

File testing/test_verify.py

View file
  • Ignore whitespace
     ffi.cdef("struct foo_s { struct { int x; } someone; };")
     ffi.verify("struct foo_s { struct { int x; } someone; };")
     # assert did not crash
+
+def test_nested_anonymous_struct_exact():
+    ffi = FFI()
+    ffi.cdef("""
+        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
+    """)
+    ffi.verify("""
+        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
+    """)
+    p = ffi.new("struct foo_s *")
+    assert ffi.sizeof(p) == 3 * ffi.sizeof("int")    # with alignment
+    p.a = 1234567
+    p.b = 'X'
+    p.c = 'Y'
+    assert p.a == 1234567
+    assert p.b == 'X'
+    assert p.c == 'Y'
+    assert p.d == 'Y'
+
+def test_nested_anonymous_struct_exact():
+    ffi = FFI()
+    ffi.cdef("""
+        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
+    """)
+    ffi.verify("""
+        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
+    """)
+    p = ffi.new("struct foo_s *")
+    assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int")    # with alignment
+    p.a = 1234567
+    p.b = 'X'
+    p.c = 'Y'
+    assert p.a == 1234567
+    assert p.b == 'X'
+    assert p.c == 'Y'
+    assert p.d == 'Y'
+
+def test_nested_anonymous_struct_exact_error():
+    ffi = FFI()
+    ffi.cdef("""
+        struct foo_s { struct { int a; char b; }; union { char c, d; }; };
+    """)
+    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; }; };
+    """)