Commits

Armin Rigo  committed 0e07105

Fix for anonymous nested structs.

  • Participants
  • Parent commits 1e09626

Comments (0)

Files changed (3)

File pypy/module/_cffi_backend/ctypefunc.py

         # 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,

File pypy/module/_cffi_backend/ctypestruct.py

     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:

File pypy/module/_cffi_backend/newtype.py

             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