summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeston Carvalho <westoncarvalho@google.com>2021-01-13 10:04:50 -0800
committerEmilio Cobos Álvarez <emilio@crisal.io>2021-01-29 13:18:25 +0100
commite0f06c7fb2c59ab1154a4aba92cb885b1342a2fc (patch)
tree53aa1a57d6c1640d1e6d456318254e74205dd633
parent51778893c4cb18eb11cbfe83a72046f7cb0f3eac (diff)
Generate fields as non-pub if they would be access restricted in C++.
-rw-r--r--src/clang.rs9
-rw-r--r--src/codegen/mod.rs54
-rw-r--r--src/ir/comp.rs52
-rw-r--r--src/lib.rs15
-rw-r--r--src/options.rs7
-rw-r--r--tests/expectations/tests/no_debug_whitelisted.rs7
-rw-r--r--tests/expectations/tests/private_fields.rs522
-rw-r--r--tests/headers/private_fields.hpp44
8 files changed, 684 insertions, 26 deletions
diff --git a/src/clang.rs b/src/clang.rs
index 488660c4..66125089 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -632,6 +632,15 @@ impl Cursor {
unsafe { clang_getCXXAccessSpecifier(self.x) }
}
+ /// Is the cursor's referrent publically accessible in C++?
+ ///
+ /// Returns true if self.access_specifier() is `CX_CXXPublic` or
+ /// `CX_CXXInvalidAccessSpecifier`.
+ pub fn public_accessible(&self) -> bool {
+ let access = self.access_specifier();
+ access == CX_CXXPublic || access == CX_CXXInvalidAccessSpecifier
+ }
+
/// Is this cursor's referent a field declaration that is marked as
/// `mutable`?
pub fn is_mutable_field(&self) -> bool {
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 194a461c..cad2f47e 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1271,10 +1271,11 @@ impl<'a> FieldCodegen<'a> for FieldData {
}
}
- let is_private = self
- .annotations()
- .private_fields()
- .unwrap_or(fields_should_be_private);
+ let is_private = (!self.is_public() &&
+ ctx.options().respect_cxx_access_specs) ||
+ self.annotations()
+ .private_fields()
+ .unwrap_or(fields_should_be_private);
let accessor_kind =
self.annotations().accessor_kind().unwrap_or(accessor_kind);
@@ -1395,6 +1396,17 @@ impl Bitfield {
}
}
+fn access_specifier(
+ ctx: &BindgenContext,
+ is_pub: bool,
+) -> proc_macro2::TokenStream {
+ if is_pub || !ctx.options().respect_cxx_access_specs {
+ quote! { pub }
+ } else {
+ quote! {}
+ }
+}
+
impl<'a> FieldCodegen<'a> for BitfieldUnit {
type Extra = ();
@@ -1455,11 +1467,6 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
let unit_field_name = format!("_bitfield_{}", self.nth());
let unit_field_ident = ctx.rust_ident(&unit_field_name);
- let field = quote! {
- pub #unit_field_ident : #field_ty ,
- };
- fields.extend(Some(field));
-
let ctor_name = self.ctor_name();
let mut ctor_params = vec![];
let mut ctor_impl = quote! {};
@@ -1468,6 +1475,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
// implement AsRef<[u8]> / AsMut<[u8]> / etc.
let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT;
+ let mut access_spec = !fields_should_be_private;
for bf in self.bitfields() {
// Codegen not allowed for anonymous bitfields
if bf.name().is_none() {
@@ -1478,6 +1486,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
continue;
}
+ access_spec &= bf.is_public();
let mut bitfield_representable_as_int = true;
bf.codegen(
@@ -1511,10 +1520,17 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
ctor_impl = bf.extend_ctor_impl(ctx, param_name, ctor_impl);
}
+ let access_spec = access_specifier(ctx, access_spec);
+
+ let field = quote! {
+ #access_spec #unit_field_ident : #field_ty ,
+ };
+ fields.extend(Some(field));
+
if generate_ctor {
methods.extend(Some(quote! {
#[inline]
- pub fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty {
+ #access_spec fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty {
let mut __bindgen_bitfield_unit: #unit_field_ty = Default::default();
#ctor_impl
__bindgen_bitfield_unit
@@ -1550,7 +1566,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
fn codegen<F, M>(
&self,
ctx: &BindgenContext,
- _fields_should_be_private: bool,
+ fields_should_be_private: bool,
_codegen_depth: usize,
_accessor_kind: FieldAccessorKind,
parent: &CompInfo,
@@ -1590,13 +1606,16 @@ impl<'a> FieldCodegen<'a> for Bitfield {
bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);
let offset = self.offset_into_unit();
-
let width = self.width() as u8;
+ let access_spec = access_specifier(
+ ctx,
+ self.is_public() && !fields_should_be_private,
+ );
if parent.is_union() && !parent.can_be_rust_union(ctx) {
methods.extend(Some(quote! {
#[inline]
- pub fn #getter_name(&self) -> #bitfield_ty {
+ #access_spec fn #getter_name(&self) -> #bitfield_ty {
unsafe {
::#prefix::mem::transmute(
self.#unit_field_ident.as_ref().get(#offset, #width)
@@ -1606,7 +1625,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
}
#[inline]
- pub fn #setter_name(&mut self, val: #bitfield_ty) {
+ #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
unsafe {
let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
self.#unit_field_ident.as_mut().set(
@@ -1620,7 +1639,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
} else {
methods.extend(Some(quote! {
#[inline]
- pub fn #getter_name(&self) -> #bitfield_ty {
+ #access_spec fn #getter_name(&self) -> #bitfield_ty {
unsafe {
::#prefix::mem::transmute(
self.#unit_field_ident.get(#offset, #width)
@@ -1630,7 +1649,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
}
#[inline]
- pub fn #setter_name(&mut self, val: #bitfield_ty) {
+ #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
unsafe {
let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
self.#unit_field_ident.set(
@@ -1717,8 +1736,9 @@ impl CodeGenerator for CompInfo {
struct_layout.saw_base(inner_item.expect_type());
+ let access_spec = access_specifier(ctx, base.is_public());
fields.push(quote! {
- pub #field_name: #inner,
+ #access_spec #field_name: #inner,
});
}
}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index a0ca925c..60b1e2f0 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -148,6 +148,9 @@ pub trait FieldMethods {
/// If this is a bitfield, how many bits does it need?
fn bitfield_width(&self) -> Option<u32>;
+ /// Is this feild declared public?
+ fn is_public(&self) -> bool;
+
/// Get the annotations for this field.
fn annotations(&self) -> &Annotations;
@@ -412,6 +415,10 @@ impl FieldMethods for Bitfield {
self.data.bitfield_width()
}
+ fn is_public(&self) -> bool {
+ self.data.is_public()
+ }
+
fn annotations(&self) -> &Annotations {
self.data.annotations()
}
@@ -436,6 +443,7 @@ impl RawField {
comment: Option<String>,
annotations: Option<Annotations>,
bitfield_width: Option<u32>,
+ public: bool,
offset: Option<usize>,
) -> RawField {
RawField(FieldData {
@@ -444,6 +452,7 @@ impl RawField {
comment,
annotations: annotations.unwrap_or_default(),
bitfield_width,
+ public,
offset,
})
}
@@ -466,6 +475,10 @@ impl FieldMethods for RawField {
self.0.bitfield_width()
}
+ fn is_public(&self) -> bool {
+ self.0.is_public()
+ }
+
fn annotations(&self) -> &Annotations {
self.0.annotations()
}
@@ -878,6 +891,9 @@ pub struct FieldData {
/// If this field is a bitfield, and how many bits does it contain if it is.
bitfield_width: Option<u32>,
+ /// If the C++ field is declared `public`
+ public: bool,
+
/// The offset of the field (in bits)
offset: Option<usize>,
}
@@ -899,6 +915,10 @@ impl FieldMethods for FieldData {
self.bitfield_width
}
+ fn is_public(&self) -> bool {
+ self.public
+ }
+
fn annotations(&self) -> &Annotations {
&self.annotations
}
@@ -934,6 +954,8 @@ pub struct Base {
pub kind: BaseKind,
/// Name of the field in which this base should be stored.
pub field_name: String,
+ /// Whether this base is inherited from publically.
+ pub is_pub: bool,
}
impl Base {
@@ -961,6 +983,11 @@ impl Base {
true
}
+
+ /// Whether this base is inherited from publically.
+ pub fn is_public(&self) -> bool {
+ self.is_pub
+ }
}
/// A compound type.
@@ -1230,7 +1257,7 @@ impl CompInfo {
let mut maybe_anonymous_struct_field = None;
cursor.visit(|cur| {
if cur.kind() != CXCursor_FieldDecl {
- if let Some((ty, clang_ty, offset)) =
+ if let Some((ty, clang_ty, public, offset)) =
maybe_anonymous_struct_field.take()
{
if cur.kind() == CXCursor_TypedefDecl &&
@@ -1242,8 +1269,9 @@ impl CompInfo {
// anonymous field. Detect that case here, and do
// nothing.
} else {
- let field =
- RawField::new(None, ty, None, None, None, offset);
+ let field = RawField::new(
+ None, ty, None, None, None, public, offset,
+ );
ci.fields.append_raw_field(field);
}
}
@@ -1251,7 +1279,7 @@ impl CompInfo {
match cur.kind() {
CXCursor_FieldDecl => {
- if let Some((ty, clang_ty, offset)) =
+ if let Some((ty, clang_ty, public, offset)) =
maybe_anonymous_struct_field.take()
{
let mut used = false;
@@ -1261,9 +1289,10 @@ impl CompInfo {
}
CXChildVisit_Continue
});
+
if !used {
let field = RawField::new(
- None, ty, None, None, None, offset,
+ None, ty, None, None, None, public, offset,
);
ci.fields.append_raw_field(field);
}
@@ -1280,6 +1309,7 @@ impl CompInfo {
let comment = cur.raw_comment();
let annotations = Annotations::new(&cur);
let name = cur.spelling();
+ let is_public = cur.public_accessible();
let offset = cur.offset_of_field().ok();
// Name can be empty if there are bitfields, for example,
@@ -1297,6 +1327,7 @@ impl CompInfo {
comment,
annotations,
bit_width,
+ is_public,
offset,
);
ci.fields.append_raw_field(field);
@@ -1353,9 +1384,11 @@ impl CompInfo {
cur.kind() != CXCursor_EnumDecl
{
let ty = cur.cur_type();
+ let public = cur.public_accessible();
let offset = cur.offset_of_field().ok();
+
maybe_anonymous_struct_field =
- Some((inner, ty, offset));
+ Some((inner, ty, public, offset));
}
}
CXCursor_PackedAttr => {
@@ -1388,6 +1421,8 @@ impl CompInfo {
ty: type_id,
kind,
field_name,
+ is_pub: cur.access_specifier() ==
+ clang_sys::CX_CXXPublic,
});
}
CXCursor_Constructor | CXCursor_Destructor |
@@ -1503,8 +1538,9 @@ impl CompInfo {
CXChildVisit_Continue
});
- if let Some((ty, _, offset)) = maybe_anonymous_struct_field {
- let field = RawField::new(None, ty, None, None, None, offset);
+ if let Some((ty, _, public, offset)) = maybe_anonymous_struct_field {
+ let field =
+ RawField::new(None, ty, None, None, None, public, offset);
ci.fields.append_raw_field(field);
}
diff --git a/src/lib.rs b/src/lib.rs
index 2329dee9..8dcba3fb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -545,6 +545,10 @@ impl Builder {
output_vector.push(name.clone());
}
+ if self.options.respect_cxx_access_specs {
+ output_vector.push("--respect-cxx-access-specs".into());
+ }
+
// Add clang arguments
output_vector.push("--".into());
@@ -1518,6 +1522,12 @@ impl Builder {
self.options.dynamic_library_name = Some(dynamic_library_name.into());
self
}
+
+ /// Generate bindings as `pub` only if the bound item is publically accessible by C++.
+ pub fn respect_cxx_access_specs(mut self, doit: bool) -> Self {
+ self.options.respect_cxx_access_specs = doit;
+ self
+ }
}
/// Configuration options for generated bindings.
@@ -1805,6 +1815,10 @@ struct BindgenOptions {
/// The name of the dynamic library (if we are generating bindings for a shared library). If
/// this is None, no dynamic bindings are created.
dynamic_library_name: Option<String>,
+
+ /// Only make generated bindings `pub` if the items would be publically accessible
+ /// by C++.
+ respect_cxx_access_specs: bool,
}
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -1941,6 +1955,7 @@ impl Default for BindgenOptions {
array_pointers_in_arguments: false,
wasm_import_module_name: None,
dynamic_library_name: None,
+ respect_cxx_access_specs: false,
}
}
}
diff --git a/src/options.rs b/src/options.rs
index 7d3e077e..63e48dc8 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -493,6 +493,9 @@ where
.long("dynamic-loading")
.takes_value(true)
.help("Use dynamic loading mode with the given library name."),
+ Arg::with_name("respect-cxx-access-specs")
+ .long("respect-cxx-access-specs")
+ .help("Makes generated bindings `pub` only for items if the items are publically accessible in C++."),
]) // .args()
.get_matches_from(args);
@@ -915,6 +918,10 @@ where
builder = builder.dynamic_library_name(dynamic_library_name);
}
+ if matches.is_present("respect-cxx-access-specs") {
+ builder = builder.respect_cxx_access_specs(true);
+ }
+
let verbose = matches.is_present("verbose");
Ok((builder, output, verbose))
diff --git a/tests/expectations/tests/no_debug_whitelisted.rs b/tests/expectations/tests/no_debug_whitelisted.rs
index ac43e4ea..e240d645 100644
--- a/tests/expectations/tests/no_debug_whitelisted.rs
+++ b/tests/expectations/tests/no_debug_whitelisted.rs
@@ -25,6 +25,11 @@ fn bindgen_test_layout_NoDebug() {
assert_eq!(
unsafe { &(*(::std::ptr::null::<NoDebug>())).i as *const _ as usize },
0usize,
- concat!("Offset of field: ", stringify!(NoDebug), "::", stringify!(i))
+ concat!(
+ "Offset of field: ",
+ stringify!(NoDebug),
+ "::",
+ stringify!(i)
+ )
);
}
diff --git a/tests/expectations/tests/private_fields.rs b/tests/expectations/tests/private_fields.rs
new file mode 100644
index 00000000..f5edccae
--- /dev/null
+++ b/tests/expectations/tests/private_fields.rs
@@ -0,0 +1,522 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct __BindgenBitfieldUnit<Storage> {
+ storage: Storage,
+}
+impl<Storage> __BindgenBitfieldUnit<Storage> {
+ #[inline]
+ pub const fn new(storage: Storage) -> Self {
+ Self { storage }
+ }
+}
+impl<Storage> __BindgenBitfieldUnit<Storage>
+where
+ Storage: AsRef<[u8]> + AsMut<[u8]>,
+{
+ #[inline]
+ pub fn get_bit(&self, index: usize) -> bool {
+ debug_assert!(index / 8 < self.storage.as_ref().len());
+ let byte_index = index / 8;
+ let byte = self.storage.as_ref()[byte_index];
+ let bit_index = if cfg!(target_endian = "big") {
+ 7 - (index % 8)
+ } else {
+ index % 8
+ };
+ let mask = 1 << bit_index;
+ byte & mask == mask
+ }
+ #[inline]
+ pub fn set_bit(&mut self, index: usize, val: bool) {
+ debug_assert!(index / 8 < self.storage.as_ref().len());
+ let byte_index = index / 8;
+ let byte = &mut self.storage.as_mut()[byte_index];
+ let bit_index = if cfg!(target_endian = "big") {
+ 7 - (index % 8)
+ } else {
+ index % 8
+ };
+ let mask = 1 << bit_index;
+ if val {
+ *byte |= mask;
+ } else {
+ *byte &= !mask;
+ }
+ }
+ #[inline]
+ pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
+ debug_assert!(bit_width <= 64);
+ debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
+ debug_assert!(
+ (bit_offset + (bit_width as usize)) / 8 <=
+ self.storage.as_ref().len()
+ );
+ let mut val = 0;
+ for i in 0..(bit_width as usize) {
+ if self.get_bit(i + bit_offset) {
+ let index = if cfg!(target_endian = "big") {
+ bit_width as usize - 1 - i
+ } else {
+ i
+ };
+ val |= 1 << index;
+ }
+ }
+ val
+ }
+ #[inline]
+ pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
+ debug_assert!(bit_width <= 64);
+ debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
+ debug_assert!(
+ (bit_offset + (bit_width as usize)) / 8 <=
+ self.storage.as_ref().len()
+ );
+ for i in 0..(bit_width as usize) {
+ let mask = 1 << i;
+ let val_bit_is_set = val & mask == mask;
+ let index = if cfg!(target_endian = "big") {
+ bit_width as usize - 1 - i
+ } else {
+ i
+ };
+ self.set_bit(index + bit_offset, val_bit_is_set);
+ }
+ }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct PubPriv {
+ pub x: ::std::os::raw::c_int,
+ y: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_PubPriv() {
+ assert_eq!(
+ ::std::mem::size_of::<PubPriv>(),
+ 8usize,
+ concat!("Size of: ", stringify!(PubPriv))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<PubPriv>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(PubPriv))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<PubPriv>())).x as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(PubPriv),
+ "::",
+ stringify!(x)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<PubPriv>())).y as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(PubPriv),
+ "::",
+ stringify!(y)
+ )
+ );
+}
+#[repr(C)]
+#[repr(align(4))]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct PrivateBitFields {
+ pub _bitfield_align_1: [u8; 0],
+ _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>,
+ pub __bindgen_padding_0: [u8; 3usize],
+}
+#[test]
+fn bindgen_test_layout_PrivateBitFields() {
+ assert_eq!(
+ ::std::mem::size_of::<PrivateBitFields>(),
+ 4usize,
+ concat!("Size of: ", stringify!(PrivateBitFields))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<PrivateBitFields>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(PrivateBitFields))
+ );
+}
+impl PrivateBitFields {
+ #[inline]
+ fn a(&self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32)
+ }
+ }
+ #[inline]
+ fn set_a(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(0usize, 4u8, val as u64)
+ }
+ }
+ #[inline]
+ fn b(&self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32)
+ }
+ }
+ #[inline]
+ fn set_b(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(4usize, 4u8, val as u64)
+ }
+ }
+ #[inline]
+ fn new_bitfield_1(
+ a: ::std::os::raw::c_uint,
+ b: ::std::os::raw::c_uint,
+ ) -> __BindgenBitfieldUnit<[u8; 1usize]> {
+ let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> =
+ Default::default();
+ __bindgen_bitfield_unit.set(0usize, 4u8, {
+ let a: u32 = unsafe { ::std::mem::transmute(a) };
+ a as u64
+ });
+ __bindgen_bitfield_unit.set(4usize, 4u8, {
+ let b: u32 = unsafe { ::std::mem::transmute(b) };
+ b as u64
+ });
+ __bindgen_bitfield_unit
+ }
+}
+#[repr(C)]
+#[repr(align(4))]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct PublicBitFields {
+ pub _bitfield_align_1: [u8; 0],
+ pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>,
+ pub __bindgen_padding_0: [u8; 3usize],
+}
+#[test]
+fn bindgen_test_layout_PublicBitFields() {
+ assert_eq!(
+ ::std::mem::size_of::<PublicBitFields>(),
+ 4usize,
+ concat!("Size of: ", stringify!(PublicBitFields))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<PublicBitFields>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(PublicBitFields))
+ );
+}
+impl PublicBitFields {
+ #[inline]
+ pub fn a(&self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32)
+ }
+ }
+ #[inline]
+ pub fn set_a(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(0usize, 4u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn b(&self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32)
+ }
+ }
+ #[inline]
+ pub fn set_b(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(4usize, 4u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn new_bitfield_1(
+ a: ::std::os::raw::c_uint,
+ b: ::std::os::raw::c_uint,
+ ) -> __BindgenBitfieldUnit<[u8; 1usize]> {
+ let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> =
+ Default::default();
+ __bindgen_bitfield_unit.set(0usize, 4u8, {
+ let a: u32 = unsafe { ::std::mem::transmute(a) };
+ a as u64
+ });
+ __bindgen_bitfield_unit.set(4usize, 4u8, {
+ let b: u32 = unsafe { ::std::mem::transmute(b) };
+ b as u64
+ });
+ __bindgen_bitfield_unit
+ }
+}
+#[repr(C)]
+#[repr(align(4))]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct MixedBitFields {
+ pub _bitfield_align_1: [u8; 0],
+ _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>,
+ pub __bindgen_padding_0: [u8; 3usize],
+}
+#[test]
+fn bindgen_test_layout_MixedBitFields() {
+ assert_eq!(
+ ::std::mem::size_of::<MixedBitFields>(),
+ 4usize,
+ concat!("Size of: ", stringify!(MixedBitFields))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<MixedBitFields>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(MixedBitFields))
+ );
+}
+impl MixedBitFields {
+ #[inline]
+ fn a(&self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32)
+ }
+ }
+ #[inline]
+ fn set_a(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(0usize, 4u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn d(&self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32)
+ }
+ }
+ #[inline]
+ pub fn set_d(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(4usize, 4u8, val as u64)
+ }
+ }
+ #[inline]
+ fn new_bitfield_1(
+ a: ::std::os::raw::c_uint,
+ d: ::std::os::raw::c_uint,
+ ) -> __BindgenBitfieldUnit<[u8; 1usize]> {
+ let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> =
+ Default::default();
+ __bindgen_bitfield_unit.set(0usize, 4u8, {
+ let a: u32 = unsafe { ::std::mem::transmute(a) };
+ a as u64
+ });
+ __bindgen_bitfield_unit.set(4usize, 4u8, {
+ let d: u32 = unsafe { ::std::mem::transmute(d) };
+ d as u64
+ });
+ __bindgen_bitfield_unit
+ }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct Base {
+ pub member: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_Base() {
+ assert_eq!(
+ ::std::mem::size_of::<Base>(),
+ 4usize,
+ concat!("Size of: ", stringify!(Base))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Base>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Base))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<Base>())).member as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Base),
+ "::",
+ stringify!(member)
+ )
+ );
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct InheritsPrivately {
+ _base: Base,
+}
+#[test]
+fn bindgen_test_layout_InheritsPrivately() {
+ assert_eq!(
+ ::std::mem::size_of::<InheritsPrivately>(),
+ 4usize,
+ concat!("Size of: ", stringify!(InheritsPrivately))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<InheritsPrivately>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(InheritsPrivately))
+ );
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct InheritsPublically {
+ pub _base: Base,
+}
+#[test]
+fn bindgen_test_layout_InheritsPublically() {
+ assert_eq!(
+ ::std::mem::size_of::<InheritsPublically>(),
+ 4usize,
+ concat!("Size of: ", stringify!(InheritsPublically))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<InheritsPublically>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(InheritsPublically))
+ );
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct WithAnonStruct {
+ __bindgen_anon_1: WithAnonStruct__bindgen_ty_1,
+ pub __bindgen_anon_2: WithAnonStruct__bindgen_ty_2,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct WithAnonStruct__bindgen_ty_1 {
+ pub a: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_WithAnonStruct__bindgen_ty_1() {
+ assert_eq!(
+ ::std::mem::size_of::<WithAnonStruct__bindgen_ty_1>(),
+ 4usize,
+ concat!("Size of: ", stringify!(WithAnonStruct__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<WithAnonStruct__bindgen_ty_1>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(WithAnonStruct__bindgen_ty_1))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<WithAnonStruct__bindgen_ty_1>())).a
+ as *const _ as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(WithAnonStruct__bindgen_ty_1),
+ "::",
+ stringify!(a)
+ )
+ );
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct WithAnonStruct__bindgen_ty_2 {
+ pub b: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_WithAnonStruct__bindgen_ty_2() {
+ assert_eq!(
+ ::std::mem::size_of::<WithAnonStruct__bindgen_ty_2>(),
+ 4usize,
+ concat!("Size of: ", stringify!(WithAnonStruct__bindgen_ty_2))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<WithAnonStruct__bindgen_ty_2>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(WithAnonStruct__bindgen_ty_2))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<WithAnonStruct__bindgen_ty_2>())).b
+ as *const _ as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(WithAnonStruct__bindgen_ty_2),
+ "::",
+ stringify!(b)
+ )
+ );
+}
+#[test]
+fn bindgen_test_layout_WithAnonStruct() {
+ assert_eq!(
+ ::std::mem::size_of::<WithAnonStruct>(),
+ 8usize,
+ concat!("Size of: ", stringify!(WithAnonStruct))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<WithAnonStruct>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(WithAnonStruct))
+ );
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct WithAnonUnion {
+ __bindgen_anon_1: WithAnonUnion__bindgen_ty_1,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union WithAnonUnion__bindgen_ty_1 {
+ _bindgen_union_align: u8,
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_WithAnonUnion__bindgen_ty_1() {
+ assert_eq!(
+ ::std::mem::size_of::<WithAnonUnion__bindgen_ty_1>(),
+ 1usize,
+ concat!("Size of: ", stringify!(WithAnonUnion__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<WithAnonUnion__bindgen_ty_1>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(WithAnonUnion__bindgen_ty_1))
+ );
+}
+impl Default for WithAnonUnion__bindgen_ty_1 {
+ fn default() -> Self {
+ unsafe { ::std::mem::zeroed() }
+ }
+}
+#[test]
+fn bindgen_test_layout_WithAnonUnion() {
+ assert_eq!(
+ ::std::mem::size_of::<WithAnonUnion>(),
+ 1usize,
+ concat!("Size of: ", stringify!(WithAnonUnion))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<WithAnonUnion>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(WithAnonUnion))
+ );
+}
+impl Default for WithAnonUnion {
+ fn default() -> Self {
+ unsafe { ::std::mem::zeroed() }
+ }
+}
diff --git a/tests/headers/private_fields.hpp b/tests/headers/private_fields.hpp
new file mode 100644
index 00000000..9d55ebca
--- /dev/null
+++ b/tests/headers/private_fields.hpp
@@ -0,0 +1,44 @@
+// bindgen-flags: --respect-cxx-access-specs
+class PubPriv {
+ public:
+ int x;
+ private:
+ int y;
+};
+
+class PrivateBitFields {
+ unsigned int a : 4;
+ unsigned int b : 4;
+};
+class PublicBitFields {
+ public:
+ unsigned int a : 4;
+ unsigned int b : 4;
+};
+class MixedBitFields {
+ unsigned int a : 4;
+ public:
+ unsigned int d : 4;
+};
+
+class Base {
+ public:
+ int member;
+};
+
+class InheritsPrivately : Base {};
+class InheritsPublically : public Base {};
+
+class WithAnonStruct {
+ struct {
+ int a;
+ };
+ public:
+ struct {
+ int b;
+ };
+};
+
+class WithAnonUnion {
+ union {};
+}; \ No newline at end of file