Skip to content

Commit

Permalink
Remove member name from transparent associated constants
Browse files Browse the repository at this point in the history
  • Loading branch information
grovesNL committed Nov 12, 2018
1 parent 3e07fe7 commit fce3e83
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 48 deletions.
22 changes: 14 additions & 8 deletions src/bindgen/ir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,9 @@ impl Constant {
pub fn load_assoc(
name: String,
item: &syn::ImplItemConst,
impl_ty: &syn::Type,
mod_cfg: &Option<Cfg>,
is_transparent: bool,
struct_path: &Path,
) -> Result<Constant, String> {
let ty = Type::load(&item.ty)?;

Expand All @@ -201,19 +202,24 @@ impl Constant {
return Err("Unhanded const definition".to_owned());
}

let impl_ty = Type::load(impl_ty)?;
if impl_ty.is_none() {
return Err("impl has an empty type".to_owned());
}
let impl_ty = impl_ty.unwrap();
let expr = Literal::load(
if let syn::Expr::Struct(syn::ExprStruct { ref fields, .. }) = item.expr {
if is_transparent && fields.len() == 1 {
&fields[0].expr
} else {
&item.expr
}
} else {
&item.expr
},
)?;

let struct_path = impl_ty.get_root_path().unwrap();
let full_name = Path::new(format!("{}_{}", struct_path, name));

Ok(Constant::new(
full_name,
ty,
Literal::load(&item.expr)?,
expr,
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
AnnotationSet::load(&item.attrs)?,
Documentation::load(&item.attrs),
Expand Down
114 changes: 82 additions & 32 deletions src/bindgen/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use syn;
use bindgen::cargo::{Cargo, PackageRef};
use bindgen::error::Error;
use bindgen::ir::{
AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams, ItemMap,
OpaqueItem, Path, Static, Struct, Typedef, Union,
AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams, ItemContainer,
ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
};
use bindgen::utilities::{SynAbiHelpers, SynItemHelpers};

Expand Down Expand Up @@ -494,6 +494,8 @@ impl Parse {
mod_cfg: &Option<Cfg>,
items: &[syn::Item],
) {
let mut impls = Vec::new();

for item in items {
if item.has_test_attr() {
continue;
Expand Down Expand Up @@ -524,21 +526,25 @@ impl Parse {
self.load_syn_ty(crate_name, mod_cfg, item);
}
syn::Item::Impl(ref item_impl) => {
for item in &item_impl.items {
if let syn::ImplItem::Const(ref item) = item {
self.load_syn_assoc_const(
binding_crate_name,
crate_name,
mod_cfg,
&item_impl.self_ty,
item,
);
}
}
impls.push(item_impl);
}
_ => {}
}
}

for item_impl in impls {
let associated_constants = item_impl.items.iter().filter_map(|item| match item {
syn::ImplItem::Const(ref associated_constant) => Some(associated_constant),
_ => None,
});
self.load_syn_assoc_consts(
binding_crate_name,
crate_name,
mod_cfg,
&item_impl.self_ty,
associated_constants,
);
}
}

/// Enters a `extern "C" { }` declaration and loads function declarations.
Expand Down Expand Up @@ -636,36 +642,80 @@ impl Parse {
}
}

/// Loads an associated `const` declaration
fn load_syn_assoc_const(
/// Loads associated `const` declarations
fn load_syn_assoc_consts<'a, I>(
&mut self,
binding_crate_name: &str,
crate_name: &str,
mod_cfg: &Option<Cfg>,
impl_ty: &syn::Type,
item: &syn::ImplItemConst,
) {
if crate_name != binding_crate_name {
info!(
"Skip {}::{} - (const's outside of the binding crate are not used).",
crate_name, &item.ident
);
items: I,
) where
I: IntoIterator<Item = &'a syn::ImplItemConst>,
{
let ty = Type::load(&impl_ty).unwrap();
if ty.is_none() {
return;
}

let const_name = item.ident.to_string();
let impl_struct_path = ty.unwrap().get_root_path().unwrap();

match Constant::load_assoc(const_name.clone(), item, impl_ty, mod_cfg) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);
let is_transparent = if let Some(ref impl_items) = self.structs.get_items(&impl_struct_path)
{
if impl_items.len() != 1 {
error!(
"Expected one struct to match path {}, but found {}",
impl_struct_path,
impl_items.len()
);
return;
}
if let ItemContainer::Struct(ref s) = impl_items[0] {
s.is_transparent
} else {
info!(
"Skip impl block for {}::{} (impl blocks for associated constants are only defined for structs).",
crate_name, impl_struct_path
);
return;
}
} else {
error!(
"Cannot find type for {}::{} (impl blocks require the struct declaration to be known).",
crate_name, impl_struct_path
);
return;
};

let full_name = constant.path.clone();
if !self.constants.try_insert(constant) {
error!("Conflicting name for constant {}", full_name);
}
for item in items.into_iter() {
if crate_name != binding_crate_name {
info!(
"Skip {}::{} - (const's outside of the binding crate are not used).",
crate_name, &item.ident
);
continue;
}
Err(msg) => {
warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg);

let const_name = item.ident.to_string();

match Constant::load_assoc(
const_name.clone(),
item,
mod_cfg,
is_transparent,
&impl_struct_path,
) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);

let full_name = constant.path.clone();
if !self.constants.try_insert(constant) {
error!("Conflicting name for constant {}", full_name);
}
}
Err(msg) => {
warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/both/const_conflict.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
#include <stdlib.h>
#include <stdbool.h>

#define Foo_FOO 0
#define Foo_FOO 42
9 changes: 8 additions & 1 deletion tests/expectations/both/transparent.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@ typedef DummyStruct TransparentComplexWrapper_i32;

typedef uint32_t TransparentPrimitiveWrapper_i32;

typedef uint32_t TransparentPrimitiveWithAssociatedConstants;

#define TransparentPrimitiveWithAssociatedConstants_ONE 1

#define TransparentPrimitiveWithAssociatedConstants_ZERO 0

void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
TransparentComplexWrappingStructure c,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f);
TransparentPrimitiveWrapper_i32 f,
TransparentPrimitiveWithAssociatedConstants g);
2 changes: 1 addition & 1 deletion tests/expectations/const_conflict.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
#include <stdlib.h>
#include <stdbool.h>

#define Foo_FOO 0
#define Foo_FOO 42
2 changes: 1 addition & 1 deletion tests/expectations/const_conflict.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <cstdint>
#include <cstdlib>

static const int32_t Foo_FOO = 0;
static const uint32_t Foo_FOO = 42;
2 changes: 1 addition & 1 deletion tests/expectations/tag/const_conflict.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
#include <stdlib.h>
#include <stdbool.h>

#define Foo_FOO 0
#define Foo_FOO 42
9 changes: 8 additions & 1 deletion tests/expectations/tag/transparent.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@ typedef struct DummyStruct TransparentComplexWrapper_i32;

typedef uint32_t TransparentPrimitiveWrapper_i32;

typedef uint32_t TransparentPrimitiveWithAssociatedConstants;

#define TransparentPrimitiveWithAssociatedConstants_ONE 1

#define TransparentPrimitiveWithAssociatedConstants_ZERO 0

void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
TransparentComplexWrappingStructure c,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f);
TransparentPrimitiveWrapper_i32 f,
TransparentPrimitiveWithAssociatedConstants g);
9 changes: 8 additions & 1 deletion tests/expectations/transparent.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@ typedef DummyStruct TransparentComplexWrapper_i32;

typedef uint32_t TransparentPrimitiveWrapper_i32;

typedef uint32_t TransparentPrimitiveWithAssociatedConstants;

#define TransparentPrimitiveWithAssociatedConstants_ONE 1

#define TransparentPrimitiveWithAssociatedConstants_ZERO 0

void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
TransparentComplexWrappingStructure c,
TransparentPrimitiveWrappingStructure d,
TransparentComplexWrapper_i32 e,
TransparentPrimitiveWrapper_i32 f);
TransparentPrimitiveWrapper_i32 f,
TransparentPrimitiveWithAssociatedConstants g);
9 changes: 8 additions & 1 deletion tests/expectations/transparent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ using TransparentComplexWrapper = DummyStruct;
template<typename T>
using TransparentPrimitiveWrapper = uint32_t;

using TransparentPrimitiveWithAssociatedConstants = uint32_t;

static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ONE = 1;

static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ZERO = 0;

extern "C" {

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

} // extern "C"
19 changes: 19 additions & 0 deletions tests/rust/transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ struct TransparentPrimitiveWrapper<T> {
marker: PhantomData<T>,
}

// Associated constant declared before struct declaration.
impl TransparentPrimitiveWithAssociatedConstants {
pub const ZERO: TransparentPrimitiveWithAssociatedConstants = TransparentPrimitiveWithAssociatedConstants {
bits: 0
};
}

// Transparent structure wrapping a primitive with associated constants.
#[repr(transparent)]
struct TransparentPrimitiveWithAssociatedConstants { bits: u32 }

// Associated constant declared after struct declaration.
impl TransparentPrimitiveWithAssociatedConstants {
pub const ONE: TransparentPrimitiveWithAssociatedConstants = TransparentPrimitiveWithAssociatedConstants {
bits: 1
};
}

#[no_mangle]
pub extern "C" fn root(
a: TransparentComplexWrappingStructTuple,
Expand All @@ -38,4 +56,5 @@ pub extern "C" fn root(
d: TransparentPrimitiveWrappingStructure,
e: TransparentComplexWrapper<i32>,
f: TransparentPrimitiveWrapper<i32>,
g: TransparentPrimitiveWithAssociatedConstants,
) { }

0 comments on commit fce3e83

Please sign in to comment.