Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r56825:0e07105c06d5
Date: 2012-08-23 19:05 +0200
http://bitbucket.org/pypy/pypy/changeset/0e07105c06d5/

Log:    Fix for anonymous nested structs.

diff --git a/pypy/module/_cffi_backend/ctypefunc.py 
b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -264,6 +264,11 @@
         # But on 64-bit UNIX, these two structs are passed by value
         # differently: e.g. on x86-64, "b" ends up in register "rsi" in
         # the first case and "rdi" in the second case.
+        #
+        # Another reason for 'custom_field_pos' would be anonymous
+        # nested structures: we lost the information about having it
+        # here, so better safe (and forbid it) than sorry (and maybe
+        # crash).
         space = self.space
         if ctype.custom_field_pos:
             raise OperationError(space.w_TypeError,
diff --git a/pypy/module/_cffi_backend/ctypestruct.py 
b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -162,6 +162,10 @@
     def is_bitfield(self):
         return self.bitshift >= 0
 
+    def make_shifted(self, offset):
+        return W_CField(self.ctype, offset + self.offset,
+                        self.bitshift, self.bitsize)
+
     def read(self, cdata):
         cdata = rffi.ptradd(cdata, self.offset)
         if self.bitshift == self.BS_REGULAR:
diff --git a/pypy/module/_cffi_backend/newtype.py 
b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -182,9 +182,26 @@
             if not is_union:
                 prev_bit_position += fbitsize
         #
-        fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
-        fields_list.append(fld)
-        fields_dict[fname] = fld
+        if (len(fname) == 0 and
+            isinstance(ftype, ctypestruct.W_CTypeStructOrUnion)):
+            # a nested anonymous struct or union
+            srcfield2names = {}
+            for name, srcfld in ftype.fields_dict.items():
+                srcfield2names[srcfld] = name
+            for srcfld in ftype.fields_list:
+                fld = srcfld.make_shifted(offset)
+                fields_list.append(fld)
+                try:
+                    fields_dict[srcfield2names[srcfld]] = fld
+                except KeyError:
+                    pass
+            # always forbid such structures from being passed by value
+            custom_field_pos = True
+        else:
+            # a regular field
+            fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
+            fields_list.append(fld)
+            fields_dict[fname] = fld
         #
         if maxsize < ftype.size:
             maxsize = ftype.size
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to