summaryrefslogtreecommitdiff
path: root/libbindgen/src/ir/comp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libbindgen/src/ir/comp.rs')
-rw-r--r--libbindgen/src/ir/comp.rs962
1 files changed, 0 insertions, 962 deletions
diff --git a/libbindgen/src/ir/comp.rs b/libbindgen/src/ir/comp.rs
deleted file mode 100644
index 968bf879..00000000
--- a/libbindgen/src/ir/comp.rs
+++ /dev/null
@@ -1,962 +0,0 @@
-//! Compound types (unions and structs) in our intermediate representation.
-
-use clang;
-use parse::{ClangItemParser, ParseError};
-use std::cell::Cell;
-use super::annotations::Annotations;
-use super::context::{BindgenContext, ItemId};
-use super::derive::{CanDeriveCopy, CanDeriveDebug};
-use super::item::Item;
-use super::layout::Layout;
-use super::ty::Type;
-use super::type_collector::{ItemSet, TypeCollector};
-
-/// The kind of compound type.
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum CompKind {
- /// A struct.
- Struct,
- /// A union.
- Union,
-}
-
-/// The kind of C++ method.
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum MethodKind {
- /// A constructor. We represent it as method for convenience, to avoid code
- /// duplication.
- Constructor,
- /// A static method.
- Static,
- /// A normal method.
- Normal,
- /// A virtual method.
- Virtual,
-}
-
-/// A struct representing a C++ method, either static, normal, or virtual.
-#[derive(Debug)]
-pub struct Method {
- kind: MethodKind,
- /// The signature of the method. Take into account this is not a `Type`
- /// item, but a `Function` one.
- ///
- /// This is tricky and probably this field should be renamed.
- signature: ItemId,
- is_const: bool,
-}
-
-impl Method {
- /// Construct a new `Method`.
- pub fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self {
- Method {
- kind: kind,
- signature: signature,
- is_const: is_const,
- }
- }
-
- /// What kind of method is this?
- pub fn kind(&self) -> MethodKind {
- self.kind
- }
-
- /// Is this a constructor?
- pub fn is_constructor(&self) -> bool {
- self.kind == MethodKind::Constructor
- }
-
- /// Is this a virtual method?
- pub fn is_virtual(&self) -> bool {
- self.kind == MethodKind::Virtual
- }
-
- /// Is this a static method?
- pub fn is_static(&self) -> bool {
- self.kind == MethodKind::Static
- }
-
- /// Get the `ItemId` for the `Function` signature for this method.
- pub fn signature(&self) -> ItemId {
- self.signature
- }
-
- /// Is this a const qualified method?
- pub fn is_const(&self) -> bool {
- self.is_const
- }
-}
-
-/// A struct representing a C++ field.
-#[derive(Clone, Debug)]
-pub struct Field {
- /// The name of the field, empty if it's an unnamed bitfield width.
- name: Option<String>,
- /// The inner type.
- ty: ItemId,
- /// The doc comment on the field if any.
- comment: Option<String>,
- /// Annotations for this field, or the default.
- annotations: Annotations,
- /// If this field is a bitfield, and how many bits does it contain if it is.
- bitfield: Option<u32>,
- /// If the C++ field is marked as `mutable`
- mutable: bool,
-}
-
-impl Field {
- /// Construct a new `Field`.
- pub fn new(name: Option<String>,
- ty: ItemId,
- comment: Option<String>,
- annotations: Option<Annotations>,
- bitfield: Option<u32>,
- mutable: bool)
- -> Field {
- Field {
- name: name,
- ty: ty,
- comment: comment,
- annotations: annotations.unwrap_or_default(),
- bitfield: bitfield,
- mutable: mutable,
- }
- }
-
- /// Get the name of this field.
- pub fn name(&self) -> Option<&str> {
- self.name.as_ref().map(|n| &**n)
- }
-
- /// Get the type of this field.
- pub fn ty(&self) -> ItemId {
- self.ty
- }
-
- /// Get the comment for this field.
- pub fn comment(&self) -> Option<&str> {
- self.comment.as_ref().map(|c| &**c)
- }
-
- /// If this is a bitfield, how many bits does it need?
- pub fn bitfield(&self) -> Option<u32> {
- self.bitfield
- }
-
- /// Is this field marked as `mutable`?
- pub fn is_mutable(&self) -> bool {
- self.mutable
- }
-
- /// Get the annotations for this field.
- pub fn annotations(&self) -> &Annotations {
- &self.annotations
- }
-}
-
-impl CanDeriveDebug for Field {
- type Extra = ();
-
- fn can_derive_debug(&self, ctx: &BindgenContext, _: ()) -> bool {
- self.ty.can_derive_debug(ctx, ())
- }
-}
-
-impl<'a> CanDeriveCopy<'a> for Field {
- type Extra = ();
-
- fn can_derive_copy(&self, ctx: &BindgenContext, _: ()) -> bool {
- self.ty.can_derive_copy(ctx, ())
- }
-
- fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool {
- self.ty.can_derive_copy_in_array(ctx, ())
- }
-}
-
-
-/// The kind of inheritance a base class is using.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum BaseKind {
- /// Normal inheritance, like:
- ///
- /// ```cpp
- /// class A : public B {};
- /// ```
- Normal,
- /// Virtual inheritance, like:
- ///
- /// ```cpp
- /// class A: public virtual B {};
- /// ```
- Virtual,
-}
-
-/// A base class.
-#[derive(Clone, Debug)]
-pub struct Base {
- /// The type of this base class.
- pub ty: ItemId,
- /// The kind of inheritance we're doing.
- pub kind: BaseKind,
-}
-
-impl Base {
- /// Whether this base class is inheriting virtually.
- pub fn is_virtual(&self) -> bool {
- self.kind == BaseKind::Virtual
- }
-}
-
-/// A compound type.
-///
-/// Either a struct or union, a compound type is built up from the combination
-/// of fields which also are associated with their own (potentially compound)
-/// type.
-#[derive(Debug)]
-pub struct CompInfo {
- /// Whether this is a struct or a union.
- kind: CompKind,
-
- /// The members of this struct or union.
- fields: Vec<Field>,
-
- /// The template parameters of this class. These are non-concrete, and
- /// should always be a Type(TypeKind::Named(name)), but still they need to
- /// be registered with an unique type id in the context.
- template_args: Vec<ItemId>,
-
- /// The method declarations inside this class, if in C++ mode.
- methods: Vec<Method>,
-
- /// The different constructors this struct or class contains.
- constructors: Vec<ItemId>,
-
- /// Vector of classes this one inherits from.
- base_members: Vec<Base>,
-
- /// The parent reference template if any.
- ref_template: Option<ItemId>,
-
- /// The inner types that were declared inside this class, in something like:
- ///
- /// class Foo {
- /// typedef int FooTy;
- /// struct Bar {
- /// int baz;
- /// };
- /// }
- ///
- /// static Foo::Bar const = {3};
- inner_types: Vec<ItemId>,
-
- /// Set of static constants declared inside this class.
- inner_vars: Vec<ItemId>,
-
- /// Whether this type should generate an vtable (TODO: Should be able to
- /// look at the virtual methods and ditch this field).
- has_vtable: bool,
-
- /// Whether this type has destructor.
- has_destructor: bool,
-
- /// Whether this type has a base type with more than one member.
- ///
- /// TODO: We should be able to compute this.
- has_nonempty_base: bool,
-
- /// If this type has a template parameter which is not a type (e.g.: a
- /// size_t)
- has_non_type_template_params: bool,
-
- /// Whether this struct layout is packed.
- packed: bool,
-
- /// Whether this struct is anonymous.
- is_anonymous: bool,
-
- /// Used to know if we've found an opaque attribute that could cause us to
- /// generate a type with invalid layout. This is explicitly used to avoid us
- /// generating bad alignments when parsing types like max_align_t.
- ///
- /// It's not clear what the behavior should be here, if generating the item
- /// and pray, or behave as an opaque type.
- found_unknown_attr: bool,
-
- /// Used to detect if we've run in a can_derive_debug cycle while cycling
- /// around the template arguments.
- detect_derive_debug_cycle: Cell<bool>,
-
- /// Used to detect if we've run in a has_destructor cycle while cycling
- /// around the template arguments.
- detect_has_destructor_cycle: Cell<bool>,
-}
-
-impl CompInfo {
- /// Construct a new compound type.
- pub fn new(kind: CompKind) -> Self {
- CompInfo {
- kind: kind,
- fields: vec![],
- template_args: vec![],
- methods: vec![],
- constructors: vec![],
- base_members: vec![],
- ref_template: None,
- inner_types: vec![],
- inner_vars: vec![],
- has_vtable: false,
- has_destructor: false,
- has_nonempty_base: false,
- has_non_type_template_params: false,
- packed: false,
- is_anonymous: false,
- found_unknown_attr: false,
- detect_derive_debug_cycle: Cell::new(false),
- detect_has_destructor_cycle: Cell::new(false),
- }
- }
-
- /// Is this compound type unsized?
- pub fn is_unsized(&self, ctx: &BindgenContext) -> bool {
- !self.has_vtable(ctx) && self.fields.is_empty() &&
- self.base_members.iter().all(|base| {
- ctx.resolve_type(base.ty).canonical_type(ctx).is_unsized(ctx)
- }) &&
- self.ref_template
- .map_or(true, |template| ctx.resolve_type(template).is_unsized(ctx))
- }
-
- /// Does this compound type have a destructor?
- pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
- if self.detect_has_destructor_cycle.get() {
- warn!("Cycle detected looking for destructors");
- // Assume no destructor, since we don't have an explicit one.
- return false;
- }
-
- self.detect_has_destructor_cycle.set(true);
-
- let has_destructor = self.has_destructor ||
- match self.kind {
- CompKind::Union => false,
- CompKind::Struct => {
- // NB: We can't rely on a type with type parameters
- // not having destructor.
- //
- // This is unfortunate, but...
- self.ref_template.as_ref().map_or(false, |t| {
- ctx.resolve_type(*t).has_destructor(ctx)
- }) ||
- self.template_args.iter().any(|t| {
- ctx.resolve_type(*t).has_destructor(ctx)
- }) ||
- self.base_members.iter().any(|base| {
- ctx.resolve_type(base.ty).has_destructor(ctx)
- }) ||
- self.fields.iter().any(|field| {
- ctx.resolve_type(field.ty)
- .has_destructor(ctx)
- })
- }
- };
-
- self.detect_has_destructor_cycle.set(false);
-
- has_destructor
- }
-
- /// Is this type a template specialization?
- pub fn is_template_specialization(&self) -> bool {
- self.ref_template.is_some()
- }
-
- /// Get the template declaration this specialization is specializing.
- pub fn specialized_template(&self) -> Option<ItemId> {
- self.ref_template
- }
-
- /// Compute the layout of this type.
- ///
- /// This is called as a fallback under some circumstances where LLVM doesn't
- /// give us the correct layout.
- ///
- /// If we're a union without known layout, we try to compute it from our
- /// members. This is not ideal, but clang fails to report the size for these
- /// kind of unions, see test/headers/template_union.hpp
- pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
- use std::cmp;
-
- // We can't do better than clang here, sorry.
- if self.kind == CompKind::Struct {
- return None;
- }
-
- let mut max_size = 0;
- let mut max_align = 0;
- for field in &self.fields {
- let field_layout = ctx.resolve_type(field.ty)
- .layout(ctx);
-
- if let Some(layout) = field_layout {
- max_size = cmp::max(max_size, layout.size);
- max_align = cmp::max(max_align, layout.align);
- }
- }
-
- Some(Layout::new(max_size, max_align))
- }
-
- /// Get this type's set of fields.
- pub fn fields(&self) -> &[Field] {
- &self.fields
- }
-
- /// Get this type's set of free template arguments. Empty if this is not a
- /// template.
- pub fn template_args(&self) -> &[ItemId] {
- &self.template_args
- }
-
- /// Does this type have any template parameters that aren't types
- /// (e.g. int)?
- pub fn has_non_type_template_params(&self) -> bool {
- self.has_non_type_template_params
- }
-
- /// Does this type have a virtual table?
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- self.has_vtable ||
- self.base_members().iter().any(|base| {
- ctx.resolve_type(base.ty)
- .has_vtable(ctx)
- }) ||
- self.ref_template.map_or(false, |template| {
- ctx.resolve_type(template).has_vtable(ctx)
- })
- }
-
- /// Get this type's set of methods.
- pub fn methods(&self) -> &[Method] {
- &self.methods
- }
-
- /// Get this type's set of constructors.
- pub fn constructors(&self) -> &[ItemId] {
- &self.constructors
- }
-
- /// What kind of compound type is this?
- pub fn kind(&self) -> CompKind {
- self.kind
- }
-
- /// The set of types that this one inherits from.
- pub fn base_members(&self) -> &[Base] {
- &self.base_members
- }
-
- /// Construct a new compound type from a Clang type.
- pub fn from_ty(potential_id: ItemId,
- ty: &clang::Type,
- location: Option<clang::Cursor>,
- ctx: &mut BindgenContext)
- -> Result<Self, ParseError> {
- use clang_sys::*;
- // Sigh... For class templates we want the location, for
- // specialisations, we want the declaration... So just try both.
- //
- // TODO: Yeah, this code reads really bad.
- let mut cursor = ty.declaration();
- let mut kind = Self::kind_from_cursor(&cursor);
- if kind.is_err() {
- if let Some(location) = location {
- kind = Self::kind_from_cursor(&location);
- cursor = location;
- }
- }
-
- let kind = try!(kind);
-
- debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor);
-
- let mut ci = CompInfo::new(kind);
- ci.is_anonymous = cursor.is_anonymous();
- ci.template_args = match ty.template_args() {
- // In forward declarations and not specializations,
- // etc, they are in
- // the ast, we'll meet them in
- // CXCursor_TemplateTypeParameter
- None => vec![],
- Some(arg_types) => {
- let num_arg_types = arg_types.len();
- let mut specialization = true;
-
- let args = arg_types.filter(|t| t.kind() != CXType_Invalid)
- .filter_map(|t| {
- if t.spelling().starts_with("type-parameter") {
- specialization = false;
- None
- } else {
- Some(Item::from_ty_or_ref(t, None, None, ctx))
- }
- })
- .collect::<Vec<_>>();
-
- if specialization && args.len() != num_arg_types {
- ci.has_non_type_template_params = true;
- warn!("warning: Template parameter is not a type");
- }
-
- if specialization { args } else { vec![] }
- }
- };
-
- ci.ref_template = cursor.specialized()
- .and_then(|c| Item::parse(c, None, ctx).ok());
-
- let mut maybe_anonymous_struct_field = None;
- cursor.visit(|cur| {
- if cur.kind() != CXCursor_FieldDecl {
- if let Some((ty, _)) = maybe_anonymous_struct_field {
- let field = Field::new(None, ty, None, None, None, false);
- ci.fields.push(field);
- }
- maybe_anonymous_struct_field = None;
- }
-
- match cur.kind() {
- CXCursor_FieldDecl => {
- match maybe_anonymous_struct_field.take() {
- Some((ty, clang_ty)) => {
- let mut used = false;
- cur.visit(|child| {
- if child.cur_type() == clang_ty {
- used = true;
- }
- CXChildVisit_Continue
- });
- if !used {
- let field = Field::new(None,
- ty,
- None,
- None,
- None,
- false);
- ci.fields.push(field);
- }
- }
- None => {}
- }
-
- let bit_width = cur.bit_width();
- let field_type = Item::from_ty_or_ref(cur.cur_type(),
- Some(cur),
- Some(potential_id),
- ctx);
-
- let comment = cur.raw_comment();
- let annotations = Annotations::new(&cur);
- let name = cur.spelling();
- let is_mutable = cursor.is_mutable_field();
-
- // Name can be empty if there are bitfields, for example,
- // see tests/headers/struct_with_bitfields.h
- assert!(!name.is_empty() || bit_width.is_some(),
- "Empty field name?");
-
- let name = if name.is_empty() { None } else { Some(name) };
-
- let field = Field::new(name,
- field_type,
- comment,
- annotations,
- bit_width,
- is_mutable);
- ci.fields.push(field);
-
- // No we look for things like attributes and stuff.
- cur.visit(|cur| {
- if cur.kind() == CXCursor_UnexposedAttr {
- ci.found_unknown_attr = true;
- }
- CXChildVisit_Continue
- });
-
- }
- CXCursor_UnexposedAttr => {
- ci.found_unknown_attr = true;
- }
- CXCursor_EnumDecl |
- CXCursor_TypeAliasDecl |
- CXCursor_TypedefDecl |
- CXCursor_StructDecl |
- CXCursor_UnionDecl |
- CXCursor_ClassTemplate |
- CXCursor_ClassDecl => {
- let inner = Item::parse(cur, Some(potential_id), ctx)
- .expect("Inner ClassDecl");
- if !ci.inner_types.contains(&inner) {
- ci.inner_types.push(inner);
- }
- // A declaration of an union or a struct without name could
- // also be an unnamed field, unfortunately.
- if cur.spelling().is_empty() &&
- cur.kind() != CXCursor_EnumDecl {
- let ty = cur.cur_type();
- maybe_anonymous_struct_field = Some((inner, ty));
- }
- }
- CXCursor_PackedAttr => {
- ci.packed = true;
- }
- CXCursor_TemplateTypeParameter => {
- // Yes! You can arrive here with an empty template parameter
- // name! Awesome, isn't it?
- //
- // see tests/headers/empty_template_param_name.hpp
- if cur.spelling().is_empty() {
- return CXChildVisit_Continue;
- }
-
- let param =
- Item::named_type(cur.spelling(), potential_id, ctx);
- ci.template_args.push(param);
- }
- CXCursor_CXXBaseSpecifier => {
- let is_virtual_base = cur.is_virtual_base();
- ci.has_vtable |= is_virtual_base;
-
- let kind = if is_virtual_base {
- BaseKind::Virtual
- } else {
- BaseKind::Normal
- };
-
- let type_id = Item::from_ty_or_ref(cur.cur_type(),
- Some(cur),
- None,
- ctx);
- ci.base_members.push(Base {
- ty: type_id,
- kind: kind,
- });
- }
- CXCursor_Constructor |
- CXCursor_Destructor |
- CXCursor_CXXMethod => {
- let is_virtual = cur.method_is_virtual();
- let is_static = cur.method_is_static();
- debug_assert!(!(is_static && is_virtual), "How?");
-
- ci.has_destructor |= cur.kind() == CXCursor_Destructor;
- ci.has_vtable |= is_virtual;
-
- // This used to not be here, but then I tried generating
- // stylo bindings with this (without path filters), and
- // cried a lot with a method in gfx/Point.h
- // (ToUnknownPoint), that somehow was causing the same type
- // to be inserted in the map two times.
- //
- // I couldn't make a reduced test case, but anyway...
- // Methods of template functions not only use to be inlined,
- // but also instantiated, and we wouldn't be able to call
- // them, so just bail out.
- if !ci.template_args.is_empty() {
- return CXChildVisit_Continue;
- }
-
- // NB: This gets us an owned `Function`, not a
- // `FunctionSig`.
- let signature = match Item::parse(cur, Some(potential_id), ctx) {
- Ok(item) if ctx.resolve_item(item).kind().is_function() => item,
- _ => return CXChildVisit_Continue,
- };
-
- match cur.kind() {
- CXCursor_Constructor => {
- ci.constructors.push(signature);
- }
- // TODO(emilio): Bind the destructor?
- CXCursor_Destructor => {}
- CXCursor_CXXMethod => {
- let is_const = cur.method_is_const();
- let method_kind = if is_static {
- MethodKind::Static
- } else if is_virtual {
- MethodKind::Virtual
- } else {
- MethodKind::Normal
- };
-
- let method =
- Method::new(method_kind, signature, is_const);
-
- ci.methods.push(method);
- }
- _ => unreachable!("How can we see this here?"),
- }
- }
- CXCursor_NonTypeTemplateParameter => {
- ci.has_non_type_template_params = true;
- }
- CXCursor_VarDecl => {
- let linkage = cur.linkage();
- if linkage != CXLinkage_External &&
- linkage != CXLinkage_UniqueExternal {
- return CXChildVisit_Continue;
- }
-
- let visibility = cur.visibility();
- if visibility != CXVisibility_Default {
- return CXChildVisit_Continue;
- }
-
- if let Ok(item) = Item::parse(cur,
- Some(potential_id),
- ctx) {
- ci.inner_vars.push(item);
- }
- }
- // Intentionally not handled
- CXCursor_CXXAccessSpecifier |
- CXCursor_CXXFinalAttr |
- CXCursor_FunctionTemplate |
- CXCursor_ConversionFunction => {}
- _ => {
- warn!("unhandled comp member `{}` (kind {:?}) in `{}` ({})",
- cur.spelling(),
- cur.kind(),
- cursor.spelling(),
- cur.location());
- }
- }
- CXChildVisit_Continue
- });
-
- if let Some((ty, _)) = maybe_anonymous_struct_field {
- let field = Field::new(None, ty, None, None, None, false);
- ci.fields.push(field);
- }
-
- Ok(ci)
- }
-
- fn kind_from_cursor(cursor: &clang::Cursor)
- -> Result<CompKind, ParseError> {
- use clang_sys::*;
- Ok(match cursor.kind() {
- CXCursor_UnionDecl => CompKind::Union,
- CXCursor_ClassDecl |
- CXCursor_StructDecl => CompKind::Struct,
- CXCursor_CXXBaseSpecifier |
- CXCursor_ClassTemplatePartialSpecialization |
- CXCursor_ClassTemplate => {
- match cursor.template_kind() {
- CXCursor_UnionDecl => CompKind::Union,
- _ => CompKind::Struct,
- }
- }
- _ => {
- warn!("Unknown kind for comp type: {:?}", cursor);
- return Err(ParseError::Continue);
- }
- })
- }
-
- /// Do any of the types that participate in this type's "signature" use the
- /// named type `ty`?
- ///
- /// See also documentation for `ir::Item::signature_contains_named_type`.
- pub fn signature_contains_named_type(&self,
- ctx: &BindgenContext,
- ty: &Type)
- -> bool {
- // We don't generate these, so rather don't make the codegen step to
- // think we got it covered.
- if self.has_non_type_template_params() {
- return false;
- }
- self.template_args.iter().any(|arg| {
- ctx.resolve_type(*arg)
- .signature_contains_named_type(ctx, ty)
- })
- }
-
- /// Get the set of types that were declared within this compound type
- /// (e.g. nested class definitions).
- pub fn inner_types(&self) -> &[ItemId] {
- &self.inner_types
- }
-
- /// Get the set of static variables declared within this compound type.
- pub fn inner_vars(&self) -> &[ItemId] {
- &self.inner_vars
- }
-
- /// Have we found a field with an opaque type that could potentially mess up
- /// the layout of this compound type?
- pub fn found_unknown_attr(&self) -> bool {
- self.found_unknown_attr
- }
-
- /// Is this compound type packed?
- pub fn packed(&self) -> bool {
- self.packed
- }
-
- /// Returns whether this type needs an explicit vtable because it has
- /// virtual methods and none of its base classes has already a vtable.
- pub fn needs_explicit_vtable(&self, ctx: &BindgenContext) -> bool {
- self.has_vtable(ctx) &&
- !self.base_members.iter().any(|base| {
- // NB: Ideally, we could rely in all these types being `comp`, and
- // life would be beautiful.
- //
- // Unfortunately, given the way we implement --match-pat, and also
- // that you can inherit from templated types, we need to handle
- // other cases here too.
- ctx.resolve_type(base.ty)
- .canonical_type(ctx)
- .as_comp()
- .map_or(false, |ci| ci.has_vtable(ctx))
- })
- }
-}
-
-impl CanDeriveDebug for CompInfo {
- type Extra = Option<Layout>;
-
- fn can_derive_debug(&self,
- ctx: &BindgenContext,
- layout: Option<Layout>)
- -> bool {
- if self.has_non_type_template_params() {
- return layout.map_or(false, |l| l.opaque().can_derive_debug(ctx, ()));
- }
-
- // We can reach here recursively via template parameters of a member,
- // for example.
- if self.detect_derive_debug_cycle.get() {
- warn!("Derive debug cycle detected!");
- return true;
- }
-
- if self.kind == CompKind::Union {
- if ctx.options().unstable_rust {
- return false;
- }
-
- return layout.unwrap_or_else(Layout::zero)
- .opaque()
- .can_derive_debug(ctx, ());
- }
-
- self.detect_derive_debug_cycle.set(true);
-
- let can_derive_debug = {
- self.base_members
- .iter()
- .all(|base| base.ty.can_derive_debug(ctx, ())) &&
- self.template_args
- .iter()
- .all(|id| id.can_derive_debug(ctx, ())) &&
- self.fields
- .iter()
- .all(|f| f.can_derive_debug(ctx, ())) &&
- self.ref_template.map_or(true, |id| id.can_derive_debug(ctx, ()))
- };
-
- self.detect_derive_debug_cycle.set(false);
-
- can_derive_debug
- }
-}
-
-impl<'a> CanDeriveCopy<'a> for CompInfo {
- type Extra = (&'a Item, Option<Layout>);
-
- fn can_derive_copy(&self,
- ctx: &BindgenContext,
- (item, layout): (&Item, Option<Layout>))
- -> bool {
- if self.has_non_type_template_params() {
- return layout.map_or(false, |l| l.opaque().can_derive_copy(ctx, ()));
- }
-
- // NOTE: Take into account that while unions in C and C++ are copied by
- // default, the may have an explicit destructor in C++, so we can't
- // defer this check just for the union case.
- if self.has_destructor(ctx) {
- return false;
- }
-
- if self.kind == CompKind::Union {
- if !ctx.options().unstable_rust {
- // NOTE: If there's no template parameters we can derive copy
- // unconditionally, since arrays are magical for rustc, and
- // __BindgenUnionField always implements copy.
- return true;
- }
-
- // https://github.com/rust-lang/rust/issues/36640
- if !self.template_args.is_empty() || self.ref_template.is_some() ||
- !item.applicable_template_args(ctx).is_empty() {
- return false;
- }
- }
-
- // With template args, use a safe subset of the types,
- // since copyability depends on the types itself.
- self.ref_template
- .as_ref()
- .map_or(true, |t| t.can_derive_copy(ctx, ())) &&
- self.base_members
- .iter()
- .all(|base| base.ty.can_derive_copy(ctx, ())) &&
- self.fields.iter().all(|field| field.can_derive_copy(ctx, ()))
- }
-
- fn can_derive_copy_in_array(&self,
- ctx: &BindgenContext,
- extra: (&Item, Option<Layout>))
- -> bool {
- self.can_derive_copy(ctx, extra)
- }
-}
-
-impl TypeCollector for CompInfo {
- type Extra = Item;
-
- fn collect_types(&self,
- context: &BindgenContext,
- types: &mut ItemSet,
- item: &Item) {
- if let Some(template) = self.specialized_template() {
- types.insert(template);
- }
-
- let applicable_template_args = item.applicable_template_args(context);
- for arg in applicable_template_args {
- types.insert(arg);
- }
-
- for base in self.base_members() {
- types.insert(base.ty);
- }
-
- for field in self.fields() {
- types.insert(field.ty());
- }
-
- for &ty in self.inner_types() {
- types.insert(ty);
- }
-
- for &var in self.inner_vars() {
- types.insert(var);
- }
-
- // FIXME(emilio): Methods, VTable?
- }
-}