Skip to content

Commit

Permalink
Add an alternate path determining the arguments for a function.
Browse files Browse the repository at this point in the history
This fixes the issue seen in #1500 where function
pointers as a return type have their parameters incorrectly generated.
  • Loading branch information
Your Name committed Jan 31, 2019
1 parent 86eff21 commit 2894f7d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 18 deletions.
53 changes: 36 additions & 17 deletions src/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,33 +550,27 @@ impl Cursor {

/// Given that this cursor's referent is a function, return cursors to its
/// parameters.
///
/// Returns None if the cursor's referent is not a function/method call or
/// declaration.
pub fn args(&self) -> Option<Vec<Cursor>> {
// XXX: We might want to use and keep num_args
// match self.kind() {
// CXCursor_FunctionDecl |
// CXCursor_CXXMethod => {
unsafe {
let w = clang_Cursor_getNumArguments(self.x);
if w == -1 {
None
} else {
let num = w as u32;

let mut args = vec![];
for i in 0..num {
args.push(Cursor {
x: clang_Cursor_getArgument(self.x, i as c_uint),
});
self.num_args().ok().map(|num| {
(0..num).map(|i| {
Cursor {
x: unsafe { clang_Cursor_getArgument(self.x, i as c_uint) },
}
Some(args)
}
}
})
.collect::<Vec<Cursor>>()
})
}

/// Given that this cursor's referent is a function/method call or
/// declaration, return the number of arguments it takes.
///
/// Returns -1 if the cursor's referent is not a function/method call or
/// Returns Err if the cursor's referent is not a function/method call or
/// declaration.
pub fn num_args(&self) -> Result<u32, ()> {
unsafe {
Expand Down Expand Up @@ -1017,6 +1011,31 @@ impl Type {
})
}

/// Given that this type is a function prototype, return the types of its parameters.
///
/// Returns None if the type is not a function prototype.
pub fn args(&self) -> Option<Vec<Type>> {
self.num_args().ok().map(|num| {
(0..num).map(|i| {
Type {
x: unsafe { clang_getArgType(self.x, i as c_uint) },
}
})
.collect::<Vec<Type>>()
})
}

/// Given that this type is a function prototype, return the number of arguments it takes.
///
/// Returns Err if the type is not a function prototype.
pub fn num_args(&self) -> Result<u32, ()> {
unsafe {
let w = clang_getNumArgTypes(self.x);
if w == -1 { Err(()) } else { Ok(w as u32) }
}
}


/// Given that this type is a pointer type, return the type that it points
/// to.
pub fn pointee_type(&self) -> Option<Type> {
Expand Down
18 changes: 17 additions & 1 deletion src/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,17 @@ impl FunctionSig {
})
.collect()
}
CXCursor_NoDeclFound => {
ty
.args()
.unwrap()
.iter()
.map(|arg| {
let ty = Item::from_ty_or_ref(*arg, cursor, None, ctx);
(None, ty)
})
.collect()
}
_ => {
// For non-CXCursor_FunctionDecl, visiting the cursor's children
// is the only reliable way to get parameter names.
Expand Down Expand Up @@ -451,7 +462,12 @@ impl FunctionSig {
} else {
ty.ret_type().ok_or(ParseError::Continue)?
};
let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);

let ret = Item::from_ty_or_ref(
ty_ret_type,
ty_ret_type.declaration(),
None,
ctx);

// Clang plays with us at "find the calling convention", see #549 and
// co. This seems to be a better fix than that commit.
Expand Down
18 changes: 18 additions & 0 deletions tests/expectations/tests/func_ptr_return_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* automatically generated by rust-bindgen */

#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

extern "C" {
pub fn func() -> ::std::option::Option<
unsafe extern "C" fn(
arg1: ::std::os::raw::c_int,
arg2: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int,
>;
}

1 change: 1 addition & 0 deletions tests/headers/func_ptr_return_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int (*func(void))(int, int);

0 comments on commit 2894f7d

Please sign in to comment.