From d9ede218489e0bf5330d0005676f7687025e44c8 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Wed, 21 Jun 2017 11:46:32 -0700 Subject: [PATCH 1/2] Allow marking specific template instantiations as opaque If a template has a specialization that bindgen doesn't understand, it can be helpful to mark it as opaque and continue making forward progress in the meantime. This is something we need in the SpiderMonkey bindings. --- src/codegen/mod.rs | 39 +++--- src/ir/comp.rs | 4 +- src/ir/context.rs | 4 +- src/ir/item.rs | 54 ++++++-- src/ir/template.rs | 36 ++++- src/ir/ty.rs | 22 +-- tests/expectations/tests/issue-674-1.rs | 9 -- tests/expectations/tests/issue-674-2.rs | 9 -- tests/expectations/tests/issue-674-3.rs | 9 -- ...paque-template-instantiation-namespaced.rs | 128 ++++++++++++++++++ .../tests/opaque-template-instantiation.rs | 75 ++++++++++ ...aque-template-instantiation-namespaced.hpp | 29 ++++ .../headers/opaque-template-instantiation.hpp | 17 +++ 13 files changed, 363 insertions(+), 72 deletions(-) create mode 100644 tests/expectations/tests/opaque-template-instantiation-namespaced.rs create mode 100644 tests/expectations/tests/opaque-template-instantiation.rs create mode 100644 tests/headers/opaque-template-instantiation-namespaced.hpp create mode 100644 tests/headers/opaque-template-instantiation.hpp diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index d926f02b6c..50ebebf285 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::>(); 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 { - 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> { + 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 315d342a90..6dfc998028 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 eb0fd98aea..7b4e9b6a92 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 b80ddbd956..3564c6e89a 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; } +/// 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; @@ -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, "opaquetrue")?; } diff --git a/src/ir/template.rs b/src/ir/template.rs index 722c1b81a9..fcba40e17d 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". 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 3e5f53b0a5..d19a488983 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 e8b81dd3f3..01257c2377 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::() , 1usize , concat ! ( - "Size of template specialization: " , stringify ! ( u8 ) - )); - assert_eq!(::std::mem::align_of::() , 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 d7b0bb1c58..da0d82876f 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::() , 1usize , concat ! ( - "Size of template specialization: " , stringify ! ( u8 ) - )); - assert_eq!(::std::mem::align_of::() , 1usize , concat ! ( - "Alignment of template specialization: " , stringify ! ( u8 - ) )); - } - #[test] fn __bindgen_test_layout_StaticRefPtr_instantiation() { assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( diff --git a/tests/expectations/tests/issue-674-3.rs b/tests/expectations/tests/issue-674-3.rs index 8fd06b769c..6e915a18af 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::() , 1usize , concat ! ( - "Size of template specialization: " , stringify ! ( u8 ) - )); - assert_eq!(::std::mem::align_of::() , 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 0000000000..6623dae286 --- /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 { + pub member: T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + } + impl Default for Template { + 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::() , 1usize , concat ! ( + "Size of: " , stringify ! ( Foo ) )); + assert_eq! (::std::mem::align_of::() , 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::() , 4usize , concat ! ( + "Size of: " , stringify ! ( Bar ) )); + assert_eq! (::std::mem::align_of::() , 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, + } + #[test] + fn bindgen_test_layout_ContainsInstantiation() { + assert_eq!(::std::mem::size_of::() , 1usize + , concat ! ( + "Size of: " , stringify ! ( ContainsInstantiation ) )); + assert_eq! (::std::mem::align_of::() , + 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::() , + 4usize , concat ! ( + "Size of: " , stringify ! ( ContainsOpaqueInstantiation + ) )); + assert_eq! (::std::mem::align_of::() + , 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::>() + , 1usize , concat ! ( + "Size of template specialization: " , stringify ! ( + root::zoidberg::Template ) )); + assert_eq!(::std::mem::align_of::>() + , 1usize , concat ! ( + "Alignment of template specialization: " , stringify ! ( + root::zoidberg::Template ) )); + } +} diff --git a/tests/expectations/tests/opaque-template-instantiation.rs b/tests/expectations/tests/opaque-template-instantiation.rs new file mode 100644 index 0000000000..eb4e92bc38 --- /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 { + pub member: T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, +} +impl Default for Template { + 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::() , 1usize , + concat ! ( "Size of: " , stringify ! ( ContainsInstantiation ) + )); + assert_eq! (::std::mem::align_of::() , 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::() , 4usize , + concat ! ( + "Size of: " , stringify ! ( ContainsOpaqueInstantiation ) )); + assert_eq! (::std::mem::align_of::() , 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::>() , + 1usize , concat ! ( + "Size of template specialization: " , stringify ! ( + Template<::std::os::raw::c_char> ) )); + assert_eq!(::std::mem::align_of::>() , + 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 0000000000..31fb0d523d --- /dev/null +++ b/tests/headers/opaque-template-instantiation-namespaced.hpp @@ -0,0 +1,29 @@ +// bindgen-flags: --enable-cxx-namespaces --opaque-type 'zoidberg::Template' -- -std=c++14 + +namespace zoidberg { + +template +class Template { + T member; +}; + +struct Foo { + char c; +}; + +struct Bar { + int i; +}; + +class ContainsInstantiation { + Template 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 opaque; +}; + +} diff --git a/tests/headers/opaque-template-instantiation.hpp b/tests/headers/opaque-template-instantiation.hpp new file mode 100644 index 0000000000..7589b53c8d --- /dev/null +++ b/tests/headers/opaque-template-instantiation.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: --opaque-type 'Template' -- -std=c++14 + +template +class Template { + T member; +}; + +class ContainsInstantiation { + Template 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 opaque; +}; From 2000177d0b99cc8cbd901e4ceb81ea60a547e381 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 22 Jun 2017 09:37:19 -0700 Subject: [PATCH 2/2] Minor version bump to 0.26.2 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b88f8be1f3..4f5ab457b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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)", diff --git a/Cargo.toml b/Cargo.toml index 0f17dc8e4a..39724baaa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 = [