Skip to content

Commit 0f3f1fc

Browse files
committed
Use __BindegenComplex for C Complex Fix rust-lang#72
C complex only exists for floating point types. C Complex are built in types long double _Complex is not supported. Long double would be an f128, runing generated binding test produces: assertion failed: `(left == right)` (left: `16`, right: `32`)', tests/expectations/tests/complex.rs:72 We test global long double _Complex because it does not require layout tests. Handle all the different way a complex can be present in BindgenContext calling generated_bindegen_complex to indicate that __BindgenContext will need to be added.
1 parent 08f56c3 commit 0f3f1fc

File tree

11 files changed

+187
-99
lines changed

11 files changed

+187
-99
lines changed

src/codegen/helpers.rs

+48
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,51 @@ impl BlobTyBuilder {
7171
}
7272
}
7373
}
74+
75+
pub mod ast_ty {
76+
use aster;
77+
use ir::context::BindgenContext;
78+
use ir::ty::FloatKind;
79+
use syntax::ast;
80+
use syntax::ptr::P;
81+
82+
pub fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
83+
let ident = ctx.rust_ident_raw(&name);
84+
match ctx.options().ctypes_prefix {
85+
Some(ref prefix) => {
86+
let prefix = ctx.rust_ident_raw(prefix);
87+
quote_ty!(ctx.ext_cx(), $prefix::$ident)
88+
}
89+
None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident),
90+
}
91+
}
92+
93+
pub fn float_kind_rust_type(ctx: &BindgenContext,
94+
fk: FloatKind)
95+
-> P<ast::Ty> {
96+
macro_rules! raw {
97+
($ty: ident) => {
98+
raw_type(ctx, stringify!($ty))
99+
}
100+
}
101+
// TODO: we probably should just take the type layout into
102+
// account?
103+
//
104+
// Also, maybe this one shouldn't be the default?
105+
//
106+
// FIXME: `c_longdouble` doesn't seem to be defined in some
107+
// systems, so we use `c_double` directly.
108+
use ir::ty::FloatKind;
109+
match (fk, ctx.options().convert_floats) {
110+
(FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(),
111+
(FloatKind::Double, true) |
112+
(FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(),
113+
(FloatKind::Float, false) => raw!(c_float),
114+
(FloatKind::Double, false) |
115+
(FloatKind::LongDouble, false) => raw!(c_double),
116+
(FloatKind::Float128, _) => {
117+
aster::ty::TyBuilder::new().array(16).u8()
118+
}
119+
}
120+
}
121+
}

src/codegen/mod.rs

+28-29
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ impl CodeGenerator for Type {
336336
TypeKind::NullPtr |
337337
TypeKind::Int(..) |
338338
TypeKind::Float(..) |
339+
TypeKind::Complex(..) |
339340
TypeKind::Array(..) |
340341
TypeKind::Pointer(..) |
341342
TypeKind::BlockPointer |
@@ -1549,21 +1550,12 @@ impl ItemToRustTy for Item {
15491550
}
15501551
}
15511552

1552-
fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
1553-
let ident = ctx.rust_ident_raw(&name);
1554-
match ctx.options().ctypes_prefix {
1555-
Some(ref prefix) => {
1556-
let prefix = ctx.rust_ident_raw(prefix);
1557-
quote_ty!(ctx.ext_cx(), $prefix::$ident)
1558-
}
1559-
None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident),
1560-
}
1561-
}
1562-
15631553
impl ToRustTy for Type {
15641554
type Extra = Item;
15651555

15661556
fn to_rust_ty(&self, ctx: &BindgenContext, item: &Item) -> P<ast::Ty> {
1557+
use self::helpers::ast_ty::*;
1558+
15671559
macro_rules! raw {
15681560
($ty: ident) => {
15691561
raw_type(ctx, stringify!($ty))
@@ -1608,24 +1600,12 @@ impl ToRustTy for Type {
16081600
}
16091601
}
16101602
}
1611-
TypeKind::Float(fk) => {
1612-
// TODO: we probably should just take the type layout into
1613-
// account?
1614-
//
1615-
// Also, maybe this one shouldn't be the default?
1616-
//
1617-
// FIXME: `c_longdouble` doesn't seem to be defined in some
1618-
// systems, so we use `c_double` directly.
1619-
use ir::ty::FloatKind;
1620-
match (fk, ctx.options().convert_floats) {
1621-
(FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(),
1622-
(FloatKind::Double, true) |
1623-
(FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(),
1624-
(FloatKind::Float, false) => raw!(c_float),
1625-
(FloatKind::Double, false) |
1626-
(FloatKind::LongDouble, false) => raw!(c_double),
1627-
(FloatKind::Float128, _) => aster::ty::TyBuilder::new().array(16).u8(),
1628-
}
1603+
TypeKind::Float(fk) => float_kind_rust_type(ctx, fk),
1604+
TypeKind::Complex(fk) => {
1605+
let float_path = float_kind_rust_type(ctx, fk);
1606+
1607+
ctx.generated_bindegen_complex();
1608+
quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>)
16291609
}
16301610
TypeKind::Function(ref fs) => {
16311611
let ty = fs.to_rust_ty(ctx, item);
@@ -1900,6 +1880,9 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
19001880
if saw_union && !context.options().unstable_rust {
19011881
utils::prepend_union_types(context, &mut result);
19021882
}
1883+
if context.need_bindegen_complex_type() {
1884+
utils::prepend_complex_type(context, &mut result);
1885+
}
19031886
result
19041887
})
19051888
}
@@ -1981,6 +1964,22 @@ mod utils {
19811964
result.extend(old_items.into_iter());
19821965
}
19831966

1967+
pub fn prepend_complex_type(ctx: &BindgenContext,
1968+
result: &mut Vec<P<ast::Item>>) {
1969+
let complex_type = quote_item!(ctx.ext_cx(),
1970+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
1971+
#[repr(C)]
1972+
pub struct __BindgenComplex<T> {
1973+
pub re: T,
1974+
pub im: T
1975+
}
1976+
)
1977+
.unwrap();
1978+
1979+
let items = vec![complex_type];
1980+
let old_items = mem::replace(result, items);
1981+
result.extend(old_items.into_iter());
1982+
}
19841983

19851984
pub fn build_templated_path(item: &Item,
19861985
ctx: &BindgenContext,

src/ir/context.rs

+26
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use cexpr;
55
use clang::{self, Cursor};
66
use parse::ClangItemParser;
77
use std::borrow::Cow;
8+
use std::cell::Cell;
89
use std::collections::{HashMap, hash_map};
910
use std::collections::btree_map::{self, BTreeMap};
1011
use std::fmt;
@@ -99,6 +100,9 @@ pub struct BindgenContext<'ctx> {
99100

100101
/// The options given by the user via cli or other medium.
101102
options: BindgenOptions,
103+
104+
/// Whether a bindgen complex was generated
105+
generated_bindegen_complex: Cell<bool>,
102106
}
103107

104108
impl<'ctx> BindgenContext<'ctx> {
@@ -134,6 +138,7 @@ impl<'ctx> BindgenContext<'ctx> {
134138
index: index,
135139
translation_unit: translation_unit,
136140
options: options,
141+
generated_bindegen_complex: Cell::new(false),
137142
};
138143

139144
me.add_item(root_module, None, None);
@@ -698,6 +703,17 @@ impl<'ctx> BindgenContext<'ctx> {
698703
CXType_Double => TypeKind::Float(FloatKind::Double),
699704
CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
700705
CXType_Float128 => TypeKind::Float(FloatKind::Float128),
706+
CXType_Complex => {
707+
let float_type = ty.elem_type()
708+
.expect("Not able to resolve complex type?");
709+
let float_kind = match float_type.kind() {
710+
CXType_Float => FloatKind::Float,
711+
CXType_Double => FloatKind::Double,
712+
CXType_LongDouble => FloatKind::LongDouble,
713+
_ => panic!("Non floating-type complex?"),
714+
};
715+
TypeKind::Complex(float_kind)
716+
}
701717
_ => return None,
702718
};
703719

@@ -930,6 +946,16 @@ impl<'ctx> BindgenContext<'ctx> {
930946
self.rust_ident_raw("std")
931947
}
932948
}
949+
950+
/// Call if a binden complex is generated
951+
pub fn generated_bindegen_complex(&self) {
952+
self.generated_bindegen_complex.set(true)
953+
}
954+
955+
/// Whether we need to generate the binden complex type
956+
pub fn need_bindegen_complex_type(&self) -> bool {
957+
self.generated_bindegen_complex.get()
958+
}
933959
}
934960

935961
/// An iterator over whitelisted items.

src/ir/ty.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ impl Type {
334334
TypeKind::Comp(..) |
335335
TypeKind::Int(..) |
336336
TypeKind::Float(..) |
337+
TypeKind::Complex(..) |
337338
TypeKind::Function(..) |
338339
TypeKind::Enum(..) |
339340
TypeKind::Reference(..) |
@@ -386,6 +387,9 @@ pub enum TypeKind {
386387
/// A floating point type.
387388
Float(FloatKind),
388389

390+
/// A complex floating point type.
391+
Complex(FloatKind),
392+
389393
/// A type alias, with a name, that points to another type.
390394
Alias(String, ItemId),
391395

@@ -463,6 +467,7 @@ impl Type {
463467
TypeKind::Named(..) |
464468
TypeKind::Int(..) |
465469
TypeKind::Float(..) |
470+
TypeKind::Complex(..) |
466471
TypeKind::Function(..) |
467472
TypeKind::Enum(..) |
468473
TypeKind::Reference(..) |
@@ -801,17 +806,6 @@ impl Type {
801806
.expect("Not able to resolve array element?");
802807
TypeKind::Array(inner, ty.num_elements().unwrap())
803808
}
804-
// A complex number is always a real and an imaginary part,
805-
// so
806-
// represent that as a two-item array.
807-
CXType_Complex => {
808-
let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
809-
location,
810-
parent_id,
811-
ctx)
812-
.expect("Not able to resolve array element?");
813-
TypeKind::Array(inner, 2)
814-
}
815809
#[cfg(not(feature="llvm_stable"))]
816810
CXType_Elaborated => {
817811
return Self::from_clang_ty(potential_id,

tests/expectations/tests/complex.rs

+28-48
Original file line numberDiff line numberDiff line change
@@ -4,81 +4,61 @@
44
#![allow(non_snake_case)]
55

66

7+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
78
#[repr(C)]
8-
#[derive(Debug, Copy)]
9-
pub struct Testdouble {
10-
pub mMember: [f64; 2usize],
11-
}
12-
#[test]
13-
fn bindgen_test_layout_Testdouble() {
14-
assert_eq!(::std::mem::size_of::<Testdouble>() , 16usize);
15-
assert_eq!(::std::mem::align_of::<Testdouble>() , 8usize);
16-
}
17-
impl Clone for Testdouble {
18-
fn clone(&self) -> Self { *self }
19-
}
20-
#[repr(C)]
21-
#[derive(Debug, Copy)]
22-
pub struct TestdoublePtr {
23-
pub mMember: *mut [f64; 2usize],
24-
}
25-
#[test]
26-
fn bindgen_test_layout_TestdoublePtr() {
27-
assert_eq!(::std::mem::size_of::<TestdoublePtr>() , 8usize);
28-
assert_eq!(::std::mem::align_of::<TestdoublePtr>() , 8usize);
29-
}
30-
impl Clone for TestdoublePtr {
31-
fn clone(&self) -> Self { *self }
9+
pub struct __BindgenComplex<T> {
10+
pub re: T,
11+
pub im: T,
3212
}
3313
#[repr(C)]
3414
#[derive(Debug, Copy)]
35-
pub struct Testfloat {
36-
pub mMember: [f32; 2usize],
15+
pub struct TestDouble {
16+
pub mMember: __BindgenComplex<f64>,
3717
}
3818
#[test]
39-
fn bindgen_test_layout_Testfloat() {
40-
assert_eq!(::std::mem::size_of::<Testfloat>() , 8usize);
41-
assert_eq!(::std::mem::align_of::<Testfloat>() , 4usize);
19+
fn bindgen_test_layout_TestDouble() {
20+
assert_eq!(::std::mem::size_of::<TestDouble>() , 16usize);
21+
assert_eq!(::std::mem::align_of::<TestDouble>() , 8usize);
4222
}
43-
impl Clone for Testfloat {
23+
impl Clone for TestDouble {
4424
fn clone(&self) -> Self { *self }
4525
}
4626
#[repr(C)]
4727
#[derive(Debug, Copy)]
48-
pub struct TestfloatPtr {
49-
pub mMember: *mut [f32; 2usize],
28+
pub struct TestDoublePtr {
29+
pub mMember: *mut __BindgenComplex<f64>,
5030
}
5131
#[test]
52-
fn bindgen_test_layout_TestfloatPtr() {
53-
assert_eq!(::std::mem::size_of::<TestfloatPtr>() , 8usize);
54-
assert_eq!(::std::mem::align_of::<TestfloatPtr>() , 8usize);
32+
fn bindgen_test_layout_TestDoublePtr() {
33+
assert_eq!(::std::mem::size_of::<TestDoublePtr>() , 8usize);
34+
assert_eq!(::std::mem::align_of::<TestDoublePtr>() , 8usize);
5535
}
56-
impl Clone for TestfloatPtr {
36+
impl Clone for TestDoublePtr {
5737
fn clone(&self) -> Self { *self }
5838
}
5939
#[repr(C)]
6040
#[derive(Debug, Copy)]
61-
pub struct Testint {
62-
pub mMember: [::std::os::raw::c_int; 2usize],
41+
pub struct TestFloat {
42+
pub mMember: __BindgenComplex<f32>,
6343
}
6444
#[test]
65-
fn bindgen_test_layout_Testint() {
66-
assert_eq!(::std::mem::size_of::<Testint>() , 8usize);
67-
assert_eq!(::std::mem::align_of::<Testint>() , 4usize);
45+
fn bindgen_test_layout_TestFloat() {
46+
assert_eq!(::std::mem::size_of::<TestFloat>() , 8usize);
47+
assert_eq!(::std::mem::align_of::<TestFloat>() , 4usize);
6848
}
69-
impl Clone for Testint {
49+
impl Clone for TestFloat {
7050
fn clone(&self) -> Self { *self }
7151
}
7252
#[repr(C)]
7353
#[derive(Debug, Copy)]
74-
pub struct TestintPtr {
75-
pub mMember: *mut [::std::os::raw::c_int; 2usize],
54+
pub struct TestFloatPtr {
55+
pub mMember: *mut __BindgenComplex<f32>,
7656
}
7757
#[test]
78-
fn bindgen_test_layout_TestintPtr() {
79-
assert_eq!(::std::mem::size_of::<TestintPtr>() , 8usize);
80-
assert_eq!(::std::mem::align_of::<TestintPtr>() , 8usize);
58+
fn bindgen_test_layout_TestFloatPtr() {
59+
assert_eq!(::std::mem::size_of::<TestFloatPtr>() , 8usize);
60+
assert_eq!(::std::mem::align_of::<TestFloatPtr>() , 8usize);
8161
}
82-
impl Clone for TestintPtr {
62+
impl Clone for TestFloatPtr {
8363
fn clone(&self) -> Self { *self }
8464
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
8+
#[repr(C)]
9+
pub struct __BindgenComplex<T> {
10+
pub re: T,
11+
pub im: T,
12+
}
13+
extern "C" {
14+
#[link_name = "globalValueFloat"]
15+
pub static mut globalValueFloat: __BindgenComplex<f32>;
16+
}
17+
extern "C" {
18+
#[link_name = "globalValueDouble"]
19+
pub static mut globalValueDouble: __BindgenComplex<f64>;
20+
}
21+
extern "C" {
22+
#[link_name = "globalValueLongDouble"]
23+
pub static mut globalValueLongDouble: __BindgenComplex<f64>;
24+
}

0 commit comments

Comments
 (0)