diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index b9f261091..8cc746edb 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -120,10 +120,10 @@ impl Function { &self.path } - pub fn simplify_standard_types(&mut self) { - self.ret.simplify_standard_types(); + pub fn simplify_standard_types(&mut self, config: &Config) { + self.ret.simplify_standard_types(config); for arg in &mut self.args { - arg.ty.simplify_standard_types(); + arg.ty.simplify_standard_types(config); } } diff --git a/src/bindgen/ir/global.rs b/src/bindgen/ir/global.rs index a6ba150d6..a9d989df8 100644 --- a/src/bindgen/ir/global.rs +++ b/src/bindgen/ir/global.rs @@ -61,8 +61,8 @@ impl Static { } } - pub fn simplify_standard_types(&mut self) { - self.ty.simplify_standard_types(); + pub fn simplify_standard_types(&mut self, config: &Config) { + self.ty.simplify_standard_types(config); } } diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index e80beecd9..84e808c30 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -143,9 +143,9 @@ impl Struct { } } - pub fn simplify_standard_types(&mut self) { + pub fn simplify_standard_types(&mut self, config: &Config) { for &mut (_, ref mut ty, _) in &mut self.fields { - ty.simplify_standard_types(); + ty.simplify_standard_types(config); } } diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index dcee55715..a95c41303 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -6,7 +6,7 @@ use std::fmt; use std::io::Write; use crate::bindgen::cdecl; -use crate::bindgen::config::Config; +use crate::bindgen::config::{Config, Language}; use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{Documentation, GenericParams, GenericPath, Path}; @@ -411,7 +411,7 @@ impl Type { } } - fn simplified_type(&self) -> Option { + fn simplified_type(&self, config: &Config) -> Option { let path = match *self { Type::Path(ref p) => p, _ => return None, @@ -422,7 +422,7 @@ impl Type { } let mut generic = path.generics()[0].clone(); - generic.simplify_standard_types(); + generic.simplify_standard_types(config); match path.name() { // FIXME(#223): This is not quite correct. @@ -433,13 +433,24 @@ impl Type { is_nullable: false, is_ref: false, }), + "Box" + if config.language == Language::C && config.function.swift_name_macro.is_none() => + { + Some(Type::Ptr { + ty: Box::new(generic), + is_const: false, + is_nullable: false, + is_ref: false, + }) + } "Cell" => Some(generic), + "ManuallyDrop" | "MaybeUninit" if config.language == Language::C => Some(generic), _ => None, } } - pub fn simplify_standard_types(&mut self) { - if let Some(ty) = self.simplified_type() { + pub fn simplify_standard_types(&mut self, config: &Config) { + if let Some(ty) = self.simplified_type(config) { *self = ty; } } diff --git a/src/bindgen/ir/typedef.rs b/src/bindgen/ir/typedef.rs index e6ae07296..18da50bbf 100644 --- a/src/bindgen/ir/typedef.rs +++ b/src/bindgen/ir/typedef.rs @@ -66,8 +66,8 @@ impl Typedef { } } - pub fn simplify_standard_types(&mut self) { - self.aliased.simplify_standard_types(); + pub fn simplify_standard_types(&mut self, config: &Config) { + self.aliased.simplify_standard_types(config); } pub fn transfer_annotations(&mut self, out: &mut HashMap) { diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index 6d9e2347c..089499a0a 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -96,9 +96,9 @@ impl Union { } } - pub fn simplify_standard_types(&mut self) { + pub fn simplify_standard_types(&mut self, config: &Config) { for &mut (_, ref mut ty, _) in &mut self.fields { - ty.simplify_standard_types(); + ty.simplify_standard_types(config); } } diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index 26c6fa3a3..fdd6e1702 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -344,20 +344,22 @@ impl Library { } fn simplify_standard_types(&mut self) { + let config = &self.config; + self.structs.for_all_items_mut(|x| { - x.simplify_standard_types(); + x.simplify_standard_types(config); }); self.unions.for_all_items_mut(|x| { - x.simplify_standard_types(); + x.simplify_standard_types(config); }); self.globals.for_all_items_mut(|x| { - x.simplify_standard_types(); + x.simplify_standard_types(config); }); self.typedefs.for_all_items_mut(|x| { - x.simplify_standard_types(); + x.simplify_standard_types(config); }); for x in &mut self.functions { - x.simplify_standard_types(); + x.simplify_standard_types(config); } } diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs index 4cf4521b7..6e7695d98 100644 --- a/src/bindgen/parser.rs +++ b/src/bindgen/parser.rs @@ -392,6 +392,8 @@ impl Parse { add_opaque("BTreeSet", vec!["T"]); add_opaque("LinkedList", vec!["T"]); add_opaque("VecDeque", vec!["T"]); + add_opaque("ManuallyDrop", vec!["T"]); + add_opaque("MaybeUninit", vec!["T"]); } pub fn extend_with(&mut self, other: &Parse) { diff --git a/tests/expectations/both/box.c b/tests/expectations/both/box.c new file mode 100644 index 000000000..6468f86ed --- /dev/null +++ b/tests/expectations/both/box.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +typedef struct NotReprC_Box_i32 NotReprC_Box_i32; + +typedef NotReprC_Box_i32 Foo; + +typedef struct MyStruct { + int32_t *number; +} MyStruct; + +void delete(int32_t *x); + +void root(const Foo *a, const MyStruct *with_box); diff --git a/tests/expectations/both/box.compat.c b/tests/expectations/both/box.compat.c new file mode 100644 index 000000000..31f5d7a8f --- /dev/null +++ b/tests/expectations/both/box.compat.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +typedef struct NotReprC_Box_i32 NotReprC_Box_i32; + +typedef NotReprC_Box_i32 Foo; + +typedef struct MyStruct { + int32_t *number; +} MyStruct; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void delete(int32_t *x); + +void root(const Foo *a, const MyStruct *with_box); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/both/manuallydrop.c b/tests/expectations/both/manuallydrop.c new file mode 100644 index 000000000..8e942facb --- /dev/null +++ b/tests/expectations/both/manuallydrop.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +typedef struct NotReprC_ManuallyDrop_Point NotReprC_ManuallyDrop_Point; + +typedef NotReprC_ManuallyDrop_Point Foo; + +typedef struct Point { + int32_t x; + int32_t y; +} Point; + +typedef struct MyStruct { + Point point; +} MyStruct; + +void root(const Foo *a, const MyStruct *with_manual_drop); + +void take(Point with_manual_drop); diff --git a/tests/expectations/both/manuallydrop.compat.c b/tests/expectations/both/manuallydrop.compat.c new file mode 100644 index 000000000..6eb3444f5 --- /dev/null +++ b/tests/expectations/both/manuallydrop.compat.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +typedef struct NotReprC_ManuallyDrop_Point NotReprC_ManuallyDrop_Point; + +typedef NotReprC_ManuallyDrop_Point Foo; + +typedef struct Point { + int32_t x; + int32_t y; +} Point; + +typedef struct MyStruct { + Point point; +} MyStruct; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const Foo *a, const MyStruct *with_manual_drop); + +void take(Point with_manual_drop); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/both/maybeuninit.c b/tests/expectations/both/maybeuninit.c new file mode 100644 index 000000000..8e87f5dc7 --- /dev/null +++ b/tests/expectations/both/maybeuninit.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +typedef struct NotReprC_MaybeUninit______i32 NotReprC_MaybeUninit______i32; + +typedef NotReprC_MaybeUninit______i32 Foo; + +typedef struct MyStruct { + const int32_t *number; +} MyStruct; + +void root(const Foo *a, const MyStruct *with_maybe_uninit); diff --git a/tests/expectations/both/maybeuninit.compat.c b/tests/expectations/both/maybeuninit.compat.c new file mode 100644 index 000000000..b3b2fa178 --- /dev/null +++ b/tests/expectations/both/maybeuninit.compat.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +typedef struct NotReprC_MaybeUninit______i32 NotReprC_MaybeUninit______i32; + +typedef NotReprC_MaybeUninit______i32 Foo; + +typedef struct MyStruct { + const int32_t *number; +} MyStruct; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const Foo *a, const MyStruct *with_maybe_uninit); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/box.c b/tests/expectations/box.c new file mode 100644 index 000000000..967f4b7fe --- /dev/null +++ b/tests/expectations/box.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +typedef struct NotReprC_Box_i32 NotReprC_Box_i32; + +typedef NotReprC_Box_i32 Foo; + +typedef struct { + int32_t *number; +} MyStruct; + +void delete(int32_t *x); + +void root(const Foo *a, const MyStruct *with_box); diff --git a/tests/expectations/box.compat.c b/tests/expectations/box.compat.c new file mode 100644 index 000000000..4a31ac943 --- /dev/null +++ b/tests/expectations/box.compat.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +typedef struct NotReprC_Box_i32 NotReprC_Box_i32; + +typedef NotReprC_Box_i32 Foo; + +typedef struct { + int32_t *number; +} MyStruct; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void delete(int32_t *x); + +void root(const Foo *a, const MyStruct *with_box); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/manuallydrop.c b/tests/expectations/manuallydrop.c new file mode 100644 index 000000000..c4c4c2393 --- /dev/null +++ b/tests/expectations/manuallydrop.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +typedef struct NotReprC_ManuallyDrop_Point NotReprC_ManuallyDrop_Point; + +typedef NotReprC_ManuallyDrop_Point Foo; + +typedef struct { + int32_t x; + int32_t y; +} Point; + +typedef struct { + Point point; +} MyStruct; + +void root(const Foo *a, const MyStruct *with_manual_drop); + +void take(Point with_manual_drop); diff --git a/tests/expectations/manuallydrop.compat.c b/tests/expectations/manuallydrop.compat.c new file mode 100644 index 000000000..baac99a83 --- /dev/null +++ b/tests/expectations/manuallydrop.compat.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +typedef struct NotReprC_ManuallyDrop_Point NotReprC_ManuallyDrop_Point; + +typedef NotReprC_ManuallyDrop_Point Foo; + +typedef struct { + int32_t x; + int32_t y; +} Point; + +typedef struct { + Point point; +} MyStruct; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const Foo *a, const MyStruct *with_manual_drop); + +void take(Point with_manual_drop); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/maybeuninit.c b/tests/expectations/maybeuninit.c new file mode 100644 index 000000000..df1b889a2 --- /dev/null +++ b/tests/expectations/maybeuninit.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +typedef struct NotReprC_MaybeUninit______i32 NotReprC_MaybeUninit______i32; + +typedef NotReprC_MaybeUninit______i32 Foo; + +typedef struct { + const int32_t *number; +} MyStruct; + +void root(const Foo *a, const MyStruct *with_maybe_uninit); diff --git a/tests/expectations/maybeuninit.compat.c b/tests/expectations/maybeuninit.compat.c new file mode 100644 index 000000000..99fadecb6 --- /dev/null +++ b/tests/expectations/maybeuninit.compat.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +typedef struct NotReprC_MaybeUninit______i32 NotReprC_MaybeUninit______i32; + +typedef NotReprC_MaybeUninit______i32 Foo; + +typedef struct { + const int32_t *number; +} MyStruct; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const Foo *a, const MyStruct *with_maybe_uninit); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/tag/box.c b/tests/expectations/tag/box.c new file mode 100644 index 000000000..1667e37b2 --- /dev/null +++ b/tests/expectations/tag/box.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +struct NotReprC_Box_i32; + +typedef struct NotReprC_Box_i32 Foo; + +struct MyStruct { + int32_t *number; +}; + +void delete(int32_t *x); + +void root(const Foo *a, const struct MyStruct *with_box); diff --git a/tests/expectations/tag/box.compat.c b/tests/expectations/tag/box.compat.c new file mode 100644 index 000000000..3bf1324ec --- /dev/null +++ b/tests/expectations/tag/box.compat.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +struct NotReprC_Box_i32; + +typedef struct NotReprC_Box_i32 Foo; + +struct MyStruct { + int32_t *number; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void delete(int32_t *x); + +void root(const Foo *a, const struct MyStruct *with_box); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/tag/manuallydrop.c b/tests/expectations/tag/manuallydrop.c new file mode 100644 index 000000000..193bfbab9 --- /dev/null +++ b/tests/expectations/tag/manuallydrop.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +struct NotReprC_ManuallyDrop_Point; + +typedef struct NotReprC_ManuallyDrop_Point Foo; + +struct Point { + int32_t x; + int32_t y; +}; + +struct MyStruct { + struct Point point; +}; + +void root(const Foo *a, const struct MyStruct *with_manual_drop); + +void take(struct Point with_manual_drop); diff --git a/tests/expectations/tag/manuallydrop.compat.c b/tests/expectations/tag/manuallydrop.compat.c new file mode 100644 index 000000000..55cea1b99 --- /dev/null +++ b/tests/expectations/tag/manuallydrop.compat.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +struct NotReprC_ManuallyDrop_Point; + +typedef struct NotReprC_ManuallyDrop_Point Foo; + +struct Point { + int32_t x; + int32_t y; +}; + +struct MyStruct { + struct Point point; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const Foo *a, const struct MyStruct *with_manual_drop); + +void take(struct Point with_manual_drop); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/tag/maybeuninit.c b/tests/expectations/tag/maybeuninit.c new file mode 100644 index 000000000..246177601 --- /dev/null +++ b/tests/expectations/tag/maybeuninit.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +struct NotReprC_MaybeUninit______i32; + +typedef struct NotReprC_MaybeUninit______i32 Foo; + +struct MyStruct { + const int32_t *number; +}; + +void root(const Foo *a, const struct MyStruct *with_maybe_uninit); diff --git a/tests/expectations/tag/maybeuninit.compat.c b/tests/expectations/tag/maybeuninit.compat.c new file mode 100644 index 000000000..4e8cc8047 --- /dev/null +++ b/tests/expectations/tag/maybeuninit.compat.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +struct NotReprC_MaybeUninit______i32; + +typedef struct NotReprC_MaybeUninit______i32 Foo; + +struct MyStruct { + const int32_t *number; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const Foo *a, const struct MyStruct *with_maybe_uninit); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/rust/box.skip_cpp.rs b/tests/rust/box.skip_cpp.rs new file mode 100644 index 000000000..a2e95d4ff --- /dev/null +++ b/tests/rust/box.skip_cpp.rs @@ -0,0 +1,16 @@ +#[repr(C)] +pub struct MyStruct { + number: Box, +} + +pub struct NotReprC { + inner: T, +} + +pub type Foo = NotReprC>; + +#[no_mangle] +pub extern "C" fn root(a: &Foo, with_box: &MyStruct) {} + +#[no_mangle] +pub extern "C" fn delete(x: Option>) {} diff --git a/tests/rust/manuallydrop.skip_cpp.rs b/tests/rust/manuallydrop.skip_cpp.rs new file mode 100644 index 000000000..fea2537df --- /dev/null +++ b/tests/rust/manuallydrop.skip_cpp.rs @@ -0,0 +1,22 @@ +#[repr(C)] +pub struct Point { + x: i32, + y: i32, +} + +#[repr(C)] +pub struct MyStruct { + point: std::mem::ManuallyDrop, +} + +pub struct NotReprC { + inner: T, +} + +pub type Foo = NotReprC>; + +#[no_mangle] +pub extern "C" fn root(a: &Foo, with_manual_drop: &MyStruct) {} + +#[no_mangle] +pub extern "C" fn take(with_manual_drop: std::mem::ManuallyDrop) {} diff --git a/tests/rust/maybeuninit.skip_cpp.rs b/tests/rust/maybeuninit.skip_cpp.rs new file mode 100644 index 000000000..807316755 --- /dev/null +++ b/tests/rust/maybeuninit.skip_cpp.rs @@ -0,0 +1,13 @@ +#[repr(C)] +pub struct MyStruct<'a> { + number: std::mem::MaybeUninit<&'a i32>, +} + +pub struct NotReprC { + inner: T, +} + +pub type Foo<'a> = NotReprC>; + +#[no_mangle] +pub extern "C" fn root<'a, 'b>(a: &'a Foo, with_maybe_uninit: &'b MyStruct) {} diff --git a/tests/tests.rs b/tests/tests.rs index c60da0565..0c27b32e9 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -130,6 +130,9 @@ fn compile( } } +const SKIP_CPP_SUFFIX: &'static str = ".skip_cpp"; +const SKIP_WARNING_AS_ERROR_SUFFIX: &'static str = ".skip_warning_as_error"; + fn run_compile_test( cbindgen_path: &'static str, name: &'static str, @@ -164,18 +167,14 @@ fn run_compile_test( } } }; - let skip_warning_as_error_suffix = ".skip_warning_as_error"; - let skip_warning_as_error_position = name.rfind(skip_warning_as_error_suffix); - let skip_warning_as_error = skip_warning_as_error_position.is_some(); - let mut source_file = format!("{}.{}", name, &ext); - - if skip_warning_as_error { - source_file = format!( - "{}.{}", - &name[0..skip_warning_as_error_position.unwrap()], - &ext - ); - } + + let skip_warning_as_error = name.rfind(SKIP_WARNING_AS_ERROR_SUFFIX).is_some(); + let skip_cpp = name.rfind(SKIP_CPP_SUFFIX).is_some(); + + let source_file = format!("{}.{}", &name, &ext) + .replace(SKIP_CPP_SUFFIX, "") + .replace(SKIP_WARNING_AS_ERROR_SUFFIX, ""); + generated_file.push(source_file); run_cbindgen( @@ -196,7 +195,7 @@ fn run_compile_test( skip_warning_as_error, ); - if language == Language::C && cpp_compat { + if language == Language::C && cpp_compat && !skip_cpp { compile( &generated_file, &tests_path, @@ -228,15 +227,20 @@ fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static ); } } - run_compile_test( - cbindgen_path, - name, - &test, - tmp_dir, - Language::Cxx, - /* cpp_compat = */ false, - None, - ); + + let skip_cpp = name.rfind(SKIP_CPP_SUFFIX).is_some(); + + if !skip_cpp { + run_compile_test( + cbindgen_path, + name, + &test, + tmp_dir, + Language::Cxx, + /* cpp_compat = */ false, + None, + ); + } } macro_rules! test_file {