diff options
author | Armin Rigo <arigo@tunes.org> | 2018-01-31 21:39:19 +0100 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2018-01-31 21:39:19 +0100 |
commit | 0c20cb6f04a8bbae352bf71e4cab149da77f5918 (patch) | |
tree | 6569799e9f46315c0479d95cc6161bc1f7fbf1be /cffi | |
parent | 6d08968ac72990cefcb33c9efb58e68f320c6424 (diff) | |
download | cffi-0c20cb6f04a8bbae352bf71e4cab149da77f5918.tar.gz |
Issue #357: fix the out-of-line ABI mode when we see structs
containing anonymous unions or vice-versa
Diffstat (limited to 'cffi')
-rw-r--r-- | cffi/model.py | 17 | ||||
-rw-r--r-- | cffi/recompiler.py | 9 |
2 files changed, 15 insertions, 11 deletions
diff --git a/cffi/model.py b/cffi/model.py index fb30f7d..5d1139d 100644 --- a/cffi/model.py +++ b/cffi/model.py @@ -352,21 +352,20 @@ class StructOrUnion(StructOrUnionOrEnum): self.fldquals = fldquals self.build_c_name_with_marker() - def has_anonymous_struct_fields(self): - if self.fldtypes is None: - return False - for name, type in zip(self.fldnames, self.fldtypes): - if name == '' and isinstance(type, StructOrUnion): - return True - return False + def anonymous_struct_fields(self): + if self.fldtypes is not None: + for name, type in zip(self.fldnames, self.fldtypes): + if name == '' and isinstance(type, StructOrUnion): + yield type - def enumfields(self): + def enumfields(self, expand_anonymous_struct_union=True): fldquals = self.fldquals if fldquals is None: fldquals = (0,) * len(self.fldnames) for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes, self.fldbitsize, fldquals): - if name == '' and isinstance(type, StructOrUnion): + if (name == '' and isinstance(type, StructOrUnion) + and expand_anonymous_struct_union): # nested anonymous struct/union for result in type.enumfields(): yield result diff --git a/cffi/recompiler.py b/cffi/recompiler.py index 821be16..f48b773 100644 --- a/cffi/recompiler.py +++ b/cffi/recompiler.py @@ -836,6 +836,10 @@ class Recompiler: def _struct_collecttype(self, tp): self._do_collect_type(tp) + if self.target_is_python: + # also requires nested anon struct/unions in ABI mode, recursively + for fldtype in tp.anonymous_struct_fields(): + self._struct_collecttype(fldtype) def _struct_decl(self, tp, cname, approxname): if tp.fldtypes is None: @@ -884,7 +888,7 @@ class Recompiler: named_ptr not in self.ffi._parser._included_declarations)): if tp.fldtypes is None: pass # opaque - elif tp.partial or tp.has_anonymous_struct_fields(): + elif tp.partial or any(tp.anonymous_struct_fields()): pass # field layout obtained silently from the C compiler else: flags.append("_CFFI_F_CHECK_FIELDS") @@ -896,7 +900,8 @@ class Recompiler: flags = '|'.join(flags) or '0' c_fields = [] if reason_for_not_expanding is None: - enumfields = list(tp.enumfields()) + expand_anonymous_struct_union = not self.target_is_python + enumfields = list(tp.enumfields(expand_anonymous_struct_union)) for fldname, fldtype, fbitsize, fqual in enumfields: fldtype = self._field_type(tp, fldname, fldtype) self._check_not_opaque(fldtype, |