diff options
-rw-r--r-- | src/ir/item.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/canonical-types.rs | 278 | ||||
-rw-r--r-- | tests/expectations/tests/layout_cmdline_token.rs | 2 | ||||
-rw-r--r-- | tests/headers/canonical-types.hpp | 51 |
4 files changed, 333 insertions, 2 deletions
diff --git a/src/ir/item.rs b/src/ir/item.rs index 4e0ba80b..a38c8e5f 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -1594,8 +1594,8 @@ impl ClangItemParser for Item { } let decl = { - let decl = ty.declaration(); - decl.definition().unwrap_or(decl) + let canonical_def = ty.canonical_type().declaration().definition(); + canonical_def.unwrap_or_else(|| ty.declaration()) }; let comment = decl.raw_comment().or_else(|| location.raw_comment()); diff --git a/tests/expectations/tests/canonical-types.rs b/tests/expectations/tests/canonical-types.rs new file mode 100644 index 00000000..80d7fec3 --- /dev/null +++ b/tests/expectations/tests/canonical-types.rs @@ -0,0 +1,278 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ClassA { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassA_ClassAInner<T> { + pub x: *mut T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, +} +impl<T> Default for ClassA_ClassAInner<T> { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ClassB { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ClassC { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassC_ClassCInnerB { + pub cache: *mut ClassC_ClassCInnerA, +} +impl Default for ClassC_ClassCInnerB { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassC_ClassCInnerA { + pub member: *mut ClassC_ClassCInnerB, +} +impl Default for ClassC_ClassCInnerA { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassC_ClassCInnerCRTP { + pub _address: u8, +} +impl Default for ClassC_ClassCInnerCRTP { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassD { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_ClassD() { + assert_eq!( + ::std::mem::size_of::<ClassD>(), + 1usize, + concat!("Size of: ", stringify!(ClassD)) + ); + assert_eq!( + ::std::mem::align_of::<ClassD>(), + 1usize, + concat!("Alignment of ", stringify!(ClassD)) + ); +} +impl Default for ClassD { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[test] +fn __bindgen_test_layout_ClassB_open0_ClassD_ClassCInnerCRTP_close0_instantiation( +) { + assert_eq!( + ::std::mem::size_of::<ClassB>(), + 1usize, + concat!("Size of template specialization: ", stringify!(ClassB)) + ); + assert_eq!( + ::std::mem::align_of::<ClassB>(), + 1usize, + concat!("Alignment of template specialization: ", stringify!(ClassB)) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassCInnerCRTP { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_ClassCInnerCRTP() { + assert_eq!( + ::std::mem::size_of::<ClassCInnerCRTP>(), + 1usize, + concat!("Size of: ", stringify!(ClassCInnerCRTP)) + ); + assert_eq!( + ::std::mem::align_of::<ClassCInnerCRTP>(), + 1usize, + concat!("Alignment of ", stringify!(ClassCInnerCRTP)) + ); +} +impl Default for ClassCInnerCRTP { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[test] +fn __bindgen_test_layout_ClassB_open0_ClassCInnerCRTP_ClassAInner_close0_instantiation( +) { + assert_eq!( + ::std::mem::size_of::<ClassB>(), + 1usize, + concat!("Size of template specialization: ", stringify!(ClassB)) + ); + assert_eq!( + ::std::mem::align_of::<ClassB>(), + 1usize, + concat!("Alignment of template specialization: ", stringify!(ClassB)) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassAInner { + pub x: *mut ClassCInnerA, +} +#[test] +fn bindgen_test_layout_ClassAInner() { + assert_eq!( + ::std::mem::size_of::<ClassAInner>(), + 8usize, + concat!("Size of: ", stringify!(ClassAInner)) + ); + assert_eq!( + ::std::mem::align_of::<ClassAInner>(), + 8usize, + concat!("Alignment of ", stringify!(ClassAInner)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ClassAInner>())).x as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ClassAInner), + "::", + stringify!(x) + ) + ); +} +impl Default for ClassAInner { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassCInnerA { + pub member: *mut ClassCInnerB, +} +#[test] +fn bindgen_test_layout_ClassCInnerA() { + assert_eq!( + ::std::mem::size_of::<ClassCInnerA>(), + 8usize, + concat!("Size of: ", stringify!(ClassCInnerA)) + ); + assert_eq!( + ::std::mem::align_of::<ClassCInnerA>(), + 8usize, + concat!("Alignment of ", stringify!(ClassCInnerA)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ClassCInnerA>())).member as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ClassCInnerA), + "::", + stringify!(member) + ) + ); +} +impl Default for ClassCInnerA { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ClassCInnerB { + pub cache: *mut ClassCInnerA, +} +#[test] +fn bindgen_test_layout_ClassCInnerB() { + assert_eq!( + ::std::mem::size_of::<ClassCInnerB>(), + 8usize, + concat!("Size of: ", stringify!(ClassCInnerB)) + ); + assert_eq!( + ::std::mem::align_of::<ClassCInnerB>(), + 8usize, + concat!("Alignment of ", stringify!(ClassCInnerB)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ClassCInnerB>())).cache as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ClassCInnerB), + "::", + stringify!(cache) + ) + ); +} +impl Default for ClassCInnerB { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::<Self>::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/tests/expectations/tests/layout_cmdline_token.rs b/tests/expectations/tests/layout_cmdline_token.rs index 644b1b8a..47170dd7 100644 --- a/tests/expectations/tests/layout_cmdline_token.rs +++ b/tests/expectations/tests/layout_cmdline_token.rs @@ -61,6 +61,8 @@ impl Default for cmdline_token_hdr { } } } +/// Stores a pointer to the ops struct, and the offset: the place to +/// write the parsed result in the destination structure. pub type cmdline_parse_token_hdr_t = cmdline_token_hdr; /// A token is defined by this structure. /// diff --git a/tests/headers/canonical-types.hpp b/tests/headers/canonical-types.hpp new file mode 100644 index 00000000..c8eadd7e --- /dev/null +++ b/tests/headers/canonical-types.hpp @@ -0,0 +1,51 @@ +// bindgen-flags: -- -std=c++14 + +// Issue #2078. To pick up the definition of `ClassCInnerA`, +// `ty.canonical_type().declaration().definition()` is needed. + +template<class T> +class ClassA { +public: + class ClassAInner { + public: + T *x; + }; +}; + +template<class D, class I> +class ClassB { +public: + void foo() { + ((D *)0)->quux(); + } +}; + +template<typename T> +class ClassC { + struct ClassCInnerA; + + struct ClassCInnerB { + ClassCInnerA *cache; + }; + static_assert(sizeof(ClassCInnerB) > 0, ""); + + struct ClassCInnerA { + ClassCInnerB *member; + }; + +public: + class ClassCInnerCRTP : public ClassB<ClassCInnerCRTP, typename ClassA<ClassCInnerA>::ClassAInner> { + public: + void quux() { + ((typename ClassA<ClassCInnerA>::ClassAInner *)0)->x->member; + } + }; +}; + +class ClassD : public ClassB<ClassD, ClassC<int>::ClassCInnerCRTP> { +public: + void bar() { + ((ClassC<int>::ClassCInnerCRTP *)0)->foo(); + } +}; + |