diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gen.rs | 38 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/parser.rs | 72 | ||||
-rw-r--r-- | src/types.rs | 18 |
4 files changed, 93 insertions, 37 deletions
@@ -211,10 +211,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> GFunc(vi) => { let v = vi.borrow(); match v.ty { - TFunc(ref rty, ref aty, var, abi) => { + TFuncPtr(ref sig) => { let decl = cfunc_to_rs(&mut ctx, v.name.clone(), - &**rty, aty.as_slice(), var); - (abi, decl) + &*sig.ret_ty, sig.args.as_slice(), + sig.is_variadic); + (sig.abi, decl) } _ => unreachable!() } @@ -237,7 +238,9 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> map }; - defs.push(mk_extern(&mut ctx, links, vars, abi::C)); + if !Vec::is_empty(&vars) { + defs.push(mk_extern(&mut ctx, links, vars, abi::C)); + } for (abi, funcs) in funcs.into_iter() { defs.push(mk_extern(&mut ctx, links, funcs, abi)); @@ -489,7 +492,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: String, members: Vec<CompMember>) -> Ve } else { rust_type_id(ctx, f.name.clone()) }; - + let f_ty = P(cty_to_rs(ctx, &f.ty)); fields.push(respan(ctx.span, ast::StructField_ { @@ -926,9 +929,13 @@ fn cty_to_rs(ctx: &mut GenCtx, ty: &Type) -> ast::Ty { let ty = cty_to_rs(ctx, &**t); mk_arrty(ctx, &ty, s) }, - &TFunc(ref rty, ref atys, var, abi) => { - let decl = cfuncty_to_rs(ctx, &**rty, atys.as_slice(), var); - mk_fnty(ctx, &decl, abi) + &TFuncPtr(ref sig) => { + let decl = cfuncty_to_rs(ctx, &*sig.ret_ty, sig.args.as_slice(), sig.is_variadic); + mk_fnty(ctx, &decl, sig.abi) + }, + &TFuncProto(ref sig) => { + let decl = cfuncty_to_rs(ctx, &*sig.ret_ty, sig.args.as_slice(), sig.is_variadic); + mk_fn_proto_ty(ctx, &decl, sig.abi) }, &TNamed(ref ti) => { let id = rust_type_id(ctx, ti.borrow().name.clone()); @@ -1005,6 +1012,21 @@ fn mk_arrty(ctx: &GenCtx, base: &ast::Ty, n: uint) -> ast::Ty { }; } +fn mk_fn_proto_ty(ctx: &mut GenCtx, decl: &ast::FnDecl, abi: abi::Abi) -> ast::Ty { + let fnty = ast::TyBareFn(P(ast::BareFnTy { + unsafety: ast::Unsafety::Normal, + abi: abi, + lifetimes: Vec::new(), + decl: P(decl.clone()) + })); + + ast::Ty { + id: ast::DUMMY_NODE_ID, + node: fnty, + span: ctx.span, + } +} + fn mk_fnty(ctx: &mut GenCtx, decl: &ast::FnDecl, abi: abi::Abi) -> ast::Ty { let fnty = ast::TyBareFn(P(ast::BareFnTy { unsafety: ast::Unsafety::Normal, @@ -22,6 +22,7 @@ use types::Global; mod types; mod clangll; +#[allow(dead_code)] mod clang; mod gen; mod parser; @@ -59,6 +60,7 @@ impl Default for BindgenOptions { } } +#[deriving(Copy)] pub enum LinkType { Default, Static, diff --git a/src/parser.rs b/src/parser.rs index c4291d5e..2622a944 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -168,22 +168,14 @@ fn conv_ptr_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor, layout: let ret_ty = ty.ret_type(); let decl = ty.declaration(); return if ret_ty.kind() != CXType_Invalid { - let mut args_lst = vec!(); - cursor.visit(|c, _| { - if c.kind() == CXCursor_ParmDecl { - args_lst.push((c.spelling(), conv_ty(ctx, &c.cur_type(), c))); - } - CXChildVisit_Continue - }); - - let ret_ty = box conv_ty(ctx, &ret_ty, cursor); - let abi = get_abi(ty.call_conv()); - - TFunc(ret_ty, args_lst, ty.is_variadic(), abi) + TFuncPtr(mk_fn_sig(ctx, ty, cursor)) } else if decl.kind() != CXCursor_NoDeclFound { - TPtr(box conv_decl_ty(ctx, &decl), is_const, layout) + TPtr(box conv_decl_ty(ctx, &decl), ty.is_const(), layout) + } else if cursor.kind() == CXCursor_VarDecl { + let can_ty = ty.canonical_type(); + conv_ty(ctx, &can_ty, cursor) } else { - TPtr(box TVoid, is_const, layout) + TPtr(box TVoid, ty.is_const(), layout) }; } CXType_Typedef => { @@ -200,6 +192,41 @@ fn conv_ptr_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor, layout: } } +fn mk_fn_sig(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::FuncSig { + let args_lst: Vec<(String, il::Type)> = match cursor.kind() { + CXCursor_FunctionDecl => { + // For CXCursor_FunctionDecl, cursor.args() is the reliable way to + // get parameter names and types. + cursor.args().iter().map(|arg| { + let arg_name = arg.spelling(); + (arg_name, conv_ty(ctx, &arg.cur_type(), arg)) + }).collect() + } + _ => { + // For non-CXCursor_FunctionDecl, visiting the cursor's children is + // the only reliable way to get parameter names. + let mut args_lst = vec!(); + cursor.visit(|c, _| { + if c.kind() == CXCursor_ParmDecl { + args_lst.push((c.spelling(), conv_ty(ctx, &c.cur_type(), c))); + } + CXChildVisit_Continue + }); + args_lst + } + }; + + let ret_ty = box conv_ty(ctx, &ty.ret_type(), cursor); + let abi = get_abi(ty.call_conv()); + + il::FuncSig { + ret_ty: ret_ty, + args: args_lst, + is_variadic: ty.is_variadic(), + abi: abi, + } +} + fn conv_decl_ty(ctx: &mut ClangParserCtx, cursor: &Cursor) -> il::Type { return match cursor.kind() { CXCursor_StructDecl => { @@ -227,7 +254,7 @@ fn conv_decl_ty(ctx: &mut ClangParserCtx, cursor: &Cursor) -> il::Type { } fn conv_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::Type { - debug!("conv_ty: ty=`{}`", type_to_str(ty.kind())); + debug!("conv_ty: ty=`{}` sp=`{}` loc=`{}`", type_to_str(ty.kind()), cursor.spelling(), cursor.location()); let layout = Layout::new(ty.size(), ty.align()); return match ty.kind() { CXType_Void | CXType_Invalid => TVoid, @@ -251,6 +278,7 @@ fn conv_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::Type CXType_VariableArray | CXType_DependentSizedArray | CXType_IncompleteArray => { conv_ptr_ty(ctx, &ty.elem_type(), cursor, layout) } + CXType_FunctionProto => TFuncProto(mk_fn_sig(ctx, ty, cursor)), CXType_Record | CXType_Typedef | CXType_Unexposed | @@ -349,7 +377,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, if let Some(CompMember::Comp(c)) = members.pop() { members.push(CompMember::CompField(c, field)); } else { - panic!(); // Checks in is_composite make this unreachable. + unreachable!(); // Checks in is_composite make this unreachable. } } else { members.push(CompMember::Field(field)); @@ -431,19 +459,11 @@ fn visit_top<'r>(cursor: &Cursor, return CXChildVisit_Continue; } - let args_lst: Vec<(String, il::Type)> = cursor.args().iter().map(|arg| { - let arg_name = arg.spelling(); - (arg_name, conv_ty(ctx, &arg.cur_type(), cursor)) - }).collect(); - - let ty = cursor.cur_type(); - let ret_ty = box conv_ty(ctx, &cursor.ret_type(), cursor); - let abi = get_abi(ty.call_conv()); - let func = decl_name(ctx, cursor); let vi = func.varinfo(); let mut vi = vi.borrow_mut(); - vi.ty = TFunc(ret_ty.clone(), args_lst.clone(), ty.is_variadic(), abi); + + vi.ty = TFuncPtr(mk_fn_sig(ctx, &cursor.cur_type(), cursor)); ctx.globals.push(func); return CXChildVisit_Continue; diff --git a/src/types.rs b/src/types.rs index 1a0b353b..fbd108b2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -70,18 +70,28 @@ impl fmt::Show for Global { } #[deriving(Clone, PartialEq)] +pub struct FuncSig { + pub ret_ty: Box<Type>, + pub args: Vec<(String, Type)>, + pub is_variadic: bool, + pub abi: abi::Abi, +} + +#[deriving(Clone, PartialEq)] pub enum Type { TVoid, TInt(IKind, Layout), TFloat(FKind, Layout), TPtr(Box<Type>, bool, Layout), TArray(Box<Type>, uint, Layout), - TFunc(Box<Type>, Vec<(String, Type)>, bool, abi::Abi), + TFuncProto(FuncSig), + TFuncPtr(FuncSig), TNamed(Rc<RefCell<TypeInfo>>), TComp(Rc<RefCell<CompInfo>>), TEnum(Rc<RefCell<EnumInfo>>) } +#[allow(dead_code)] impl Type { pub fn size(&self) -> uint { match self { @@ -93,7 +103,8 @@ impl Type { &TComp(ref ci) => ci.borrow().layout.size, &TEnum(ref ei) => ei.borrow().layout.size, &TVoid => 0, - &TFunc(..) => 0, + &TFuncProto(..) => 0, + &TFuncPtr(..) => 0, } } @@ -107,7 +118,8 @@ impl Type { &TComp(ref ci) => ci.borrow().layout.align, &TEnum(ref ei) => ei.borrow().layout.align, &TVoid => 0, - &TFunc(..) => 0, + &TFuncProto(..) => 0, + &TFuncPtr(..) => 0, } } } |