Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for #[repr(transparent)] #185

Merged
merged 1 commit into from
Aug 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ impl EnumVariant {
generic_params: GenericParams::default(),
fields: parse_fields(is_tagged, &fields.named)?,
is_tagged,
is_transparent: false,
tuple_struct: false,
cfg: Cfg::append(mod_cfg, Cfg::load(&variant.attrs)),
annotations: AnnotationSet::load(&variant.attrs)?,
Expand All @@ -97,6 +98,7 @@ impl EnumVariant {
generic_params: GenericParams::default(),
fields: parse_fields(is_tagged, &fields.unnamed)?,
is_tagged,
is_transparent: false,
tuple_struct: true,
cfg: Cfg::append(mod_cfg, Cfg::load(&variant.attrs)),
annotations: AnnotationSet::load(&variant.attrs)?,
Expand Down
16 changes: 13 additions & 3 deletions src/bindgen/ir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

use syn;

#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ReprStyle {
Rust,
C,
Transparent,
}

impl Default for ReprStyle {
Expand All @@ -16,7 +17,7 @@ impl Default for ReprStyle {
}
}

#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ReprType {
U8,
U16,
Expand All @@ -28,7 +29,7 @@ pub enum ReprType {
ISize,
}

#[derive(Debug, Copy, Clone, PartialEq, Default)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
pub struct Repr {
pub style: ReprStyle,
pub ty: Option<ReprType>,
Expand All @@ -40,6 +41,11 @@ impl Repr {
ty: None,
};

pub const TRANSPARENT: Self = Repr {
style: ReprStyle::Transparent,
ty: None,
};

pub const RUST: Self = Repr {
style: ReprStyle::Rust,
ty: None,
Expand Down Expand Up @@ -82,6 +88,10 @@ impl Repr {
repr.style = ReprStyle::C;
continue;
}
"transparent" => {
repr.style = ReprStyle::Transparent;
continue;
}
_ => {
return Err(format!("Unsupported #[repr({})].", id));
}
Expand Down
31 changes: 26 additions & 5 deletions src/bindgen/ir/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Repr,
ToCondition, Type,
ToCondition, Type, Typedef,
};
use bindgen::library::Library;
use bindgen::mangle;
Expand All @@ -26,6 +26,7 @@ pub struct Struct {
pub generic_params: GenericParams,
pub fields: Vec<(String, Type, Documentation)>,
pub is_tagged: bool,
pub is_transparent: bool,
pub tuple_struct: bool,
pub cfg: Option<Cfg>,
pub annotations: AnnotationSet,
Expand All @@ -39,9 +40,13 @@ impl Struct {
}

pub fn load(item: &syn::ItemStruct, mod_cfg: &Option<Cfg>) -> Result<Struct, String> {
if Repr::load(&item.attrs)? != Repr::C {
return Err("Struct is not marked #[repr(C)].".to_owned());
}
let is_transparent = match Repr::load(&item.attrs)? {
Repr::C => false,
Repr::TRANSPARENT => true,
_ => {
return Err("Struct is not marked #[repr(C)] or #[repr(transparent)].".to_owned());
}
};

let (fields, tuple_struct) = match &item.fields {
&syn::Fields::Unit => (Vec::new(), false),
Expand Down Expand Up @@ -70,6 +75,7 @@ impl Struct {
generic_params: GenericParams::new(&item.generics),
fields: fields,
is_tagged: false,
is_transparent: is_transparent,
tuple_struct: tuple_struct,
cfg: Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
annotations: AnnotationSet::load(&item.attrs)?,
Expand Down Expand Up @@ -128,7 +134,9 @@ impl Item for Struct {
}

fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
resolver.add_struct(&self.name);
if !self.is_transparent {
resolver.add_struct(&self.name);
}
}

fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
Expand Down Expand Up @@ -225,6 +233,7 @@ impl Item for Struct {
.map(|x| (x.0.clone(), x.1.specialize(&mappings), x.2.clone()))
.collect(),
is_tagged: self.is_tagged,
is_transparent: self.is_transparent,
tuple_struct: self.tuple_struct,
cfg: self.cfg.clone(),
annotations: self.annotations.clone(),
Expand All @@ -240,6 +249,18 @@ impl Item for Struct {

impl Source for Struct {
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
if self.is_transparent {
let typedef = Typedef {
name: self.name.clone(),
generic_params: self.generic_params.clone(),
aliased: self.fields[0].1.clone(),
cfg: self.cfg.clone(),
annotations: self.annotations.clone(),
documentation: self.documentation.clone(),
};
return typedef.write(config, out);
}

let condition = (&self.cfg).to_condition(config);
condition.write_before(config, out);

Expand Down
24 changes: 24 additions & 0 deletions tests/expectations/both/transparent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct DummyStruct DummyStruct;

typedef DummyStruct TransparentComplexWrappingStructTuple;

typedef uint32_t TransparentPrimitiveWrappingStructTuple;

typedef DummyStruct TransparentComplexWrappingStructure;

typedef uint32_t TransparentPrimitiveWrappingStructure;

typedef DummyStruct TransparentComplexWrapper_i32;

typedef uint32_t TransparentPrimitiveWrapper_i32;

void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
TransparentComplexWrappingStructure c,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f);
24 changes: 24 additions & 0 deletions tests/expectations/tag/transparent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

struct DummyStruct;

typedef struct DummyStruct TransparentComplexWrappingStructTuple;

typedef uint32_t TransparentPrimitiveWrappingStructTuple;

typedef struct DummyStruct TransparentComplexWrappingStructure;

typedef uint32_t TransparentPrimitiveWrappingStructure;

typedef struct DummyStruct TransparentComplexWrapper_i32;

typedef uint32_t TransparentPrimitiveWrapper_i32;

void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
TransparentComplexWrappingStructure c,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f);
24 changes: 24 additions & 0 deletions tests/expectations/transparent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct DummyStruct DummyStruct;

typedef DummyStruct TransparentComplexWrappingStructTuple;

typedef uint32_t TransparentPrimitiveWrappingStructTuple;

typedef DummyStruct TransparentComplexWrappingStructure;

typedef uint32_t TransparentPrimitiveWrappingStructure;

typedef DummyStruct TransparentComplexWrapper_i32;

typedef uint32_t TransparentPrimitiveWrapper_i32;

void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
TransparentComplexWrappingStructure c,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f);
29 changes: 29 additions & 0 deletions tests/expectations/transparent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <cstdint>
#include <cstdlib>

struct DummyStruct;

using TransparentComplexWrappingStructTuple = DummyStruct;

using TransparentPrimitiveWrappingStructTuple = uint32_t;

using TransparentComplexWrappingStructure = DummyStruct;

using TransparentPrimitiveWrappingStructure = uint32_t;

template<typename T>
using TransparentComplexWrapper = DummyStruct;

template<typename T>
using TransparentPrimitiveWrapper = uint32_t;

extern "C" {

void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
TransparentComplexWrappingStructure c,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper<int32_t> e,
TransparentPrimitiveWrapper<int32_t> f);

} // extern "C"
41 changes: 41 additions & 0 deletions tests/rust/transparent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
struct DummyStruct;

// Transparent struct tuple wrapping a struct.
#[repr(transparent)]
struct TransparentComplexWrappingStructTuple(DummyStruct);

// Transparent struct tuple wrapping a primitive.
#[repr(transparent)]
struct TransparentPrimitiveWrappingStructTuple(u32);

// Transparent structure wrapping a struct.
#[repr(transparent)]
struct TransparentComplexWrappingStructure { only_field: DummyStruct }

// Transparent structure wrapping a primitive.
#[repr(transparent)]
struct TransparentPrimitiveWrappingStructure { only_field: u32 }

// Transparent struct wrapper with a marker wrapping a struct.
#[repr(transparent)]
struct TransparentComplexWrapper<T> {
only_non_zero_sized_field: DummyStruct,
marker: PhantomData<T>,
}

// Transparent struct wrapper with a marker wrapping a primitive.
#[repr(transparent)]
struct TransparentPrimitiveWrapper<T> {
only_non_zero_sized_field: u32,
marker: PhantomData<T>,
}

#[no_mangle]
pub extern "C" fn root(
a: TransparentComplexWrappingStructTuple,
b: TransparentPrimitiveWrappingStructTuple,
c: TransparentComplexWrappingStructure,
d: TransparentPrimitiveWrappingStructure,
e: TransparentComplexWrapper<i32>,
f: TransparentPrimitiveWrapper<i32>,
) { }