Merge pull request #41 from ubsan/master

Fixes #32.
Fixes #39.
Fixes #40.
This commit is contained in:
Sean Marshallsay 2016-05-03 08:01:04 +01:00
Родитель bd004d8ce1 5199f5175f
Коммит a45c899d7d
3 изменённых файлов: 45 добавлений и 21 удалений

Просмотреть файл

@ -305,7 +305,19 @@ fn parse_fn(item: &ast::Item) -> Result<Option<String>, Error> {
let has_args = !fn_decl.inputs.is_empty();
for arg in &fn_decl.inputs {
let arg_name = print::pprust::pat_to_string(&*arg.pat);
use syntax::ast::{PatIdent, BindingMode};
let arg_name = match arg.pat.node {
PatIdent(BindingMode::ByValue(_), ref ident, None) => {
ident.node.name.to_string()
}
_ => return Err(Error {
level: Level::Error,
span: None,
message: format!("cheddar only supports by-value arguments:
incorrect argument `{}` in function definition `{}`",
print::pprust::pat_to_string(&*arg.pat), name),
})
};
let arg_type = try_some!(types::rust_to_c(&*arg.ty, &arg_name));
buf_without_return.push_str(&arg_type);
buf_without_return.push_str(", ");
@ -315,9 +327,11 @@ fn parse_fn(item: &ast::Item) -> Result<Option<String>, Error> {
// Remove the trailing comma and space.
buf_without_return.pop();
buf_without_return.pop();
} else {
buf_without_return.push_str("void");
}
buf_without_return.push_str(")");
buf_without_return.push(')');
let output_type = &fn_decl.output;
let full_declaration = match *output_type {

Просмотреть файл

@ -51,19 +51,12 @@ fn ptr_to_c(ty: &ast::MutTy) -> Result<Option<String>, Error> {
let new_type = try_some!(anon_rust_to_c(&ty.ty));
let const_spec = match ty.mutbl {
// *const T
ast::Mutability::MutImmutable => {
// Avoid multiple `const` specifiers (you can't have `const const int**` in C).
if new_type.starts_with("const ") {
""
} else {
"const "
}
},
ast::Mutability::MutImmutable => " const" ,
// *mut T
ast::Mutability::MutMutable => "",
};
Ok(Some(format!("{}{}*", const_spec, new_type)))
Ok(Some(format!("{}{}*", new_type, const_spec)))
}
/// Turn a Rust function pointer into a C function pointer.
@ -114,9 +107,11 @@ fn fn_ptr_to_c(fn_ty: &ast::BareFnTy, fn_span: codemap::Span, inner: &str) -> Re
// Remove the trailing comma and space.
buf_without_return.pop();
buf_without_return.pop();
} else {
buf_without_return.push_str("void");
}
buf_without_return.push_str(")");
buf_without_return.push(')');
let output_type = &fn_decl.output;
let full_declaration = match *output_type {
@ -360,25 +355,25 @@ mod test {
let parsed_type = super::anon_rust_to_c(&ty(source))
.expect(&format!("error while parsing {:?} with no name", source))
.expect(&format!("did not parse {:?} with no name", source));
assert_eq!(parsed_type, "const uint8_t*");
assert_eq!(parsed_type, "uint8_t const*");
let source = "*const ()";
let parsed_type = super::rust_to_c(&ty(source), name)
.expect(&format!("error while parsing {:?} with name {:?}", source, name))
.expect(&format!("did not parse {:?} with name {:?}", source, name));
assert_eq!(parsed_type, format!("const void* {}", name));
assert_eq!(parsed_type, format!("void const* {}", name));
let source = "*const *const f64";
let parsed_type = super::anon_rust_to_c(&ty(source))
.expect(&format!("error while parsing {:?} with no name", source))
.expect(&format!("did not parse {:?} with no name", source));
assert_eq!(parsed_type, "const double**");
assert_eq!(parsed_type, "double const* const*");
let source = "*const *const i64";
let parsed_type = super::rust_to_c(&ty(source), name)
.expect(&format!("error while parsing {:?} with name {:?}", source, name))
.expect(&format!("did not parse {:?} with name {:?}", source, name));
assert_eq!(parsed_type, format!("const int64_t** {}", name));
assert_eq!(parsed_type, format!("int64_t const* const* {}", name));
}
#[test]
@ -418,13 +413,19 @@ mod test {
let parsed_type = super::anon_rust_to_c(&ty(source))
.expect(&format!("error while parsing {:?} with no name", source))
.expect(&format!("did not parse {:?} with no name", source));
assert_eq!(parsed_type, "const bool***");
assert_eq!(parsed_type, "bool const** const*");
let source = "*mut *mut *const libc::c_ulonglong";
let parsed_type = super::rust_to_c(&ty(source), name)
.expect(&format!("error while parsing {:?} with name {:?}", source, name))
.expect(&format!("did not parse {:?} with name {:?}", source, name));
assert_eq!(parsed_type, format!("const unsigned long long*** {}", name));
assert_eq!(parsed_type, format!("unsigned long long const*** {}", name));
let source = "*const *mut *mut i8";
let parsed_type = super::rust_to_c(&ty(source), name)
.expect(&format!("error while parsing {:?} with name {:?}", source, name))
.expect(&format!("did not parse {:?} with name {:?}", source, name));
assert_eq!(parsed_type, format!("int8_t** const* {}", name));
}
#[test]

Просмотреть файл

@ -233,12 +233,17 @@ cheddar_cmp_test! { opaque_structs,
cheddar_cmp_test! { compilable_functions,
"
int64_t add_i64(int64_t lhs, int64_t rhs);
int get_errno(void);
",
r#"
#[no_mangle]
pub extern fn add_i64(lhs: i64, rhs: i64) -> i64 {
lhs + rhs
}
#[no_mangle]
pub extern fn get_errno() -> libc::int {
unsafe { *libc::__errno_location() }
}
// Shouldn't appear in the output header file.
#[allow(dead_code)]
@ -262,12 +267,14 @@ cheddar_cmp_test! { compilable_functions,
cheddar_cmp_test! { compilable_function_pointers,
"
typedef const int32_t** (*TwoIntPtrFnPtr)(double* argument);
typedef int32_t* const* (*TwoIntPtrFnPtr)(double* argument);
double cmp(double (*cmp_fn)(double lhs, double rhs), double lhs, double rhs);
typedef bool (*Foo)(double, double);
typedef void (*NoOp)(void);
void (*signal(int sig, void (*func)(int)))(int);
",
r#"
@ -280,6 +287,8 @@ cheddar_cmp_test! { compilable_function_pointers,
pub type Foo = extern fn(f64, f64) -> bool;
pub type NoOp = extern fn();
#[no_mangle]
pub extern fn signal(sig: libc::c_int, func: extern fn(libc::c_int)) -> extern fn(libc::c_int) {
println!("{}", sig);
@ -305,9 +314,9 @@ cheddar_cmp_test! { pure_rust_types,
typedef uintptr_t UInt;
typedef bool Bool;
typedef double* FloatArray;
typedef const bool* LogicArray;
typedef bool const* LogicArray;
typedef int32_t**** FourPointers;
typedef const float** TwoPointers;
typedef float const* const* TwoPointers;
",
"
pub type MyVoid = ();