summaryrefslogtreecommitdiff
path: root/cffi
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2020-10-29 10:32:25 +0100
committerArmin Rigo <arigo@tunes.org>2020-10-29 10:32:25 +0100
commit91f92834a124383fc07e5633d242772bbef9b29e (patch)
tree466d3cd9cb11376b3243b1a09a9f41a6aee9128f /cffi
parentc6c5b0d848b02aaf8d3e43d8cc191f53a1e9664e (diff)
downloadcffi-91f92834a124383fc07e5633d242772bbef9b29e.tar.gz
Issue #478
Fix a case of nested anonymous struct/unions when recompiling to Python
Diffstat (limited to 'cffi')
-rw-r--r--cffi/recompiler.py18
1 files changed, 14 insertions, 4 deletions
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
index 1aeae5b..86b37d7 100644
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -193,6 +193,17 @@ class Recompiler:
assert isinstance(op, CffiOp)
self.cffi_types = tuple(self.cffi_types) # don't change any more
+ def _enum_fields(self, tp):
+ # When producing C, expand all anonymous struct/union fields.
+ # That's necessary to have C code checking the offsets of the
+ # individual fields contained in them. When producing Python,
+ # don't do it and instead write it like it is, with the
+ # corresponding fields having an empty name. Empty names are
+ # recognized at runtime when we import the generated Python
+ # file.
+ expand_anonymous_struct_union = not self.target_is_python
+ return tp.enumfields(expand_anonymous_struct_union)
+
def _do_collect_type(self, tp):
if not isinstance(tp, model.BaseTypeByIdentity):
if isinstance(tp, tuple):
@@ -206,7 +217,7 @@ class Recompiler:
elif isinstance(tp, model.StructOrUnion):
if tp.fldtypes is not None and (
tp not in self.ffi._parser._included_declarations):
- for name1, tp1, _, _ in tp.enumfields():
+ for name1, tp1, _, _ in self._enum_fields(tp):
self._do_collect_type(self._field_type(tp, name1, tp1))
else:
for _, x in tp._get_items():
@@ -864,7 +875,7 @@ class Recompiler:
prnt('{')
prnt(' /* only to generate compile-time warnings or errors */')
prnt(' (void)p;')
- for fname, ftype, fbitsize, fqual in tp.enumfields():
+ for fname, ftype, fbitsize, fqual in self._enum_fields(tp):
try:
if ftype.is_integer_type() or fbitsize >= 0:
# accept all integers, but complain on float or double
@@ -920,8 +931,7 @@ class Recompiler:
flags = '|'.join(flags) or '0'
c_fields = []
if reason_for_not_expanding is None:
- expand_anonymous_struct_union = not self.target_is_python
- enumfields = list(tp.enumfields(expand_anonymous_struct_union))
+ enumfields = list(self._enum_fields(tp))
for fldname, fldtype, fbitsize, fqual in enumfields:
fldtype = self._field_type(tp, fldname, fldtype)
self._check_not_opaque(fldtype,