diff options
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/codegen/mod.rs | 39 | ||||
-rw-r--r-- | src/ir/comp.rs | 4 | ||||
-rw-r--r-- | src/ir/context.rs | 4 | ||||
-rw-r--r-- | src/ir/item.rs | 54 | ||||
-rw-r--r-- | src/ir/template.rs | 36 | ||||
-rw-r--r-- | src/ir/ty.rs | 22 | ||||
-rw-r--r-- | tests/expectations/tests/issue-674-1.rs | 9 | ||||
-rw-r--r-- | tests/expectations/tests/issue-674-2.rs | 9 | ||||
-rw-r--r-- | tests/expectations/tests/issue-674-3.rs | 9 | ||||
-rw-r--r-- | tests/expectations/tests/opaque-template-instantiation-namespaced.rs | 128 | ||||
-rw-r--r-- | tests/expectations/tests/opaque-template-instantiation.rs | 75 | ||||
-rw-r--r-- | tests/headers/opaque-template-instantiation-namespaced.hpp | 29 | ||||
-rw-r--r-- | tests/headers/opaque-template-instantiation.hpp | 17 |
15 files changed, 365 insertions, 74 deletions
@@ -1,6 +1,6 @@ [root] name = "bindgen" -version = "0.26.1" +version = "0.26.2" dependencies = [ "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -13,7 +13,7 @@ name = "bindgen" readme = "README.md" repository = "https://github.com/servo/rust-bindgen" documentation = "https://docs.rs/bindgen" -version = "0.26.1" +version = "0.26.2" build = "build.rs" exclude = [ diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index d926f02b..50ebebf2 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -17,8 +17,8 @@ use ir::dot; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; use ir::function::{Abi, Function, FunctionSig}; use ir::int::IntKind; -use ir::item::{Item, ItemAncestors, ItemCanonicalName, ItemCanonicalPath, - ItemSet}; +use ir::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalName, + ItemCanonicalPath, ItemSet}; use ir::item_kind::ItemKind; use ir::layout::Layout; use ir::module::Module; @@ -580,7 +580,7 @@ impl CodeGenerator for Type { } let mut used_template_params = item.used_template_params(ctx); - let inner_rust_type = if item.is_opaque(ctx) { + let inner_rust_type = if item.is_opaque(ctx, &()) { used_template_params = None; self.to_opaque(ctx, item) } else { @@ -759,8 +759,11 @@ impl CodeGenerator for TemplateInstantiation { item: &Item) { // Although uses of instantiations don't need code generation, and are // just converted to rust types in fields, vars, etc, we take this - // opportunity to generate tests for their layout here. - if !ctx.options().layout_tests { + // opportunity to generate tests for their layout here. If the + // instantiation is opaque, then its presumably because we don't + // properly understand it (maybe because of specializations), and so we + // shouldn't emit layout tests either. + if !ctx.options().layout_tests || self.is_opaque(ctx, item) { return } @@ -1568,7 +1571,7 @@ impl CodeGenerator for CompInfo { } // Yeah, sorry about that. - if item.is_opaque(ctx) { + if item.is_opaque(ctx, &()) { fields.clear(); methods.clear(); @@ -1704,7 +1707,7 @@ impl CodeGenerator for CompInfo { }) .count() > 1; - let should_skip_field_offset_checks = item.is_opaque(ctx) || + let should_skip_field_offset_checks = item.is_opaque(ctx, &()) || too_many_base_vtables; let check_field_offset = if should_skip_field_offset_checks { @@ -2816,7 +2819,7 @@ impl TryToRustTy for Type { .build()) } TypeKind::TemplateInstantiation(ref inst) => { - inst.try_to_rust_ty(ctx, self) + inst.try_to_rust_ty(ctx, item) } TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()), TypeKind::TemplateAlias(inner, _) | @@ -2828,7 +2831,7 @@ impl TryToRustTy for Type { .collect::<Vec<_>>(); let spelling = self.name().expect("Unnamed alias?"); - if item.is_opaque(ctx) && !template_params.is_empty() { + if item.is_opaque(ctx, &()) && !template_params.is_empty() { self.try_to_opaque(ctx, item) } else if let Some(ty) = utils::type_from_named(ctx, spelling, @@ -2841,7 +2844,7 @@ impl TryToRustTy for Type { TypeKind::Comp(ref info) => { let template_params = item.used_template_params(ctx); if info.has_non_type_template_params() || - (item.is_opaque(ctx) && template_params.is_some()) { + (item.is_opaque(ctx, &()) && template_params.is_some()) { return self.try_to_opaque(ctx, item); } @@ -2895,23 +2898,27 @@ impl TryToRustTy for Type { } impl TryToOpaque for TemplateInstantiation { - type Extra = Type; + type Extra = Item; fn try_get_layout(&self, ctx: &BindgenContext, - self_ty: &Type) + item: &Item) -> error::Result<Layout> { - self_ty.layout(ctx).ok_or(error::Error::NoLayoutForOpaqueBlob) + item.expect_type().layout(ctx).ok_or(error::Error::NoLayoutForOpaqueBlob) } } impl TryToRustTy for TemplateInstantiation { - type Extra = Type; + type Extra = Item; fn try_to_rust_ty(&self, ctx: &BindgenContext, - _: &Type) + item: &Item) -> error::Result<P<ast::Ty>> { + if self.is_opaque(ctx, item) { + return Err(error::Error::InstantiationOfOpaqueType); + } + let decl = self.template_definition(); let mut ty = decl.try_to_rust_ty(ctx, &())?.unwrap(); @@ -2924,7 +2931,7 @@ impl TryToRustTy for TemplateInstantiation { extra_assert!(decl.into_resolver() .through_type_refs() .resolve(ctx) - .is_opaque(ctx)); + .is_opaque(ctx, &())); return Err(error::Error::InstantiationOfOpaqueType); } }; diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 315d342a..6dfc9980 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -4,7 +4,7 @@ use super::annotations::Annotations; use super::context::{BindgenContext, ItemId}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use super::dot::DotAttributes; -use super::item::Item; +use super::item::{IsOpaque, Item}; use super::layout::Layout; use super::traversal::{EdgeKind, Trace, Tracer}; use super::template::TemplateParameters; @@ -1585,7 +1585,7 @@ impl Trace for CompInfo { // We unconditionally trace `CompInfo`'s template parameters and inner // types for the the usage analysis. However, we don't want to continue // tracing anything else, if this type is marked opaque. - if item.is_opaque(context) { + if item.is_opaque(context, &()) { return; } diff --git a/src/ir/context.rs b/src/ir/context.rs index eb0fd98a..7b4e9b6a 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2,7 +2,7 @@ use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use super::int::IntKind; -use super::item::{Item, ItemAncestors, ItemCanonicalPath, ItemSet}; +use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath, ItemSet}; use super::item_kind::ItemKind; use super::module::{Module, ModuleKind}; use super::named::{UsedTemplateParameters, analyze}; @@ -339,7 +339,7 @@ impl<'ctx> BindgenContext<'ctx> { location); debug_assert!(declaration.is_some() || !item.kind().is_type() || item.kind().expect_type().is_builtin_or_named() || - item.kind().expect_type().is_opaque(), + item.kind().expect_type().is_opaque(self, &item), "Adding a type without declaration?"); let id = item.id(); diff --git a/src/ir/item.rs b/src/ir/item.rs index b80ddbd9..3564c6e8 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -61,6 +61,17 @@ pub trait ItemCanonicalPath { fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>; } +/// A trait for determining if some IR thing is opaque or not. +pub trait IsOpaque { + /// Extra context the IR thing needs to determine if it is opaque or not. + type Extra; + + /// Returns `true` if the thing is opaque, and `false` otherwise. + /// + /// May only be called when `ctx` is in the codegen phase. + fn is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool; +} + /// A trait for iterating over an item and its parents and up its ancestor chain /// up to (but not including) the implicit root module. pub trait ItemAncestors { @@ -231,7 +242,7 @@ impl Trace for Item { // don't want to stop collecting types even though they may be // opaque. if ty.should_be_traced_unconditionally() || - !self.is_opaque(ctx) { + !self.is_opaque(ctx, &()) { ty.trace(ctx, tracer, self); } } @@ -269,7 +280,7 @@ impl CanDeriveDebug for Item { let result = ctx.options().derive_debug && match self.kind { ItemKind::Type(ref ty) => { - if self.is_opaque(ctx) { + if self.is_opaque(ctx, &()) { ty.layout(ctx) .map_or(true, |l| l.opaque().can_derive_debug(ctx, ())) } else { @@ -292,7 +303,7 @@ impl CanDeriveDefault for Item { ctx.options().derive_default && match self.kind { ItemKind::Type(ref ty) => { - if self.is_opaque(ctx) { + if self.is_opaque(ctx, &()) { ty.layout(ctx) .map_or(false, |l| l.opaque().can_derive_default(ctx, ())) @@ -317,7 +328,7 @@ impl<'a> CanDeriveCopy<'a> for Item { let result = match self.kind { ItemKind::Type(ref ty) => { - if self.is_opaque(ctx) { + if self.is_opaque(ctx, &()) { ty.layout(ctx) .map_or(true, |l| l.opaque().can_derive_copy(ctx, ())) } else { @@ -335,7 +346,7 @@ impl<'a> CanDeriveCopy<'a> for Item { fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool { match self.kind { ItemKind::Type(ref ty) => { - if self.is_opaque(ctx) { + if self.is_opaque(ctx, &()) { ty.layout(ctx) .map_or(true, |l| { l.opaque().can_derive_copy_in_array(ctx, ()) @@ -593,15 +604,6 @@ impl Item { ctx.hidden_by_name(&self.canonical_path(ctx), self.id) } - /// Is this item opaque? - pub fn is_opaque(&self, ctx: &BindgenContext) -> bool { - debug_assert!(ctx.in_codegen_phase(), - "You're not supposed to call this yet"); - self.annotations.opaque() || - self.as_type().map_or(false, |ty| ty.is_opaque()) || - ctx.opaque_by_name(&self.canonical_path(ctx)) - } - /// Is this a reference to another type? pub fn is_type_ref(&self) -> bool { self.as_type().map_or(false, |ty| ty.is_type_ref()) @@ -858,6 +860,28 @@ impl Item { } } +impl IsOpaque for ItemId { + type Extra = (); + + fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool { + debug_assert!(ctx.in_codegen_phase(), + "You're not supposed to call this yet"); + ctx.resolve_item(*self).is_opaque(ctx, &()) + } +} + +impl IsOpaque for Item { + type Extra = (); + + fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool { + debug_assert!(ctx.in_codegen_phase(), + "You're not supposed to call this yet"); + self.annotations.opaque() || + self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) || + ctx.opaque_by_name(&self.canonical_path(ctx)) + } +} + /// A set of items. pub type ItemSet = BTreeSet<ItemId>; @@ -874,7 +898,7 @@ impl DotAttributes for Item { self.id, self.name(ctx).get())); - if self.is_opaque(ctx) { + if self.is_opaque(ctx, &()) { writeln!(out, "<tr><td>opaque</td><td>true</td></tr>")?; } diff --git a/src/ir/template.rs b/src/ir/template.rs index 722c1b81..fcba40e1 100644 --- a/src/ir/template.rs +++ b/src/ir/template.rs @@ -29,7 +29,7 @@ use super::context::{BindgenContext, ItemId}; use super::derive::{CanDeriveCopy, CanDeriveDebug}; -use super::item::{Item, ItemAncestors}; +use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath}; use super::layout::Layout; use super::traversal::{EdgeKind, Trace, Tracer}; use clang; @@ -305,6 +305,40 @@ impl TemplateInstantiation { } } +impl IsOpaque for TemplateInstantiation { + type Extra = Item; + + /// Is this an opaque template instantiation? + fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool { + if self.template_definition().is_opaque(ctx, &()) { + return true; + } + + // TODO(#774): This doesn't properly handle opaque instantiations where + // an argument is itself an instantiation because `canonical_name` does + // not insert the template arguments into the name, ie it for nested + // template arguments it creates "Foo" instead of "Foo<int>". The fully + // correct fix is to make `canonical_{name,path}` include template + // arguments properly. + + let mut path = item.canonical_path(ctx); + let args: Vec<_> = self.template_arguments() + .iter() + .map(|arg| { + let arg_path = arg.canonical_path(ctx); + arg_path[1..].join("::") + }).collect(); + { + let mut last = path.last_mut().unwrap(); + last.push('<'); + last.push_str(&args.join(", ")); + last.push('>'); + } + + ctx.opaque_by_name(&path) + } +} + impl<'a> CanDeriveCopy<'a> for TemplateInstantiation { type Extra = (); diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 3e5f53b0..d19a4889 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -7,7 +7,7 @@ use super::dot::DotAttributes; use super::enum_ty::Enum; use super::function::FunctionSig; use super::int::IntKind; -use super::item::Item; +use super::item::{IsOpaque, Item}; use super::layout::{Layout, Opaque}; use super::objc::ObjCInterface; use super::template::{AsTemplateParam, TemplateInstantiation, TemplateParameters}; @@ -102,14 +102,6 @@ impl Type { } } - /// Is this type of kind `TypeKind::Opaque`? - pub fn is_opaque(&self) -> bool { - match self.kind { - TypeKind::Opaque => true, - _ => false, - } - } - /// Is this type of kind `TypeKind::Named`? pub fn is_named(&self) -> bool { match self.kind { @@ -374,6 +366,18 @@ impl Type { } } +impl IsOpaque for Type { + type Extra = Item; + + fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool { + match self.kind { + TypeKind::Opaque => true, + TypeKind::TemplateInstantiation(ref inst) => inst.is_opaque(ctx, item), + _ => false, + } + } +} + impl AsTemplateParam for Type { type Extra = Item; diff --git a/tests/expectations/tests/issue-674-1.rs b/tests/expectations/tests/issue-674-1.rs index e8b81dd3..01257c23 100644 --- a/tests/expectations/tests/issue-674-1.rs +++ b/tests/expectations/tests/issue-674-1.rs @@ -43,13 +43,4 @@ pub mod root { impl Clone for CapturingContentInfo { fn clone(&self) -> Self { *self } } - #[test] - fn __bindgen_test_layout_Maybe_instantiation() { - assert_eq!(::std::mem::size_of::<u8>() , 1usize , concat ! ( - "Size of template specialization: " , stringify ! ( u8 ) - )); - assert_eq!(::std::mem::align_of::<u8>() , 1usize , concat ! ( - "Alignment of template specialization: " , stringify ! ( u8 - ) )); - } } diff --git a/tests/expectations/tests/issue-674-2.rs b/tests/expectations/tests/issue-674-2.rs index d7b0bb1c..da0d8287 100644 --- a/tests/expectations/tests/issue-674-2.rs +++ b/tests/expectations/tests/issue-674-2.rs @@ -67,15 +67,6 @@ pub mod root { pub _address: u8, } #[test] - fn __bindgen_test_layout_Rooted_instantiation() { - assert_eq!(::std::mem::size_of::<u8>() , 1usize , concat ! ( - "Size of template specialization: " , stringify ! ( u8 ) - )); - assert_eq!(::std::mem::align_of::<u8>() , 1usize , concat ! ( - "Alignment of template specialization: " , stringify ! ( u8 - ) )); - } - #[test] fn __bindgen_test_layout_StaticRefPtr_instantiation() { assert_eq!(::std::mem::size_of::<root::StaticRefPtr>() , 1usize , concat ! ( diff --git a/tests/expectations/tests/issue-674-3.rs b/tests/expectations/tests/issue-674-3.rs index 8fd06b76..6e915a18 100644 --- a/tests/expectations/tests/issue-674-3.rs +++ b/tests/expectations/tests/issue-674-3.rs @@ -57,13 +57,4 @@ pub mod root { impl Clone for nsCSSValue { fn clone(&self) -> Self { *self } } - #[test] - fn __bindgen_test_layout_nsRefPtrHashtable_instantiation() { - assert_eq!(::std::mem::size_of::<u8>() , 1usize , concat ! ( - "Size of template specialization: " , stringify ! ( u8 ) - )); - assert_eq!(::std::mem::align_of::<u8>() , 1usize , concat ! ( - "Alignment of template specialization: " , stringify ! ( u8 - ) )); - } } diff --git a/tests/expectations/tests/opaque-template-instantiation-namespaced.rs b/tests/expectations/tests/opaque-template-instantiation-namespaced.rs new file mode 100644 index 00000000..6623dae2 --- /dev/null +++ b/tests/expectations/tests/opaque-template-instantiation-namespaced.rs @@ -0,0 +1,128 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod zoidberg { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct Template<T> { + pub member: T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, + } + impl <T> Default for Template<T> { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } + } + #[repr(C)] + #[derive(Debug, Default, Copy)] + pub struct Foo { + pub c: ::std::os::raw::c_char, + } + #[test] + fn bindgen_test_layout_Foo() { + assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! ( + "Size of: " , stringify ! ( Foo ) )); + assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! ( + "Alignment of " , stringify ! ( Foo ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Foo ) ) . c as * const _ as usize + } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Foo ) , "::" , + stringify ! ( c ) )); + } + impl Clone for Foo { + fn clone(&self) -> Self { *self } + } + #[repr(C)] + #[derive(Debug, Default, Copy)] + pub struct Bar { + pub i: ::std::os::raw::c_int, + } + #[test] + fn bindgen_test_layout_Bar() { + assert_eq!(::std::mem::size_of::<Bar>() , 4usize , concat ! ( + "Size of: " , stringify ! ( Bar ) )); + assert_eq! (::std::mem::align_of::<Bar>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . i as * const _ as usize + } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( i ) )); + } + impl Clone for Bar { + fn clone(&self) -> Self { *self } + } + #[repr(C)] + #[derive(Debug, Copy)] + pub struct ContainsInstantiation { + pub not_opaque: root::zoidberg::Template<root::zoidberg::Foo>, + } + #[test] + fn bindgen_test_layout_ContainsInstantiation() { + assert_eq!(::std::mem::size_of::<ContainsInstantiation>() , 1usize + , concat ! ( + "Size of: " , stringify ! ( ContainsInstantiation ) )); + assert_eq! (::std::mem::align_of::<ContainsInstantiation>() , + 1usize , concat ! ( + "Alignment of " , stringify ! ( ContainsInstantiation + ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ContainsInstantiation ) ) . + not_opaque as * const _ as usize } , 0usize , concat ! + ( + "Alignment of field: " , stringify ! ( + ContainsInstantiation ) , "::" , stringify ! ( + not_opaque ) )); + } + impl Clone for ContainsInstantiation { + fn clone(&self) -> Self { *self } + } + impl Default for ContainsInstantiation { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } + } + #[repr(C)] + #[derive(Debug, Default, Copy)] + pub struct ContainsOpaqueInstantiation { + pub opaque: u32, + } + #[test] + fn bindgen_test_layout_ContainsOpaqueInstantiation() { + assert_eq!(::std::mem::size_of::<ContainsOpaqueInstantiation>() , + 4usize , concat ! ( + "Size of: " , stringify ! ( ContainsOpaqueInstantiation + ) )); + assert_eq! (::std::mem::align_of::<ContainsOpaqueInstantiation>() + , 4usize , concat ! ( + "Alignment of " , stringify ! ( + ContainsOpaqueInstantiation ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ContainsOpaqueInstantiation ) ) . + opaque as * const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( + ContainsOpaqueInstantiation ) , "::" , stringify ! ( + opaque ) )); + } + impl Clone for ContainsOpaqueInstantiation { + fn clone(&self) -> Self { *self } + } + } + #[test] + fn __bindgen_test_layout_Template_instantiation() { + assert_eq!(::std::mem::size_of::<root::zoidberg::Template<root::zoidberg::Foo>>() + , 1usize , concat ! ( + "Size of template specialization: " , stringify ! ( + root::zoidberg::Template<root::zoidberg::Foo> ) )); + assert_eq!(::std::mem::align_of::<root::zoidberg::Template<root::zoidberg::Foo>>() + , 1usize , concat ! ( + "Alignment of template specialization: " , stringify ! ( + root::zoidberg::Template<root::zoidberg::Foo> ) )); + } +} diff --git a/tests/expectations/tests/opaque-template-instantiation.rs b/tests/expectations/tests/opaque-template-instantiation.rs new file mode 100644 index 00000000..eb4e92bc --- /dev/null +++ b/tests/expectations/tests/opaque-template-instantiation.rs @@ -0,0 +1,75 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Template<T> { + pub member: T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, +} +impl <T> Default for Template<T> { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct ContainsInstantiation { + pub not_opaque: Template<::std::os::raw::c_char>, +} +#[test] +fn bindgen_test_layout_ContainsInstantiation() { + assert_eq!(::std::mem::size_of::<ContainsInstantiation>() , 1usize , + concat ! ( "Size of: " , stringify ! ( ContainsInstantiation ) + )); + assert_eq! (::std::mem::align_of::<ContainsInstantiation>() , 1usize , + concat ! ( + "Alignment of " , stringify ! ( ContainsInstantiation ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ContainsInstantiation ) ) . not_opaque as + * const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ContainsInstantiation ) + , "::" , stringify ! ( not_opaque ) )); +} +impl Clone for ContainsInstantiation { + fn clone(&self) -> Self { *self } +} +impl Default for ContainsInstantiation { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct ContainsOpaqueInstantiation { + pub opaque: u32, +} +#[test] +fn bindgen_test_layout_ContainsOpaqueInstantiation() { + assert_eq!(::std::mem::size_of::<ContainsOpaqueInstantiation>() , 4usize , + concat ! ( + "Size of: " , stringify ! ( ContainsOpaqueInstantiation ) )); + assert_eq! (::std::mem::align_of::<ContainsOpaqueInstantiation>() , 4usize + , concat ! ( + "Alignment of " , stringify ! ( ContainsOpaqueInstantiation ) + )); + assert_eq! (unsafe { + & ( * ( 0 as * const ContainsOpaqueInstantiation ) ) . opaque + as * const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( + ContainsOpaqueInstantiation ) , "::" , stringify ! ( opaque ) + )); +} +impl Clone for ContainsOpaqueInstantiation { + fn clone(&self) -> Self { *self } +} +#[test] +fn __bindgen_test_layout_Template_instantiation() { + assert_eq!(::std::mem::size_of::<Template<::std::os::raw::c_char>>() , + 1usize , concat ! ( + "Size of template specialization: " , stringify ! ( + Template<::std::os::raw::c_char> ) )); + assert_eq!(::std::mem::align_of::<Template<::std::os::raw::c_char>>() , + 1usize , concat ! ( + "Alignment of template specialization: " , stringify ! ( + Template<::std::os::raw::c_char> ) )); +} diff --git a/tests/headers/opaque-template-instantiation-namespaced.hpp b/tests/headers/opaque-template-instantiation-namespaced.hpp new file mode 100644 index 00000000..31fb0d52 --- /dev/null +++ b/tests/headers/opaque-template-instantiation-namespaced.hpp @@ -0,0 +1,29 @@ +// bindgen-flags: --enable-cxx-namespaces --opaque-type 'zoidberg::Template<zoidberg::Bar>' -- -std=c++14 + +namespace zoidberg { + +template <typename T> +class Template { + T member; +}; + +struct Foo { + char c; +}; + +struct Bar { + int i; +}; + +class ContainsInstantiation { + Template<Foo> not_opaque; +}; + +class ContainsOpaqueInstantiation { + // We should not generate a layout test for this instantiation, and it + // should appear as an opaque blob of bytes in + // `ContainsOpaqueInstantiation`'s type definition. + Template<Bar> opaque; +}; + +} diff --git a/tests/headers/opaque-template-instantiation.hpp b/tests/headers/opaque-template-instantiation.hpp new file mode 100644 index 00000000..7589b53c --- /dev/null +++ b/tests/headers/opaque-template-instantiation.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: --opaque-type 'Template<int>' -- -std=c++14 + +template <typename T> +class Template { + T member; +}; + +class ContainsInstantiation { + Template<char> not_opaque; +}; + +class ContainsOpaqueInstantiation { + // We should not generate a layout test for this instantiation, and it + // should appear as an opaque blob of bytes in + // `ContainsOpaqueInstantiation`'s type definition. + Template<int> opaque; +}; |