Skip to content

Commit

Permalink
ir: Handle NonZero and simplify Option<NonZero> like we simplify Opti…
Browse files Browse the repository at this point in the history
…on<NonNull>.

Fixes #646
  • Loading branch information
emilio committed Jan 14, 2021
1 parent f922f68 commit c47ee15
Show file tree
Hide file tree
Showing 12 changed files with 541 additions and 1 deletion.
67 changes: 66 additions & 1 deletion src/bindgen/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,23 @@ impl Type {
}
}

pub fn make_zeroable(&self) -> Option<Self> {
let (kind, signed) = match *self {
Type::Primitive(PrimitiveType::Integer {
zeroable: false,
kind,
signed,
}) => (kind, signed),
_ => return None,
};

Some(Type::Primitive(PrimitiveType::Integer {
kind,
signed,
zeroable: true,
}))
}

pub fn make_nullable(&self) -> Option<Self> {
match *self {
Type::Ptr {
Expand All @@ -543,12 +560,52 @@ impl Type {
}
}

fn nonzero_to_primitive(&self) -> Option<Self> {
let path = match *self {
Type::Path(ref p) => p,
_ => return None,
};

if !path.generics().is_empty() {
return None;
}

let name = path.name();
if !name.starts_with("NonZero") {
return None;
}

let (kind, signed) = match path.name() {
"NonZeroU8" => (IntKind::B8, false),
"NonZeroU16" => (IntKind::B16, false),
"NonZeroU32" => (IntKind::B32, false),
"NonZeroU64" => (IntKind::B64, false),
"NonZeroUSize" => (IntKind::Size, false),
"NonZeroI8" => (IntKind::B8, true),
"NonZeroI16" => (IntKind::B16, true),
"NonZeroI32" => (IntKind::B32, true),
"NonZeroI64" => (IntKind::B64, true),
"NonZeroISize" => (IntKind::Size, true),
_ => return None,
};

Some(Type::Primitive(PrimitiveType::Integer {
zeroable: false,
signed,
kind,
}))
}

fn simplified_type(&self, config: &Config) -> Option<Self> {
let path = match *self {
Type::Path(ref p) => p,
_ => return None,
};

if path.generics().is_empty() {
return self.nonzero_to_primitive();
}

if path.generics().len() != 1 {
return None;
}
Expand All @@ -559,7 +616,15 @@ impl Type {
None => Cow::Borrowed(unsimplified_generic),
};
match path.name() {
"Option" => generic.make_nullable(),
"Option" => {
if let Some(nullable) = generic.make_nullable() {
return Some(nullable);
}
if let Some(zeroable) = generic.make_zeroable() {
return Some(zeroable);
}
None
}
"NonNull" => Some(Type::Ptr {
ty: Box::new(generic.into_owned()),
is_const: false,
Expand Down
44 changes: 44 additions & 0 deletions tests/expectations/nonzero.both.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#if 0
''' '
#endif

#ifdef __cplusplus
struct NonZeroI64;
#endif

#if 0
' '''
#endif


#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;

typedef struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const struct Option_Option_NonZeroI64 *j;
} NonZeroTest;

void root(struct NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const struct Option_Option_NonZeroI64 *j);
52 changes: 52 additions & 0 deletions tests/expectations/nonzero.both.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#if 0
''' '
#endif

#ifdef __cplusplus
struct NonZeroI64;
#endif

#if 0
' '''
#endif


#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;

typedef struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const struct Option_Option_NonZeroI64 *j;
} NonZeroTest;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void root(struct NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const struct Option_Option_NonZeroI64 *j);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
44 changes: 44 additions & 0 deletions tests/expectations/nonzero.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#if 0
''' '
#endif

#ifdef __cplusplus
struct NonZeroI64;
#endif

#if 0
' '''
#endif


#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;

typedef struct {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option_Option_NonZeroI64 *j;
} NonZeroTest;

void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option_Option_NonZeroI64 *j);
52 changes: 52 additions & 0 deletions tests/expectations/nonzero.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#if 0
''' '
#endif

#ifdef __cplusplus
struct NonZeroI64;
#endif

#if 0
' '''
#endif


#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;

typedef struct {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option_Option_NonZeroI64 *j;
} NonZeroTest;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option_Option_NonZeroI64 *j);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
50 changes: 50 additions & 0 deletions tests/expectations/nonzero.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#if 0
''' '
#endif

#ifdef __cplusplus
struct NonZeroI64;
#endif

#if 0
' '''
#endif


#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

template<typename T = void>
struct Option;

struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option<Option<NonZeroI64>> *j;
};

extern "C" {

void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option<Option<NonZeroI64>> *j);

} // extern "C"
47 changes: 47 additions & 0 deletions tests/expectations/nonzero.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif


from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
cdef extern from *:
ctypedef bint bool
ctypedef struct va_list

cdef extern from *:

ctypedef struct Option_Option_NonZeroI64:
pass

ctypedef struct NonZeroTest:
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option_Option_NonZeroI64 *j;

void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option_Option_NonZeroI64 *j);
Loading

0 comments on commit c47ee15

Please sign in to comment.