зеркало из https://github.com/mozilla/moz-cheddar.git
Merge pull request #41 from ubsan/master
Fixes #32. Fixes #39. Fixes #40.
This commit is contained in:
Коммит
a45c899d7d
18
src/parse.rs
18
src/parse.rs
|
@ -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 {
|
||||
|
|
33
src/types.rs
33
src/types.rs
|
@ -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]
|
||||
|
|
15
tests/lib.rs
15
tests/lib.rs
|
@ -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 = ();
|
||||
|
|
Загрузка…
Ссылка в новой задаче