Skip to content

Commit

Permalink
Added support for #[repr(transparent)]
Browse files Browse the repository at this point in the history
  • Loading branch information
regexident committed Aug 28, 2018
1 parent 090b815 commit 0e2d977
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 8 deletions.
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>,
) { }

0 comments on commit 0e2d977

Please sign in to comment.