From 7063b16a5884f75f7c3e3363481c793c6c618620 Mon Sep 17 00:00:00 2001 From: Porter Smith Date: Sat, 9 Mar 2019 10:59:28 -0800 Subject: [PATCH] add test for issue #1535 --- src/ir/function.rs | 43 +++++++++++-------- .../tests/func_with_func_ptr_arg.rs | 18 ++++++-- tests/headers/func_with_func_ptr_arg.h | 2 +- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/ir/function.rs b/src/ir/function.rs index 5ae7583d5e..f7c393418b 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -314,24 +314,31 @@ fn args_from_ty_and_cursor( cursor: &clang::Cursor, ctx: &mut BindgenContext, ) -> Vec<(Option, TypeId)> { - match (cursor.args(), ty.args()) { - (Some(cursor_args), Some(ty_args)) => { - ty_args.iter().enumerate().map(|(i, ty)| { - let name = cursor_args.get(i) - .map(|c| c.spelling()) - .and_then(|name| if name.is_empty() { None } else { Some(name) }); - (name, Item::from_ty_or_ref(*ty, *cursor, None, ctx)) - }).collect() - } - (Some(cursor_args), None) => { - cursor_args.iter().map(|cursor| { - let name = cursor.spelling(); - let name = if name.is_empty() { None } else { Some(name) }; - (name, Item::from_ty_or_ref(cursor.cur_type(), *cursor, None, ctx)) - }).collect() - } - _ => panic!() - } + let cursor_args = cursor.args().unwrap().into_iter(); + let type_args = ty.args().unwrap_or_else(Vec::new).into_iter(); + + // Argument types can be found in either the cursor or the type, but argument names may only be + // found on the cursor. We often have access to both a type and a cursor, but in some cases we + // may only have one to reference. + cursor_args + .map(Some) + .chain(std::iter::repeat(None)) + .zip( + type_args + .map(Some) + .chain(std::iter::repeat(None)) + ) + .take_while(|(cur, ty)| cur.is_some() || ty.is_some()) + .map(|(arg_cur, arg_ty)| { + let name = arg_cur + .map(|a| a.spelling()) + .and_then(|name| if name.is_empty() { None} else { Some(name) }); + + let cursor = arg_cur.unwrap_or(*cursor); + let ty = arg_ty.unwrap_or(cursor.cur_type()); + (name, Item::from_ty_or_ref(ty, cursor, None, ctx)) + }) + .collect() } impl FunctionSig { diff --git a/tests/expectations/tests/func_with_func_ptr_arg.rs b/tests/expectations/tests/func_with_func_ptr_arg.rs index fed557b816..fe69f59ccb 100644 --- a/tests/expectations/tests/func_with_func_ptr_arg.rs +++ b/tests/expectations/tests/func_with_func_ptr_arg.rs @@ -1,9 +1,19 @@ /* automatically generated by rust-bindgen */ - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] extern "C" { - pub fn foo(bar: ::std::option::Option); + pub fn foo( + one: ::std::option::Option< + unsafe extern "C" fn(a: ::std::os::raw::c_int, b: ::std::os::raw::c_int), + >, + two: ::std::option::Option< + unsafe extern "C" fn(c: ::std::os::raw::c_int, d: ::std::os::raw::c_int), + >, + ); } diff --git a/tests/headers/func_with_func_ptr_arg.h b/tests/headers/func_with_func_ptr_arg.h index 629c84ab90..38ba982816 100644 --- a/tests/headers/func_with_func_ptr_arg.h +++ b/tests/headers/func_with_func_ptr_arg.h @@ -1 +1 @@ -void foo(void (*bar)()); +void foo(void (*one)(int a, int b), void (*two)(int c, int d));