diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 946f41c..bfb588c 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -65,6 +65,8 @@ impl Struct { } }; + let path = Path::new(item.ident.to_string()); + // Ensure we can safely represent the struct given the configuration. if let Some(align) = repr.align { layout_config.ensure_safe_to_represent(&align)?; @@ -76,14 +78,15 @@ impl Struct { let out = fields .named .iter() - .try_skip_map(|x| x.as_ident_and_type())?; + .try_skip_map(|x| x.as_ident_and_type(&path))?; (out, false) } syn::Fields::Unnamed(ref fields) => { let mut out = Vec::new(); let mut current = 0; for field in fields.unnamed.iter() { - if let Some(x) = Type::load(&field.ty)? { + if let Some(mut x) = Type::load(&field.ty)? { + x.replace_self_with(&path); out.push((format!("{}", current), x, Documentation::load(&field.attrs))); current += 1; } @@ -96,7 +99,7 @@ impl Struct { let is_enum_variant_body = false; Ok(Struct::new( - Path::new(item.ident.to_string()), + path, GenericParams::new(&item.generics), fields, is_tagged, @@ -639,11 +642,17 @@ impl Source for Struct { } pub trait SynFieldHelpers { - fn as_ident_and_type(&self) -> Result, String>; + fn as_ident_and_type( + &self, + self_path: &Path, + ) -> Result, String>; } impl SynFieldHelpers for syn::Field { - fn as_ident_and_type(&self) -> Result, String> { + fn as_ident_and_type( + &self, + self_path: &Path, + ) -> Result, String> { let ident = self .ident .as_ref() @@ -651,7 +660,8 @@ impl SynFieldHelpers for syn::Field { .clone(); let converted_ty = Type::load(&self.ty)?; - if let Some(x) = converted_ty { + if let Some(mut x) = converted_ty { + x.replace_self_with(self_path); Ok(Some(( ident.to_string(), x, diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index 96a0a86..319d070 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -50,17 +50,19 @@ impl Union { layout_config.ensure_safe_to_represent(&align)?; } + let path = Path::new(item.ident.to_string()); + let (fields, tuple_union) = { let out = item .fields .named .iter() - .try_skip_map(|x| x.as_ident_and_type())?; + .try_skip_map(|x| x.as_ident_and_type(&path))?; (out, false) }; Ok(Union::new( - Path::new(item.ident.to_string()), + path, GenericParams::new(&item.generics), fields, repr.align, diff --git a/tests/expectations/both/struct_self.c b/tests/expectations/both/struct_self.c new file mode 100644 index 0000000..b7e7097 --- /dev/null +++ b/tests/expectations/both/struct_self.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +typedef struct Foo_Bar { + const int32_t *something; +} Foo_Bar; + +typedef struct Bar { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +void root(Bar b); diff --git a/tests/expectations/both/struct_self.compat.c b/tests/expectations/both/struct_self.compat.c new file mode 100644 index 0000000..a28a9ce --- /dev/null +++ b/tests/expectations/both/struct_self.compat.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +typedef struct Foo_Bar { + const int32_t *something; +} Foo_Bar; + +typedef struct Bar { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Bar b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/both/union_self.c b/tests/expectations/both/union_self.c new file mode 100644 index 0000000..4a17aa8 --- /dev/null +++ b/tests/expectations/both/union_self.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +typedef struct Foo_Bar { + const int32_t *something; +} Foo_Bar; + +typedef union Bar { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +void root(Bar b); diff --git a/tests/expectations/both/union_self.compat.c b/tests/expectations/both/union_self.compat.c new file mode 100644 index 0000000..ef287f5 --- /dev/null +++ b/tests/expectations/both/union_self.compat.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +typedef struct Foo_Bar { + const int32_t *something; +} Foo_Bar; + +typedef union Bar { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Bar b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/struct_self.c b/tests/expectations/struct_self.c new file mode 100644 index 0000000..d1bcc13 --- /dev/null +++ b/tests/expectations/struct_self.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +typedef struct { + const int32_t *something; +} Foo_Bar; + +typedef struct { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +void root(Bar b); diff --git a/tests/expectations/struct_self.compat.c b/tests/expectations/struct_self.compat.c new file mode 100644 index 0000000..1e54375 --- /dev/null +++ b/tests/expectations/struct_self.compat.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +typedef struct { + const int32_t *something; +} Foo_Bar; + +typedef struct { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Bar b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/struct_self.cpp b/tests/expectations/struct_self.cpp new file mode 100644 index 0000000..9e97dd5 --- /dev/null +++ b/tests/expectations/struct_self.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +template +struct Foo { + const int32_t *something; +}; + +struct Bar { + int32_t something; + Foo subexpressions; +}; + +extern "C" { + +void root(Bar b); + +} // extern "C" diff --git a/tests/expectations/tag/struct_self.c b/tests/expectations/tag/struct_self.c new file mode 100644 index 0000000..cc7db72 --- /dev/null +++ b/tests/expectations/tag/struct_self.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +struct Foo_Bar { + const int32_t *something; +}; + +struct Bar { + int32_t something; + struct Foo_Bar subexpressions; +}; + +void root(struct Bar b); diff --git a/tests/expectations/tag/struct_self.compat.c b/tests/expectations/tag/struct_self.compat.c new file mode 100644 index 0000000..ccb3936 --- /dev/null +++ b/tests/expectations/tag/struct_self.compat.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +struct Foo_Bar { + const int32_t *something; +}; + +struct Bar { + int32_t something; + struct Foo_Bar subexpressions; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct Bar b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/tag/union_self.c b/tests/expectations/tag/union_self.c new file mode 100644 index 0000000..209069e --- /dev/null +++ b/tests/expectations/tag/union_self.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +struct Foo_Bar { + const int32_t *something; +}; + +union Bar { + int32_t something; + struct Foo_Bar subexpressions; +}; + +void root(union Bar b); diff --git a/tests/expectations/tag/union_self.compat.c b/tests/expectations/tag/union_self.compat.c new file mode 100644 index 0000000..a150fa1 --- /dev/null +++ b/tests/expectations/tag/union_self.compat.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +struct Foo_Bar { + const int32_t *something; +}; + +union Bar { + int32_t something; + struct Foo_Bar subexpressions; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(union Bar b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/union_self.c b/tests/expectations/union_self.c new file mode 100644 index 0000000..083dabd --- /dev/null +++ b/tests/expectations/union_self.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +typedef struct { + const int32_t *something; +} Foo_Bar; + +typedef union { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +void root(Bar b); diff --git a/tests/expectations/union_self.compat.c b/tests/expectations/union_self.compat.c new file mode 100644 index 0000000..bfd26bc --- /dev/null +++ b/tests/expectations/union_self.compat.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +typedef struct { + const int32_t *something; +} Foo_Bar; + +typedef union { + int32_t something; + Foo_Bar subexpressions; +} Bar; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Bar b); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/union_self.cpp b/tests/expectations/union_self.cpp new file mode 100644 index 0000000..af502e5 --- /dev/null +++ b/tests/expectations/union_self.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +template +struct Foo { + const int32_t *something; +}; + +union Bar { + int32_t something; + Foo subexpressions; +}; + +extern "C" { + +void root(Bar b); + +} // extern "C" diff --git a/tests/rust/struct_self.rs b/tests/rust/struct_self.rs new file mode 100644 index 0000000..9432082 --- /dev/null +++ b/tests/rust/struct_self.rs @@ -0,0 +1,14 @@ +#[repr(C)] +pub struct Foo { + something: *const i32, + phantom: std::marker::PhantomData, +} + +#[repr(C)] +pub struct Bar { + something: i32, + subexpressions: Foo, +} + +#[no_mangle] +pub extern "C" fn root(b: Bar) {} diff --git a/tests/rust/union_self.rs b/tests/rust/union_self.rs new file mode 100644 index 0000000..77b0b0f --- /dev/null +++ b/tests/rust/union_self.rs @@ -0,0 +1,14 @@ +#[repr(C)] +pub struct Foo { + something: *const i32, + phantom: std::marker::PhantomData, +} + +#[repr(C)] +pub union Bar { + something: i32, + subexpressions: Foo, +} + +#[no_mangle] +pub extern "C" fn root(b: Bar) {}