Skip to content

Commit 7fa654c

Browse files
author
bors-servo
authored
Auto merge of #475 - scoopr:objc, r=emilio
objc: Support method arguments Welp, I attempted to get the method arguments working. I must confess, that I have not ran this against actual objective c code yet though.
2 parents 2fdb02f + bc87b2a commit 7fa654c

File tree

6 files changed

+209
-85
lines changed

6 files changed

+209
-85
lines changed

src/clang.rs

+11
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,14 @@ impl Cursor {
523523
pub fn evaluate(&self) -> Option<EvalResult> {
524524
EvalResult::new(*self)
525525
}
526+
527+
/// Return the result type for this cursor
528+
pub fn ret_type(&self) -> Option<Type> {
529+
let rt = Type {
530+
x: unsafe { clang_getCursorResultType(self.x) },
531+
};
532+
if rt.is_valid() { Some(rt) } else { None }
533+
}
526534
}
527535

528536
extern "C" fn visit_children<Visitor>(cur: CXCursor,
@@ -1363,6 +1371,9 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
13631371
prefix,
13641372
type_to_str(ty.kind())));
13651373
}
1374+
if let Some(ty) = c.ret_type() {
1375+
print_indent(depth, format!(" {}ret-type = {}", prefix, type_to_str(ty.kind())));
1376+
}
13661377

13671378
if let Some(refd) = c.referenced() {
13681379
if refd != *c {

src/codegen/mod.rs

+99-66
Original file line numberDiff line numberDiff line change
@@ -2153,61 +2153,8 @@ impl ToRustTy for FunctionSig {
21532153

21542154
fn to_rust_ty(&self, ctx: &BindgenContext, _item: &Item) -> P<ast::Ty> {
21552155
// TODO: we might want to consider ignoring the reference return value.
2156-
let return_item = ctx.resolve_item(self.return_type());
2157-
let ret =
2158-
if let TypeKind::Void = *return_item.kind().expect_type().kind() {
2159-
ast::FunctionRetTy::Default(ctx.span())
2160-
} else {
2161-
ast::FunctionRetTy::Ty(return_item.to_rust_ty(ctx))
2162-
};
2163-
2164-
let mut unnamed_arguments = 0;
2165-
let arguments = self.argument_types().iter().map(|&(ref name, ty)| {
2166-
let arg_item = ctx.resolve_item(ty);
2167-
let arg_ty = arg_item.kind().expect_type();
2168-
2169-
// From the C90 standard[1]:
2170-
//
2171-
// A declaration of a parameter as "array of type" shall be
2172-
// adjusted to "qualified pointer to type", where the type
2173-
// qualifiers (if any) are those specified within the [ and ] of
2174-
// the array type derivation.
2175-
//
2176-
// [1]: http://c0x.coding-guidelines.com/6.7.5.3.html
2177-
let arg_ty = match *arg_ty.canonical_type(ctx).kind() {
2178-
TypeKind::Array(t, _) => {
2179-
t.to_rust_ty(ctx).to_ptr(arg_ty.is_const(), ctx.span())
2180-
},
2181-
TypeKind::Pointer(inner) => {
2182-
let inner = ctx.resolve_item(inner);
2183-
let inner_ty = inner.expect_type();
2184-
if let TypeKind::ObjCInterface(_) = *inner_ty.canonical_type(ctx).kind() {
2185-
quote_ty!(ctx.ext_cx(), id)
2186-
} else {
2187-
arg_item.to_rust_ty(ctx)
2188-
}
2189-
},
2190-
_ => {
2191-
arg_item.to_rust_ty(ctx)
2192-
}
2193-
};
2194-
2195-
let arg_name = match *name {
2196-
Some(ref name) => ctx.rust_mangle(name).into_owned(),
2197-
None => {
2198-
unnamed_arguments += 1;
2199-
format!("arg{}", unnamed_arguments)
2200-
}
2201-
};
2202-
2203-
assert!(!arg_name.is_empty());
2204-
2205-
ast::Arg {
2206-
ty: arg_ty,
2207-
pat: aster::AstBuilder::new().pat().id(arg_name),
2208-
id: ast::DUMMY_NODE_ID,
2209-
}
2210-
}).collect::<Vec<_>>();
2156+
let ret = utils::fnsig_return_ty(ctx, &self);
2157+
let arguments = utils::fnsig_arguments(ctx, &self);
22112158

22122159
let decl = P(ast::FnDecl {
22132160
inputs: arguments,
@@ -2217,7 +2164,7 @@ impl ToRustTy for FunctionSig {
22172164

22182165
let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
22192166
unsafety: ast::Unsafety::Unsafe,
2220-
abi: self.abi(),
2167+
abi: self.abi().expect("Invalid abi for function!"),
22212168
lifetimes: vec![],
22222169
decl: decl,
22232170
}));
@@ -2297,7 +2244,8 @@ impl CodeGenerator for Function {
22972244
vis: ast::Visibility::Public,
22982245
};
22992246

2300-
let item = ForeignModBuilder::new(signature.abi())
2247+
let item = ForeignModBuilder::new(signature.abi()
2248+
.expect("Invalid abi for function!"))
23012249
.with_foreign_item(foreign_item)
23022250
.build(ctx);
23032251

@@ -2316,9 +2264,36 @@ impl CodeGenerator for ObjCInterface {
23162264
let mut trait_items = vec![];
23172265

23182266
for method in self.methods() {
2319-
let method_name = ctx.rust_ident(method.name());
2267+
let signature = method.signature();
2268+
let fn_args = utils::fnsig_arguments(ctx, signature);
2269+
let fn_ret = utils::fnsig_return_ty(ctx, signature);
2270+
let sig = aster::AstBuilder::new()
2271+
.method_sig()
2272+
.unsafe_()
2273+
.fn_decl()
2274+
.self_()
2275+
.build(ast::SelfKind::Value(ast::Mutability::Immutable))
2276+
.with_args(fn_args.clone())
2277+
.build(fn_ret);
2278+
2279+
// Collect the actual used argument names
2280+
let arg_names: Vec<_> = fn_args.iter()
2281+
.map(|ref arg| {
2282+
match arg.pat.node {
2283+
ast::PatKind::Ident(_, ref spanning, _) => {
2284+
spanning.node.name.as_str().to_string()
2285+
}
2286+
_ => {
2287+
panic!("odd argument!");
2288+
}
2289+
}
2290+
})
2291+
.collect();
23202292

2321-
let body = quote_stmt!(ctx.ext_cx(), msg_send![self, $method_name])
2293+
let methods_and_args =
2294+
ctx.rust_ident(&method.format_method_call(&arg_names));
2295+
let body =
2296+
quote_stmt!(ctx.ext_cx(), msg_send![self, $methods_and_args])
23222297
.unwrap();
23232298
let block = ast::Block {
23242299
stmts: vec![body],
@@ -2327,13 +2302,6 @@ impl CodeGenerator for ObjCInterface {
23272302
span: ctx.span(),
23282303
};
23292304

2330-
let sig = aster::AstBuilder::new()
2331-
.method_sig()
2332-
.unsafe_()
2333-
.fn_decl()
2334-
.self_()
2335-
.build(ast::SelfKind::Value(ast::Mutability::Immutable))
2336-
.build(ast::FunctionRetTy::Default(ctx.span()));
23372305
let attrs = vec![];
23382306

23392307
let impl_item = ast::ImplItem {
@@ -2697,4 +2665,69 @@ mod utils {
26972665
_ => panic!("How did this happen exactly?"),
26982666
}
26992667
}
2668+
2669+
pub fn fnsig_return_ty(ctx: &BindgenContext,
2670+
sig: &super::FunctionSig)
2671+
-> ast::FunctionRetTy {
2672+
let return_item = ctx.resolve_item(sig.return_type());
2673+
if let TypeKind::Void = *return_item.kind().expect_type().kind() {
2674+
ast::FunctionRetTy::Default(ctx.span())
2675+
} else {
2676+
ast::FunctionRetTy::Ty(return_item.to_rust_ty(ctx))
2677+
}
2678+
}
2679+
2680+
pub fn fnsig_arguments(ctx: &BindgenContext,
2681+
sig: &super::FunctionSig)
2682+
-> Vec<ast::Arg> {
2683+
use super::ToPtr;
2684+
let mut unnamed_arguments = 0;
2685+
sig.argument_types().iter().map(|&(ref name, ty)| {
2686+
let arg_item = ctx.resolve_item(ty);
2687+
let arg_ty = arg_item.kind().expect_type();
2688+
2689+
// From the C90 standard[1]:
2690+
//
2691+
// A declaration of a parameter as "array of type" shall be
2692+
// adjusted to "qualified pointer to type", where the type
2693+
// qualifiers (if any) are those specified within the [ and ] of
2694+
// the array type derivation.
2695+
//
2696+
// [1]: http://c0x.coding-guidelines.com/6.7.5.3.html
2697+
let arg_ty = match *arg_ty.canonical_type(ctx).kind() {
2698+
TypeKind::Array(t, _) => {
2699+
t.to_rust_ty(ctx).to_ptr(arg_ty.is_const(), ctx.span())
2700+
},
2701+
TypeKind::Pointer(inner) => {
2702+
let inner = ctx.resolve_item(inner);
2703+
let inner_ty = inner.expect_type();
2704+
if let TypeKind::ObjCInterface(_) = *inner_ty.canonical_type(ctx).kind() {
2705+
quote_ty!(ctx.ext_cx(), id)
2706+
} else {
2707+
arg_item.to_rust_ty(ctx)
2708+
}
2709+
},
2710+
_ => {
2711+
arg_item.to_rust_ty(ctx)
2712+
}
2713+
};
2714+
2715+
let arg_name = match *name {
2716+
Some(ref name) => ctx.rust_mangle(name).into_owned(),
2717+
None => {
2718+
unnamed_arguments += 1;
2719+
format!("arg{}", unnamed_arguments)
2720+
}
2721+
};
2722+
2723+
assert!(!arg_name.is_empty());
2724+
2725+
ast::Arg {
2726+
ty: arg_ty,
2727+
pat: aster::AstBuilder::new().pat().id(arg_name),
2728+
id: ast::DUMMY_NODE_ID,
2729+
}
2730+
}).collect::<Vec<_>>()
2731+
}
2732+
27002733
}

src/ir/function.rs

+23-12
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,19 @@ pub struct FunctionSig {
7373
is_variadic: bool,
7474

7575
/// The ABI of this function.
76-
abi: abi::Abi,
76+
abi: Option<abi::Abi>,
7777
}
7878

79-
fn get_abi(cc: CXCallingConv) -> abi::Abi {
79+
fn get_abi(cc: CXCallingConv) -> Option<abi::Abi> {
8080
use clang_sys::*;
8181
match cc {
82-
CXCallingConv_Default => abi::Abi::C,
83-
CXCallingConv_C => abi::Abi::C,
84-
CXCallingConv_X86StdCall => abi::Abi::Stdcall,
85-
CXCallingConv_X86FastCall => abi::Abi::Fastcall,
86-
CXCallingConv_AAPCS => abi::Abi::Aapcs,
87-
CXCallingConv_X86_64Win64 => abi::Abi::Win64,
82+
CXCallingConv_Default => Some(abi::Abi::C),
83+
CXCallingConv_C => Some(abi::Abi::C),
84+
CXCallingConv_X86StdCall => Some(abi::Abi::Stdcall),
85+
CXCallingConv_X86FastCall => Some(abi::Abi::Fastcall),
86+
CXCallingConv_AAPCS => Some(abi::Abi::Aapcs),
87+
CXCallingConv_X86_64Win64 => Some(abi::Abi::Win64),
88+
CXCallingConv_Invalid => None,
8889
other => panic!("unsupported calling convention: {:?}", other),
8990
}
9091
}
@@ -116,7 +117,7 @@ impl FunctionSig {
116117
pub fn new(return_type: ItemId,
117118
arguments: Vec<(Option<String>, ItemId)>,
118119
is_variadic: bool,
119-
abi: abi::Abi)
120+
abi: Option<abi::Abi>)
120121
-> Self {
121122
FunctionSig {
122123
return_type: return_type,
@@ -154,7 +155,8 @@ impl FunctionSig {
154155
let mut args: Vec<_> = match cursor.kind() {
155156
CXCursor_FunctionDecl |
156157
CXCursor_Constructor |
157-
CXCursor_CXXMethod => {
158+
CXCursor_CXXMethod |
159+
CXCursor_ObjCInstanceMethodDecl => {
158160
// For CXCursor_FunctionDecl, cursor.args() is the reliable way
159161
// to get parameter names and types.
160162
cursor.args()
@@ -218,10 +220,19 @@ impl FunctionSig {
218220
}
219221
}
220222

221-
let ty_ret_type = try!(ty.ret_type().ok_or(ParseError::Continue));
223+
let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl {
224+
try!(cursor.ret_type().ok_or(ParseError::Continue))
225+
} else {
226+
try!(ty.ret_type().ok_or(ParseError::Continue))
227+
};
222228
let ret = Item::from_ty_or_ref(ty_ret_type, None, None, ctx);
223229
let abi = get_abi(ty.call_conv());
224230

231+
if abi.is_none() {
232+
assert_eq!(cursor.kind(), CXCursor_ObjCInstanceMethodDecl,
233+
"Invalid ABI for function signature")
234+
}
235+
225236
Ok(Self::new(ret, args, ty.is_variadic(), abi))
226237
}
227238

@@ -236,7 +247,7 @@ impl FunctionSig {
236247
}
237248

238249
/// Get this function signature's ABI.
239-
pub fn abi(&self) -> abi::Abi {
250+
pub fn abi(&self) -> Option<abi::Abi> {
240251
self.abi
241252
}
242253

0 commit comments

Comments
 (0)