@@ -1219,7 +1219,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
1219
1219
ty. append_implicit_template_params ( ctx, field_item) ;
1220
1220
1221
1221
// NB: If supported, we use proper `union` types.
1222
- let ty = if parent. is_union ( ) && !parent . can_be_rust_union ( ctx ) {
1222
+ let ty = if parent. is_union ( ) && !struct_layout . is_rust_union ( ) {
1223
1223
result. saw_bindgen_union ( ) ;
1224
1224
if ctx. options ( ) . enable_cxx_namespaces {
1225
1225
quote ! {
@@ -1263,12 +1263,10 @@ impl<'a> FieldCodegen<'a> for FieldData {
1263
1263
. expect ( "Each field should have a name in codegen!" ) ;
1264
1264
let field_ident = ctx. rust_ident_raw ( field_name. as_str ( ) ) ;
1265
1265
1266
- if !parent. is_union ( ) {
1267
- if let Some ( padding_field) =
1268
- struct_layout. pad_field ( & field_name, field_ty, self . offset ( ) )
1269
- {
1270
- fields. extend ( Some ( padding_field) ) ;
1271
- }
1266
+ if let Some ( padding_field) =
1267
+ struct_layout. saw_field ( & field_name, field_ty, self . offset ( ) )
1268
+ {
1269
+ fields. extend ( Some ( padding_field) ) ;
1272
1270
}
1273
1271
1274
1272
let is_private = ( !self . is_public ( ) &&
@@ -1433,7 +1431,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
1433
1431
let layout = self . layout ( ) ;
1434
1432
let unit_field_ty = helpers:: bitfield_unit ( ctx, layout) ;
1435
1433
let field_ty = {
1436
- if parent. is_union ( ) && !parent . can_be_rust_union ( ctx ) {
1434
+ if parent. is_union ( ) && !struct_layout . is_rust_union ( ) {
1437
1435
result. saw_bindgen_union ( ) ;
1438
1436
if ctx. options ( ) . enable_cxx_namespaces {
1439
1437
quote ! {
@@ -1571,7 +1569,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
1571
1569
_accessor_kind : FieldAccessorKind ,
1572
1570
parent : & CompInfo ,
1573
1571
_result : & mut CodegenResult ,
1574
- _struct_layout : & mut StructLayoutTracker ,
1572
+ struct_layout : & mut StructLayoutTracker ,
1575
1573
_fields : & mut F ,
1576
1574
methods : & mut M ,
1577
1575
( unit_field_name, bitfield_representable_as_int) : ( & ' a str , & mut bool ) ,
@@ -1612,7 +1610,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
1612
1610
self . is_public ( ) && !fields_should_be_private,
1613
1611
) ;
1614
1612
1615
- if parent. is_union ( ) && !parent . can_be_rust_union ( ctx ) {
1613
+ if parent. is_union ( ) && !struct_layout . is_rust_union ( ) {
1616
1614
methods. extend ( Some ( quote ! {
1617
1615
#[ inline]
1618
1616
#access_spec fn #getter_name( & self ) -> #bitfield_ty {
@@ -1768,15 +1766,53 @@ impl CodeGenerator for CompInfo {
1768
1766
}
1769
1767
}
1770
1768
1771
- let is_union = self . kind ( ) == CompKind :: Union ;
1772
- let layout = item. kind ( ) . expect_type ( ) . layout ( ctx) ;
1773
-
1774
- let mut explicit_align = None ;
1775
1769
if is_opaque {
1776
1770
// Opaque item should not have generated methods, fields.
1777
1771
debug_assert ! ( fields. is_empty( ) ) ;
1778
1772
debug_assert ! ( methods. is_empty( ) ) ;
1773
+ }
1779
1774
1775
+ let is_union = self . kind ( ) == CompKind :: Union ;
1776
+ let layout = item. kind ( ) . expect_type ( ) . layout ( ctx) ;
1777
+ let zero_sized = item. is_zero_sized ( ctx) ;
1778
+ let forward_decl = self . is_forward_declaration ( ) ;
1779
+
1780
+ let mut explicit_align = None ;
1781
+
1782
+ // C++ requires every struct to be addressable, so what C++ compilers do
1783
+ // is making the struct 1-byte sized.
1784
+ //
1785
+ // This is apparently not the case for C, see:
1786
+ // https://github.com/rust-lang/rust-bindgen/issues/551
1787
+ //
1788
+ // Just get the layout, and assume C++ if not.
1789
+ //
1790
+ // NOTE: This check is conveniently here to avoid the dummy fields we
1791
+ // may add for unused template parameters.
1792
+ if !forward_decl && zero_sized {
1793
+ let has_address = if is_opaque {
1794
+ // Generate the address field if it's an opaque type and
1795
+ // couldn't determine the layout of the blob.
1796
+ layout. is_none ( )
1797
+ } else {
1798
+ layout. map_or ( true , |l| l. size != 0 )
1799
+ } ;
1800
+
1801
+ if has_address {
1802
+ let layout = Layout :: new ( 1 , 1 ) ;
1803
+ let ty = helpers:: blob ( ctx, Layout :: new ( 1 , 1 ) ) ;
1804
+ struct_layout. saw_field_with_layout (
1805
+ "_address" ,
1806
+ layout,
1807
+ /* offset = */ Some ( 0 ) ,
1808
+ ) ;
1809
+ fields. push ( quote ! {
1810
+ pub _address: #ty,
1811
+ } ) ;
1812
+ }
1813
+ }
1814
+
1815
+ if is_opaque {
1780
1816
match layout {
1781
1817
Some ( l) => {
1782
1818
explicit_align = Some ( l. align ) ;
@@ -1790,7 +1826,7 @@ impl CodeGenerator for CompInfo {
1790
1826
warn ! ( "Opaque type without layout! Expect dragons!" ) ;
1791
1827
}
1792
1828
}
1793
- } else if !is_union && !item . is_zero_sized ( ctx ) {
1829
+ } else if !is_union && !zero_sized {
1794
1830
if let Some ( padding_field) =
1795
1831
layout. and_then ( |layout| struct_layout. pad_struct ( layout) )
1796
1832
{
@@ -1815,57 +1851,26 @@ impl CodeGenerator for CompInfo {
1815
1851
}
1816
1852
}
1817
1853
}
1818
- } else if is_union && !self . is_forward_declaration ( ) {
1854
+ } else if is_union && !forward_decl {
1819
1855
// TODO(emilio): It'd be nice to unify this with the struct path
1820
1856
// above somehow.
1821
1857
let layout = layout. expect ( "Unable to get layout information?" ) ;
1822
- struct_layout. saw_union ( layout) ;
1823
-
1824
1858
if struct_layout. requires_explicit_align ( layout) {
1825
1859
explicit_align = Some ( layout. align ) ;
1826
1860
}
1827
1861
1828
- let ty = helpers:: blob ( ctx, layout) ;
1829
- fields. push ( if self . can_be_rust_union ( ctx) {
1830
- quote ! {
1831
- _bindgen_union_align: #ty ,
1832
- }
1833
- } else {
1834
- quote ! {
1862
+ if !struct_layout. is_rust_union ( ) {
1863
+ let ty = helpers:: blob ( ctx, layout) ;
1864
+ fields. push ( quote ! {
1835
1865
pub bindgen_union_field: #ty ,
1836
- }
1837
- } ) ;
1866
+ } )
1867
+ }
1838
1868
}
1839
1869
1840
- // C++ requires every struct to be addressable, so what C++ compilers do
1841
- // is making the struct 1-byte sized.
1842
- //
1843
- // This is apparently not the case for C, see:
1844
- // https://github.com/rust-lang/rust-bindgen/issues/551
1845
- //
1846
- // Just get the layout, and assume C++ if not.
1847
- //
1848
- // NOTE: This check is conveniently here to avoid the dummy fields we
1849
- // may add for unused template parameters.
1850
- if self . is_forward_declaration ( ) {
1870
+ if forward_decl {
1851
1871
fields. push ( quote ! {
1852
1872
_unused: [ u8 ; 0 ] ,
1853
1873
} ) ;
1854
- } else if item. is_zero_sized ( ctx) {
1855
- let has_address = if is_opaque {
1856
- // Generate the address field if it's an opaque type and
1857
- // couldn't determine the layout of the blob.
1858
- layout. is_none ( )
1859
- } else {
1860
- layout. map_or ( true , |l| l. size != 0 )
1861
- } ;
1862
-
1863
- if has_address {
1864
- let ty = helpers:: blob ( ctx, Layout :: new ( 1 , 1 ) ) ;
1865
- fields. push ( quote ! {
1866
- pub _address: #ty,
1867
- } ) ;
1868
- }
1869
1874
}
1870
1875
1871
1876
let mut generic_param_names = vec ! [ ] ;
@@ -1963,7 +1968,7 @@ impl CodeGenerator for CompInfo {
1963
1968
attributes. push ( attributes:: derives ( & derives) )
1964
1969
}
1965
1970
1966
- let mut tokens = if is_union && self . can_be_rust_union ( ctx ) {
1971
+ let mut tokens = if is_union && struct_layout . is_rust_union ( ) {
1967
1972
quote ! {
1968
1973
#( #attributes ) *
1969
1974
pub union #canonical_ident
0 commit comments