Skip to content

Commit

Permalink
Generate fields as non-pub if they would be access restricted in C++.
Browse files Browse the repository at this point in the history
  • Loading branch information
SilensAngelusNex committed Jan 11, 2021
1 parent 5177889 commit a7093b0
Show file tree
Hide file tree
Showing 114 changed files with 940 additions and 369 deletions.
48 changes: 31 additions & 17 deletions src/codegen/mod.rs
Expand Up @@ -1271,10 +1271,10 @@ 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() ||
self.annotations()
.private_fields()
.unwrap_or(fields_should_be_private);

let accessor_kind =
self.annotations().accessor_kind().unwrap_or(accessor_kind);
Expand Down Expand Up @@ -1395,6 +1395,14 @@ impl Bitfield {
}
}

fn access_specifier(is_pub: bool) -> proc_macro2::TokenStream {
if is_pub {
quote! { pub }
} else {
quote! {}
}
}

impl<'a> FieldCodegen<'a> for BitfieldUnit {
type Extra = ();

Expand Down Expand Up @@ -1455,11 +1463,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! {};
Expand All @@ -1468,6 +1471,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() {
Expand All @@ -1478,6 +1482,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
continue;
}

access_spec &= bf.is_public();
let mut bitfield_representable_as_int = true;

bf.codegen(
Expand Down Expand Up @@ -1511,10 +1516,17 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
ctor_impl = bf.extend_ctor_impl(ctx, param_name, ctor_impl);
}

let access_spec = access_specifier(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
Expand Down Expand Up @@ -1550,7 +1562,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,
Expand Down Expand Up @@ -1590,13 +1602,14 @@ 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(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)
Expand All @@ -1606,7 +1619,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(
Expand All @@ -1620,7 +1633,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)
Expand All @@ -1630,7 +1643,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(
Expand Down Expand Up @@ -1717,8 +1730,9 @@ impl CodeGenerator for CompInfo {

struct_layout.saw_base(inner_item.expect_type());

let access_spec = access_specifier(base.is_public());
fields.push(quote! {
pub #field_name: #inner,
#access_spec #field_name: #inner,
});
}
}
Expand Down
57 changes: 49 additions & 8 deletions src/ir/comp.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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()
}
Expand All @@ -436,6 +443,7 @@ impl RawField {
comment: Option<String>,
annotations: Option<Annotations>,
bitfield_width: Option<u32>,
public: bool,
offset: Option<usize>,
) -> RawField {
RawField(FieldData {
Expand All @@ -444,6 +452,7 @@ impl RawField {
comment,
annotations: annotations.unwrap_or_default(),
bitfield_width,
public,
offset,
})
}
Expand All @@ -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()
}
Expand Down Expand Up @@ -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>,
}
Expand All @@ -899,6 +915,10 @@ impl FieldMethods for FieldData {
self.bitfield_width
}

fn is_public(&self) -> bool {
self.public
}

fn annotations(&self) -> &Annotations {
&self.annotations
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -961,6 +983,10 @@ impl Base {

true
}

pub fn is_public(&self) -> bool {
self.is_pub
}
}

/// A compound type.
Expand Down Expand Up @@ -1230,7 +1256,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 &&
Expand All @@ -1242,16 +1268,17 @@ 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);
}
}
}

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;
Expand All @@ -1261,9 +1288,11 @@ 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);
}
Expand All @@ -1280,6 +1309,8 @@ impl CompInfo {
let comment = cur.raw_comment();
let annotations = Annotations::new(&cur);
let name = cur.spelling();
let is_public =
cur.access_specifier() != clang_sys::CX_CXXPrivate;
let offset = cur.offset_of_field().ok();

// Name can be empty if there are bitfields, for example,
Expand All @@ -1297,6 +1328,7 @@ impl CompInfo {
comment,
annotations,
bit_width,
is_public,
offset,
);
ci.fields.append_raw_field(field);
Expand Down Expand Up @@ -1353,9 +1385,14 @@ impl CompInfo {
cur.kind() != CXCursor_EnumDecl
{
let ty = cur.cur_type();
let public = cur.access_specifier() ==
clang_sys::CX_CXXPublic ||
cur.access_specifier() ==
clang_sys::CX_CXXInvalidAccessSpecifier;
let offset = cur.offset_of_field().ok();

maybe_anonymous_struct_field =
Some((inner, ty, offset));
Some((inner, ty, public, offset));
}
}
CXCursor_PackedAttr => {
Expand Down Expand Up @@ -1388,6 +1425,8 @@ impl CompInfo {
ty: type_id,
kind,
field_name,
is_pub: cur.access_specifier() ==
clang_sys::CX_CXXPublic,
});
}
CXCursor_Constructor | CXCursor_Destructor |
Expand Down Expand Up @@ -1503,8 +1542,10 @@ 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);
}

Expand Down
10 changes: 5 additions & 5 deletions tests/expectations/tests/class_nested.rs
Expand Up @@ -13,7 +13,7 @@ pub struct A {
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
pub struct A_B {
pub member_b: ::std::os::raw::c_int,
member_b: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_A_B() {
Expand Down Expand Up @@ -43,7 +43,7 @@ fn bindgen_test_layout_A_B() {
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct A_D<T> {
pub foo: T,
foo: T,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
impl<T> Default for A_D<T> {
Expand Down Expand Up @@ -77,7 +77,7 @@ fn bindgen_test_layout_A() {
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
pub struct A_C {
pub baz: ::std::os::raw::c_int,
baz: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_A_C() {
Expand Down Expand Up @@ -125,7 +125,7 @@ extern "C" {
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
pub struct D {
pub member: A_B,
member: A_B,
}
#[test]
fn bindgen_test_layout_D() {
Expand All @@ -148,7 +148,7 @@ fn bindgen_test_layout_D() {
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Templated<T> {
pub member: T,
member: T,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
#[repr(C)]
Expand Down
4 changes: 2 additions & 2 deletions tests/expectations/tests/class_with_dtor.rs
Expand Up @@ -8,7 +8,7 @@
#[repr(C)]
#[derive(Debug, Hash, PartialEq, Eq)]
pub struct HandleWithDtor<T> {
pub ptr: *mut T,
ptr: *mut T,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
impl<T> Default for HandleWithDtor<T> {
Expand All @@ -20,7 +20,7 @@ pub type HandleValue = HandleWithDtor<::std::os::raw::c_int>;
#[repr(C)]
#[derive(Debug, Hash, PartialEq, Eq)]
pub struct WithoutDtor {
pub shouldBeWithDtor: HandleValue,
shouldBeWithDtor: HandleValue,
}
#[test]
fn bindgen_test_layout_WithoutDtor() {
Expand Down

0 comments on commit a7093b0

Please sign in to comment.