diff --git a/src/ir/analysis/derive_debug.rs b/src/ir/analysis/derive_debug.rs index 6e72da1fb8..b9b0be1046 100644 --- a/src/ir/analysis/derive_debug.rs +++ b/src/ir/analysis/derive_debug.rs @@ -4,6 +4,7 @@ use super::{ConstrainResult, MonotoneFramework}; use std::collections::HashSet; use std::collections::HashMap; use ir::context::{BindgenContext, ItemId}; +use ir::item::IsOpaque; use ir::traversal::EdgeKind; use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; use ir::ty::TypeKind; @@ -260,19 +261,23 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { return self.insert(id); } - let ty_cannot_derive = template.template_definition() + let template_definition = template.template_definition() .into_resolver() .through_type_refs() .through_type_aliases() - .resolve(self.ctx) + .resolve(self.ctx); + + let ty_cannot_derive = template_definition .as_type() .expect("Instantiations of a non-type?") .as_comp() .and_then(|c| { - // For non-type template parameters, we generate an opaque - // blob, and in this case the instantiation has a better - // idea of the layout than the definition does. - if c.has_non_type_template_params() { + // For non-type template parameters, or opaque template + // definitions, we generate an opaque blob, and in this + // case the instantiation has a better idea of the + // layout than the definition does. + if template_definition.is_opaque(self.ctx, &()) || + c.has_non_type_template_params() { let opaque = ty.layout(self.ctx) .or_else(|| { self.ctx diff --git a/tests/expectations/tests/opaque-template-inst-member.rs b/tests/expectations/tests/opaque-template-inst-member.rs new file mode 100644 index 0000000000..f7b2354695 --- /dev/null +++ b/tests/expectations/tests/opaque-template-inst-member.rs @@ -0,0 +1,41 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct OpaqueTemplate { +} +impl Default for OpaqueTemplate { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct ContainsOpaqueTemplate { + pub mBlah: [u32; 11usize], + pub mBaz: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_ContainsOpaqueTemplate() { + assert_eq!(::std::mem::size_of::() , 48usize , + concat ! ( "Size of: " , stringify ! ( ContainsOpaqueTemplate ) + )); + assert_eq! (::std::mem::align_of::() , 4usize , + concat ! ( + "Alignment of " , stringify ! ( ContainsOpaqueTemplate ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ContainsOpaqueTemplate ) ) . mBlah as * + const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ContainsOpaqueTemplate + ) , "::" , stringify ! ( mBlah ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ContainsOpaqueTemplate ) ) . mBaz as * + const _ as usize } , 44usize , concat ! ( + "Alignment of field: " , stringify ! ( ContainsOpaqueTemplate + ) , "::" , stringify ! ( mBaz ) )); +} +impl Clone for ContainsOpaqueTemplate { + fn clone(&self) -> Self { *self } +} diff --git a/tests/headers/opaque-template-inst-member.hpp b/tests/headers/opaque-template-inst-member.hpp new file mode 100644 index 0000000000..9ee356ad37 --- /dev/null +++ b/tests/headers/opaque-template-inst-member.hpp @@ -0,0 +1,12 @@ +// bindgen-flags: --opaque-type 'OpaqueTemplate' + +template +class OpaqueTemplate { + T mData; + bool mCannotDebug[40]; +}; + +class ContainsOpaqueTemplate { + OpaqueTemplate mBlah; + int mBaz; +};