Skip to content

Commit 043de68

Browse files
committed
Merge pull request rust-lang#1 from emilio/wip
bindgen: Restructure opaque and blacklisting so we can fix debug deriving
2 parents 447afe1 + 24a3c4f commit 043de68

File tree

5 files changed

+168
-134
lines changed

5 files changed

+168
-134
lines changed

src/gen.rs

Lines changed: 35 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -376,65 +376,13 @@ fn gen_mod(mut ctx: &mut GenCtx,
376376
}
377377
}
378378

379-
// XXX: Replace the name-based lookup, or do it at parse-time,
380-
// to keep all the mess in the same place.
381-
fn type_opaque(ctx: &GenCtx, ty: &Type) -> bool {
382-
match *ty {
383-
TComp(ref ci) if ci.borrow().opaque => return true,
384-
_ => {}
385-
}
386-
387-
let ty_name = ty.name();
388-
389-
match ty_name {
390-
Some(ty_name)
391-
=> ctx.options.opaque_types.iter().any(|name| *name == ty_name),
392-
None => false,
393-
}
394-
}
395-
396-
fn global_opaque(ctx: &GenCtx, global: &Global) -> bool {
397-
let global_name = global.name();
398-
399-
match *global {
400-
GCompDecl(ref ci) |
401-
GComp(ref ci) if ci.borrow().opaque => return true,
402-
_ => {}
403-
}
404-
405-
// Can't make an opaque type without layout
406-
global.layout().is_some() &&
407-
ctx.options.opaque_types.iter().any(|name| *name == global_name)
408-
}
409-
410-
fn type_blacklisted(ctx: &GenCtx, global: &Global) -> bool {
411-
let global_name = global.name();
412-
413-
ctx.options.blacklist_type.iter().any(|name| *name == global_name)
414-
}
415-
416379
fn gen_global(mut ctx: &mut GenCtx,
417380
g: Global,
418381
defs: &mut Vec<P<ast::Item>>) {
419-
// XXX unify with anotations both type_blacklisted
420-
// and type_opaque (which actually doesn't mean the same).
421-
if type_blacklisted(ctx, &g) {
422-
return;
423-
}
424-
425-
if global_opaque(ctx, &g) {
426-
let name = first(rust_id(ctx, &g.name()));
427-
let layout = g.layout().unwrap();
428-
defs.push(mk_opaque_struct(ctx, &name, &layout));
429-
// This should always be true but anyways..
430-
defs.push(mk_test_fn(ctx, &name, &layout));
431-
return;
432-
}
433-
434382
match g {
435383
GType(ti) => {
436384
let t = ti.borrow().clone();
437-
defs.push(ctypedef_to_rs(&mut ctx, t))
385+
defs.extend(ctypedef_to_rs(&mut ctx, t).into_iter())
438386
},
439387
GCompDecl(ci) => {
440388
let c = ci.borrow().clone();
@@ -802,7 +750,7 @@ fn tag_dup_decl(gs: &[Global]) -> Vec<Global> {
802750
res
803751
}
804752

805-
fn ctypedef_to_rs(ctx: &mut GenCtx, ty: TypeInfo) -> P<ast::Item> {
753+
fn ctypedef_to_rs(ctx: &mut GenCtx, ty: TypeInfo) -> Vec<P<ast::Item>> {
806754
fn mk_item(ctx: &mut GenCtx, name: &str, comment: &str, ty: &Type) -> P<ast::Item> {
807755
let rust_name = rust_type_id(ctx, name);
808756
let rust_ty = if cty_is_translatable(ty) {
@@ -829,7 +777,14 @@ fn ctypedef_to_rs(ctx: &mut GenCtx, ty: TypeInfo) -> P<ast::Item> {
829777
})
830778
}
831779

832-
match ty.ty {
780+
if ty.opaque {
781+
return vec![
782+
mk_opaque_struct(ctx, &ty.name, &ty.layout),
783+
mk_test_fn(ctx, &ty.name, &ty.layout),
784+
];
785+
}
786+
787+
let item = match ty.ty {
833788
TComp(ref ci) => {
834789
assert!(!ci.borrow().name.is_empty());
835790
mk_item(ctx, &ty.name, &ty.comment, &ty.ty)
@@ -839,11 +794,26 @@ fn ctypedef_to_rs(ctx: &mut GenCtx, ty: TypeInfo) -> P<ast::Item> {
839794
mk_item(ctx, &ty.name, &ty.comment, &ty.ty)
840795
},
841796
_ => mk_item(ctx, &ty.name, &ty.comment, &ty.ty),
842-
}
797+
};
798+
799+
vec![item]
843800
}
844801

845802
fn comp_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo)
846803
-> Vec<P<ast::Item>> {
804+
if ci.hide {
805+
return vec![];
806+
}
807+
808+
if ci.opaque {
809+
let name = first(rust_id(ctx, &ci.name));
810+
// The test should always be correct but...
811+
return vec![
812+
mk_opaque_struct(ctx, &name, &ci.layout),
813+
mk_test_fn(ctx, &name, &ci.layout),
814+
];
815+
}
816+
847817
match ci.kind {
848818
CompKind::Struct => cstruct_to_rs(ctx, name, ci),
849819
CompKind::Union => cunion_to_rs(ctx, name, ci),
@@ -852,27 +822,19 @@ fn comp_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo)
852822

853823
fn comp_attrs(ctx: &GenCtx, ci: &CompInfo, name: &str, has_destructor: bool, extra: &mut Vec<P<ast::Item>>) -> Vec<ast::Attribute> {
854824
let mut attrs = mk_doc_attr(ctx, &ci.comment);
855-
attrs.push(mk_repr_attr(ctx, ci.layout));
825+
attrs.push(mk_repr_attr(ctx, &ci.layout));
856826
let mut derives = vec![];
857827

828+
if ci.can_derive_debug() && ctx.options.derive_debug {
829+
derives.push("Debug");
830+
}
858831

859832
if has_destructor {
860833
for attr in ctx.options.dtor_attrs.iter() {
861834
let attr = ctx.ext_cx.ident_of(attr);
862835
attrs.push(quote_attr!(&ctx.ext_cx, #[$attr]));
863836
}
864837
} else {
865-
// TODO: make can_derive_debug more reliable in presence of opaque types and all that stuff
866-
let can_derive_debug = ci.members.iter()
867-
.all(|member| match *member {
868-
CompMember::Field(ref f) |
869-
CompMember::CompField(_, ref f) => f.ty.can_derive_debug(),
870-
_ => true
871-
});
872-
873-
if can_derive_debug && ctx.options.derive_debug {
874-
derives.push("Debug");
875-
}
876838
derives.push("Copy");
877839

878840
// TODO: make mk_clone_impl work for template arguments,
@@ -906,8 +868,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
906868
let mut unnamed: u32 = 0;
907869
let mut bitfields: u32 = 0;
908870

909-
if ci.hide ||
910-
ci.has_non_type_template_params ||
871+
if ci.has_non_type_template_params ||
911872
template_args.iter().any(|f| f == &TVoid) {
912873
return vec!();
913874
}
@@ -978,7 +939,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
978939
let vf_name = format!("_vftable_{}", name);
979940
let item = P(ast::Item {
980941
ident: ctx.ext_cx.ident_of(&vf_name),
981-
attrs: vec!(mk_repr_attr(ctx, layout)),
942+
attrs: vec!(mk_repr_attr(ctx, &layout)),
982943
id: ast::DUMMY_NODE_ID,
983944
node: ast::ItemKind::Struct(
984945
ast::VariantData::Struct(vffields, ast::DUMMY_NODE_ID),
@@ -1060,7 +1021,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
10601021
drop(f.ty); // to ensure it's not used unintentionally
10611022

10621023
let is_translatable = cty_is_translatable(&f_ty);
1063-
if !is_translatable || type_opaque(ctx, &f_ty) {
1024+
if !is_translatable || f_ty.is_opaque() {
10641025
// Be conservative here and assume it might have a
10651026
// destructor or some other serious constraint.
10661027
has_destructor = true;
@@ -1814,7 +1775,7 @@ fn mk_link_name_attr(ctx: &mut GenCtx, name: String) -> ast::Attribute {
18141775
respan(ctx.span, attr)
18151776
}
18161777

1817-
fn mk_repr_attr(ctx: &GenCtx, layout: Layout) -> ast::Attribute {
1778+
fn mk_repr_attr(ctx: &GenCtx, layout: &Layout) -> ast::Attribute {
18181779
let mut values = vec!(P(respan(ctx.span, ast::MetaItemKind::Word(InternedString::new("C")))));
18191780
if layout.packed {
18201781
values.push(P(respan(ctx.span, ast::MetaItemKind::Word(InternedString::new("packed")))));
@@ -2300,7 +2261,6 @@ fn mk_test_fn(ctx: &GenCtx, name: &str, layout: &Layout) -> P<ast::Item> {
23002261
}
23012262

23022263
fn mk_opaque_struct(ctx: &GenCtx, name: &str, layout: &Layout) -> P<ast::Item> {
2303-
// XXX prevent this spurious clone
23042264
let blob_field = mk_blob_field(ctx, "_bindgen_opaque_blob", layout);
23052265
let variant_data = if layout.size == 0 {
23062266
ast::VariantData::Unit(ast::DUMMY_NODE_ID)
@@ -2322,7 +2282,7 @@ fn mk_opaque_struct(ctx: &GenCtx, name: &str, layout: &Layout) -> P<ast::Item> {
23222282

23232283
P(ast::Item {
23242284
ident: ctx.ext_cx.ident_of(&name),
2325-
attrs: vec![mk_repr_attr(ctx, layout.clone())],
2285+
attrs: vec![mk_repr_attr(ctx, layout)],
23262286
id: ast::DUMMY_NODE_ID,
23272287
node: def,
23282288
vis: ast::Visibility::Public,

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ fn parse_headers(options: &BindgenOptions, logger: &Logger) -> Result<ModuleMap,
287287
}
288288
}
289289

290+
// TODO: Unify most of these with BindgenOptions?
290291
let clang_opts = parser::ClangParserOptions {
291292
builtin_names: builtin_names(),
292293
builtins: options.builtins,
@@ -297,6 +298,8 @@ fn parse_headers(options: &BindgenOptions, logger: &Logger) -> Result<ModuleMap,
297298
enable_cxx_namespaces: options.enable_cxx_namespaces,
298299
override_enum_ty: str_to_ikind(&options.override_enum_ty),
299300
clang_args: options.clang_args.clone(),
301+
opaque_types: options.opaque_types.clone(),
302+
blacklist_type: options.blacklist_type.clone(),
300303
};
301304

302305
parser::parse(clang_opts, logger)

src/parser.rs

Lines changed: 70 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub struct ClangParserOptions {
2626
pub enable_cxx_namespaces: bool,
2727
pub override_enum_ty: Option<il::IKind>,
2828
pub clang_args: Vec<String>,
29+
pub opaque_types: Vec<String>,
30+
pub blacklist_type: Vec<String>,
2931
}
3032

3133
struct ClangParserCtx<'a> {
@@ -84,56 +86,40 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
8486
_ => "".to_string()
8587
};
8688
let glob_decl = match cursor.kind() {
89+
CXCursor_UnionDecl |
90+
CXCursor_ClassTemplate |
91+
CXCursor_ClassDecl |
8792
CXCursor_StructDecl => {
88-
let ci = Rc::new(RefCell::new(CompInfo::new(spelling, ctx.current_module_id, filename, comment, CompKind::Struct, vec!(), layout)));
89-
GCompDecl(ci)
90-
}
91-
CXCursor_UnionDecl => {
92-
let ci = Rc::new(RefCell::new(CompInfo::new(spelling, ctx.current_module_id, filename, comment, CompKind::Union, vec!(), layout)));
93-
GCompDecl(ci)
94-
}
95-
CXCursor_EnumDecl => {
96-
let kind = match override_enum_ty {
97-
Some(t) => t,
98-
None => match cursor.enum_type().kind() {
99-
CXType_SChar | CXType_Char_S => ISChar,
100-
CXType_UChar | CXType_Char_U => IUChar,
101-
CXType_UShort => IUShort,
102-
CXType_UInt => IUInt,
103-
CXType_ULong => IULong,
104-
CXType_ULongLong => IULongLong,
105-
CXType_Short => IShort,
106-
CXType_Int => IInt,
107-
CXType_Long => ILong,
108-
CXType_LongLong => ILongLong,
109-
_ => IInt,
110-
}
93+
let kind = if cursor.kind() == CXCursor_UnionDecl {
94+
CompKind::Union
95+
} else {
96+
CompKind::Struct
11197
};
11298

113-
let ei = Rc::new(RefCell::new(EnumInfo::new(spelling, ctx.current_module_id, filename, kind, vec!(), layout)));
114-
GEnumDecl(ei)
115-
}
116-
CXCursor_ClassTemplate => {
117-
let ci = Rc::new(RefCell::new(CompInfo::new(spelling, ctx.current_module_id, filename, comment, CompKind::Struct, vec!(), layout)));
118-
GCompDecl(ci)
119-
}
120-
CXCursor_ClassDecl => {
99+
let opaque = ctx.options.opaque_types.iter().any(|name| *name == spelling);
100+
let hide = ctx.options.blacklist_type.iter().any(|name| *name == spelling);
101+
121102
let mut has_non_type_template_params = false;
122-
let args = match ty.num_template_args() {
123-
-1 => vec!(),
124-
len => {
125-
let mut list = Vec::with_capacity(len as usize);
126-
for i in 0..len {
127-
let arg_type = ty.template_arg_type(i);
128-
if arg_type.kind() != CXType_Invalid {
129-
list.push(conv_ty(ctx, &arg_type, &cursor));
130-
} else {
131-
has_non_type_template_params = true;
132-
ctx.logger.warn("warning: Template parameter is not a type");
103+
let args = match cursor.kind() {
104+
CXCursor_ClassDecl => {
105+
match ty.num_template_args() {
106+
-1 => vec![],
107+
len => {
108+
let mut list = Vec::with_capacity(len as usize);
109+
for i in 0..len {
110+
let arg_type = ty.template_arg_type(i);
111+
if arg_type.kind() != CXType_Invalid {
112+
list.push(conv_ty(ctx, &arg_type, &cursor));
113+
} else {
114+
has_non_type_template_params = true;
115+
ctx.logger.warn("warning: Template parameter is not a type");
116+
}
117+
}
118+
list
133119
}
134120
}
135-
list
136121
}
122+
_ => vec![],
137123
};
138124

139125
let module_id = if args.is_empty() {
@@ -154,13 +140,42 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
154140
})
155141
};
156142

157-
let ci = Rc::new(RefCell::new(CompInfo::new(spelling, module_id, filename, comment, CompKind::Struct, vec!(), layout)));
158-
ci.borrow_mut().args = args;
159-
ci.borrow_mut().has_non_type_template_params = has_non_type_template_params;
143+
let mut ci = CompInfo::new(spelling, module_id, filename, comment, kind, vec![], layout);
144+
ci.opaque = opaque;
145+
ci.hide = hide;
146+
ci.args = args;
147+
ci.has_non_type_template_params = has_non_type_template_params;
148+
149+
let ci = Rc::new(RefCell::new(ci));
160150
GCompDecl(ci)
161151
}
152+
CXCursor_EnumDecl => {
153+
let kind = match override_enum_ty {
154+
Some(t) => t,
155+
None => match cursor.enum_type().kind() {
156+
CXType_SChar | CXType_Char_S => ISChar,
157+
CXType_UChar | CXType_Char_U => IUChar,
158+
CXType_UShort => IUShort,
159+
CXType_UInt => IUInt,
160+
CXType_ULong => IULong,
161+
CXType_ULongLong => IULongLong,
162+
CXType_Short => IShort,
163+
CXType_Int => IInt,
164+
CXType_Long => ILong,
165+
CXType_LongLong => ILongLong,
166+
_ => IInt,
167+
}
168+
};
169+
170+
let ei = Rc::new(RefCell::new(EnumInfo::new(spelling, ctx.current_module_id, filename, kind, vec!(), layout)));
171+
GEnumDecl(ei)
172+
}
162173
CXCursor_TypeAliasDecl | CXCursor_TypedefDecl => {
163-
let ti = Rc::new(RefCell::new(TypeInfo::new(spelling, ctx.current_module_id, TVoid, layout)));
174+
let opaque = ctx.options.opaque_types.iter().any(|name| *name == spelling);
175+
let mut ti = TypeInfo::new(spelling, ctx.current_module_id, TVoid, layout);
176+
ti.opaque = opaque;
177+
178+
let ti = Rc::new(RefCell::new(ti));
164179
GType(ti)
165180
}
166181
CXCursor_VarDecl => {
@@ -901,12 +916,15 @@ fn visit_top(cursor: &Cursor,
901916
let mut ci_ = ci.borrow_mut();
902917
visit_composite(c, p, ctx_, &mut ci_)
903918
});
919+
904920
if anno.opaque {
905921
ci.borrow_mut().opaque = true;
906922
}
923+
907924
if anno.hide {
908925
ci.borrow_mut().hide = true;
909926
}
927+
910928
if let Some(other_type_name) = anno.use_as {
911929
ci.borrow_mut().name = other_type_name.clone();
912930
ctx_.current_module_mut().translations.insert(other_type_name, GComp(ci));
@@ -1003,6 +1021,11 @@ fn visit_top(cursor: &Cursor,
10031021
let ti = typedef.typeinfo();
10041022
let mut ti = ti.borrow_mut();
10051023
ti.ty = ty.clone();
1024+
1025+
if anno.opaque {
1026+
ti.opaque = true;
1027+
}
1028+
10061029
ti.comment = cursor.raw_comment();
10071030
ctx.current_module_mut().globals.push(typedef);
10081031

0 commit comments

Comments
 (0)