Skip to content

Commit

Permalink
Skip signedness checks for non-integer type aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
johnschug committed Oct 18, 2018
1 parent f8bd332 commit 2099f61
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 39 deletions.
82 changes: 43 additions & 39 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,10 @@ pub struct TestGenerator {
fn_cname: Box<Fn(&str, Option<&str>) -> String>,
}

struct StructFinder {
struct TyFinder {
structs: HashSet<String>,
}

struct UnionFinder {
unions: HashSet<String>,
aliases: HashMap<String, P<ast::Ty>>,
}

struct Generator<'a> {
Expand All @@ -91,6 +89,7 @@ struct Generator<'a> {
sh: &'a SpanHandler,
structs: HashSet<String>,
unions: HashSet<String>,
aliases: HashMap<String, P<ast::Ty>>,
files: HashSet<String>,
abi: Abi,
tests: Vec<String>,
Expand Down Expand Up @@ -707,27 +706,23 @@ impl TestGenerator {
features: None,
}.fold_crate(krate);

// Probe the crate to find all structs (used to convert type names to
// names in C).
let mut structs = StructFinder {
// Probe the crate to find all structs, unions and type aliases (used to convert type names
// to names in C).
let mut types = TyFinder {
structs: HashSet::new(),
};
visit::walk_crate(&mut structs, &krate);

// Probe the crate to find all unions (used to convert type names to
// names in C).
let mut unions = UnionFinder {
unions: HashSet::new(),
aliases: HashMap::new(),
};
visit::walk_crate(&mut unions, &krate);
visit::walk_crate(&mut types, &krate);

let mut gen = Generator {
target: &target,
rust: Box::new(rust_out),
c: Box::new(c_out),
sh: &sess.span_diagnostic,
structs: structs.structs,
unions: unions.unions,
structs: types.structs,
unions: types.unions,
aliases: types.aliases,
abi: Abi::C,
tests: Vec::new(),
files: HashSet::new(),
Expand Down Expand Up @@ -941,13 +936,13 @@ impl<'a> Generator<'a> {
(self.opts.field_name)(struct_, field)
}

fn test_type(&mut self, ty: &str) {
if (self.opts.skip_type)(ty) {
fn test_type(&mut self, name: &str, ty: &ast::Ty) {
if (self.opts.skip_type)(name) {
return
}
let c = self.rust_ty_to_c_ty(ty);
self.test_size_align(ty, &c);
self.test_sign(ty, &c);
let c = self.rust_ty_to_c_ty(name);
self.test_size_align(name, &c);
self.test_sign(name, &c, ty);
}

fn test_struct(&mut self, ty: &str, s: &ast::VariantData) {
Expand Down Expand Up @@ -1063,14 +1058,31 @@ impl<'a> Generator<'a> {
self.tests.push(format!("size_align_{}", rust));
}

fn test_sign(&mut self, rust: &str, c: &str) {
match c {
"float" | "double" => return, // nope, never has a sign
_ => {}
fn has_sign(&self, ty: &ast::Ty) -> bool {
match ty.node {
ast::TyKind::Path(_, ref path) => {
let last = path.segments.last().unwrap().identifier.to_string();
if let Some(aliased) = self.aliases.get(&last) {
return self.has_sign(aliased);
}
match self.rust2c(&last).as_str() {
"char" | "short" | "int" | "long" | "long long" | "int8_t" | "int16_t"
| "int32_t" | "int64_t" | "uint8_t" | "uint16_t" | "uint32_t" | "uint64_t"
| "size_t" | "ssize_t" => true,
s => s.starts_with("signed ") || s.starts_with("unsigned "),
}
}
_ => false,
}
}

fn test_sign(&mut self, rust: &str, c: &str, ty: &ast::Ty) {
if (self.opts.skip_signededness)(rust) {
return
}
if !self.has_sign(ty) {
return
}
t!(writeln!(self.c, r#"
uint32_t __test_signed_{ty}(void) {{
return ((({cty}) -1) < 0);
Expand Down Expand Up @@ -1502,9 +1514,9 @@ impl<'a, 'v> Visitor<'v> for Generator<'a> {
let prev_abi = self.abi;
let public = i.vis == ast::Visibility::Public;
match i.node {
ast::ItemKind::Ty(_, ref generics) if public => {
ast::ItemKind::Ty(ref ty, ref generics) if public => {
self.assert_no_generics(i.ident, generics);
self.test_type(&i.ident.to_string());
self.test_type(&i.ident.to_string(), ty);
}

ast::ItemKind::Struct(ref s, ref generics) |
Expand Down Expand Up @@ -1565,7 +1577,7 @@ impl<'a, 'v> Visitor<'v> for Generator<'a> {
fn visit_mac(&mut self, _mac: &'v ast::Mac) { }
}

impl<'v> Visitor<'v> for StructFinder {
impl<'v> Visitor<'v> for TyFinder {
fn visit_item(&mut self, i: &'v ast::Item) {
match i.node {
ast::ItemKind::Struct(..) => {
Expand All @@ -1574,20 +1586,12 @@ impl<'v> Visitor<'v> for StructFinder {
ast::ItemKind::Enum(..) => {
self.structs.insert(i.ident.to_string());
}

_ => {}
}
visit::walk_item(self, i)
}
fn visit_mac(&mut self, _mac: &'v ast::Mac) { }
}

impl<'v> Visitor<'v> for UnionFinder {
fn visit_item(&mut self, i: &'v ast::Item) {
match i.node {
ast::ItemKind::Union(..) => {
self.unions.insert(i.ident.to_string());
}
ast::ItemKind::Ty(ref ty, ..) => {
self.aliases.insert(i.ident.to_string(), ty.clone());
}

_ => {}
}
Expand Down
4 changes: 4 additions & 0 deletions testcrate/src/t1.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ struct T1StructWithUnion {
union T1NoTypedefUnion u;
};

typedef double T1TypedefDouble;
typedef int* T1TypedefPtr;
typedef struct T1Bar T1TypedefStruct;

void T1a(void);
void* T1b(void);
void* T1c(void*);
Expand Down
4 changes: 4 additions & 0 deletions testcrate/src/t1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ pub struct T1StructWithUnion {
pub u: T1NoTypedefUnion,
}

pub type T1TypedefDouble = c_double;
pub type T1TypedefPtr = *mut c_int;
pub type T1TypedefStruct = T1Bar;

i! {
pub const T1C: u32 = 4;
}
Expand Down
3 changes: 3 additions & 0 deletions testcrate/src/t2.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
typedef int32_t T2Foo;
typedef int8_t T2Bar;

typedef T2Foo T2TypedefFoo;
typedef unsigned T2TypedefInt;

struct T2Baz {
int8_t _a;
int64_t a;
Expand Down
5 changes: 5 additions & 0 deletions testcrate/src/t2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use libc::*;

pub type T2Foo = u32;
pub type T2Bar = u32;

pub type T2TypedefFoo = T2Foo;
pub type T2TypedefInt = c_int;

macro_rules! i {
($i:item) => ($i)
}
Expand Down
2 changes: 2 additions & 0 deletions testcrate/tests/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ fn t2() {
assert!(!status.success(), o);
let errors = [
"bad T2Foo signed",
"bad T2TypedefFoo signed",
"bad T2TypedefInt signed",
"bad T2Bar size",
"bad T2Bar align",
"bad T2Bar signed",
Expand Down

0 comments on commit 2099f61

Please sign in to comment.