third_party/rust/bindgen/src/codegen/mod.rs
author Nick Fitzgerald <fitzgen@gmail.com>
Fri, 01 Sep 2017 16:43:16 -0700
changeset 378421 a8ae266cd61eb004d4f74a989e4d9c6d2ceb5b93
parent 371549 affa66a29e556abeb3ce0370c31ce68c08d7accd
child 378437 59ea29d58ab0b297fd57c3ac1595d770d1f389d6
permissions -rw-r--r--
Bug 1277338 - Part 13: Update vendored crates for newer `js` crate; r=sfink

mod derive_debug;
mod error;
mod helpers;
pub mod struct_layout;

use self::helpers::attributes;
use self::struct_layout::StructLayoutTracker;

use aster;
use aster::struct_field::StructFieldBuilder;

use ir::annotations::FieldAccessorKind;
use ir::comment;
use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field,
               FieldData, FieldMethods, Method, MethodKind};
use ir::context::{BindgenContext, ItemId};
use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault,
                 CanDeriveHash, CanDerivePartialEq, CanDeriveEq};
use ir::dot;
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
use ir::function::{Abi, Function, FunctionSig};
use ir::int::IntKind;
use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath};
use ir::item_kind::ItemKind;
use ir::layout::Layout;
use ir::module::Module;
use ir::objc::{ObjCInterface, ObjCMethod};
use ir::template::{AsTemplateParam, TemplateInstantiation, TemplateParameters};
use ir::ty::{Type, TypeKind};
use ir::var::Var;

use std::borrow::Cow;
use std::cell::Cell;
use std::collections::{HashSet, VecDeque};
use std::collections::hash_map::{Entry, HashMap};
use std::fmt::Write;
use std::mem;
use std::ops;
use syntax::abi;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span, respan};
use syntax::ptr::P;

// Name of type defined in constified enum module
pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type";

fn top_level_path(ctx: &BindgenContext, item: &Item) -> Vec<ast::Ident> {
    let mut path = vec![ctx.rust_ident_raw("self")];

    if ctx.options().enable_cxx_namespaces {
        let super_ = ctx.rust_ident_raw("super");

        for _ in 0..item.codegen_depth(ctx) {
            path.push(super_.clone());
        }
    }

    path
}

fn root_import(ctx: &BindgenContext, module: &Item) -> P<ast::Item> {
    assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up");
    assert!(module.is_module());

    let mut path = top_level_path(ctx, module);

    let root = ctx.root_module().canonical_name(ctx);
    let root_ident = ctx.rust_ident(&root);
    path.push(root_ident);

    let use_root = aster::AstBuilder::new()
        .item()
        .use_()
        .ids(path)
        .build()
        .build();

    quote_item!(ctx.ext_cx(), #[allow(unused_imports)] $use_root).unwrap()
}

struct CodegenResult<'a> {
    items: Vec<P<ast::Item>>,

    /// A monotonic counter used to add stable unique id's to stuff that doesn't
    /// need to be referenced by anything.
    codegen_id: &'a Cell<usize>,

    /// Whether a bindgen union has been generated at least once.
    saw_bindgen_union: bool,

    /// Whether an union has been generated at least once.
    saw_union: bool,

    /// Whether an incomplete array has been generated at least once.
    saw_incomplete_array: bool,

    /// Whether Objective C types have been seen at least once.
    saw_objc: bool,

    items_seen: HashSet<ItemId>,
    /// The set of generated function/var names, needed because in C/C++ is
    /// legal to do something like:
    ///
    /// ```c++
    /// extern "C" {
    ///   void foo();
    ///   extern int bar;
    /// }
    ///
    /// extern "C" {
    ///   void foo();
    ///   extern int bar;
    /// }
    /// ```
    ///
    /// Being these two different declarations.
    functions_seen: HashSet<String>,
    vars_seen: HashSet<String>,

    /// Used for making bindings to overloaded functions. Maps from a canonical
    /// function name to the number of overloads we have already codegen'd for
    /// that name. This lets us give each overload a unique suffix.
    overload_counters: HashMap<String, u32>,
}

impl<'a> CodegenResult<'a> {
    fn new(codegen_id: &'a Cell<usize>) -> Self {
        CodegenResult {
            items: vec![],
            saw_union: false,
            saw_bindgen_union: false,
            saw_incomplete_array: false,
            saw_objc: false,
            codegen_id: codegen_id,
            items_seen: Default::default(),
            functions_seen: Default::default(),
            vars_seen: Default::default(),
            overload_counters: Default::default(),
        }
    }

    fn saw_union(&mut self) {
        self.saw_union = true;
    }

    fn saw_bindgen_union(&mut self) {
        self.saw_union();
        self.saw_bindgen_union = true;
    }

    fn saw_incomplete_array(&mut self) {
        self.saw_incomplete_array = true;
    }

    fn saw_objc(&mut self) {
        self.saw_objc = true;
    }

    fn seen(&self, item: ItemId) -> bool {
        self.items_seen.contains(&item)
    }

    fn set_seen(&mut self, item: ItemId) {
        self.items_seen.insert(item);
    }

    fn seen_function(&self, name: &str) -> bool {
        self.functions_seen.contains(name)
    }

    fn saw_function(&mut self, name: &str) {
        self.functions_seen.insert(name.into());
    }

    /// Get the overload number for the given function name. Increments the
    /// counter internally so the next time we ask for the overload for this
    /// name, we get the incremented value, and so on.
    fn overload_number(&mut self, name: &str) -> u32 {
        let counter = self.overload_counters.entry(name.into()).or_insert(0);
        let number = *counter;
        *counter += 1;
        number
    }

    fn seen_var(&self, name: &str) -> bool {
        self.vars_seen.contains(name)
    }

    fn saw_var(&mut self, name: &str) {
        self.vars_seen.insert(name.into());
    }

    fn inner<F>(&mut self, cb: F) -> Vec<P<ast::Item>>
    where
        F: FnOnce(&mut Self),
    {
        let mut new = Self::new(self.codegen_id);

        cb(&mut new);

        self.saw_union |= new.saw_union;
        self.saw_incomplete_array |= new.saw_incomplete_array;
        self.saw_objc |= new.saw_objc;

        new.items
    }
}

impl<'a> ops::Deref for CodegenResult<'a> {
    type Target = Vec<P<ast::Item>>;

    fn deref(&self) -> &Self::Target {
        &self.items
    }
}

impl<'a> ops::DerefMut for CodegenResult<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.items
    }
}

struct ForeignModBuilder {
    inner: ast::ForeignMod,
}

impl ForeignModBuilder {
    fn new(abi: abi::Abi) -> Self {
        ForeignModBuilder {
            inner: ast::ForeignMod {
                abi: abi,
                items: vec![],
            },
        }
    }

    fn with_foreign_item(mut self, item: ast::ForeignItem) -> Self {
        self.inner.items.push(item);
        self
    }

    #[allow(dead_code)]
    fn with_foreign_items<I>(mut self, items: I) -> Self
    where
        I: IntoIterator<Item = ast::ForeignItem>,
    {
        self.inner.items.extend(items.into_iter());
        self
    }

    fn build(self, ctx: &BindgenContext) -> P<ast::Item> {
        P(ast::Item {
            ident: ctx.rust_ident(""),
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemKind::ForeignMod(self.inner),
            vis: ast::Visibility::Public,
            attrs: vec![],
            span: DUMMY_SP,
        })
    }
}

/// A trait to convert a rust type into a pointer, optionally const, to the same
/// type.
///
/// This is done due to aster's lack of pointer builder, I guess I should PR
/// there.
trait ToPtr {
    fn to_ptr(self, is_const: bool, span: Span) -> P<ast::Ty>;
}

impl ToPtr for P<ast::Ty> {
    fn to_ptr(self, is_const: bool, span: Span) -> Self {
        let ty = ast::TyKind::Ptr(ast::MutTy {
            ty: self,
            mutbl: if is_const {
                ast::Mutability::Immutable
            } else {
                ast::Mutability::Mutable
            },
        });
        P(ast::Ty {
            id: ast::DUMMY_NODE_ID,
            node: ty,
            span: span,
        })
    }
}

trait CodeGenerator {
    /// Extra information from the caller.
    type Extra;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        extra: &Self::Extra,
    );
}

impl CodeGenerator for Item {
    type Extra = ();

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        _extra: &(),
    ) {
        if !self.is_enabled_for_codegen(ctx) {
            return;
        }

        if self.is_hidden(ctx) || result.seen(self.id()) {
            debug!(
                "<Item as CodeGenerator>::codegen: Ignoring hidden or seen: \
                 self = {:?}",
                self
            );
            return;
        }

        debug!("<Item as CodeGenerator>::codegen: self = {:?}", self);
        if !ctx.codegen_items().contains(&self.id()) {
            // TODO(emilio, #453): Figure out what to do when this happens
            // legitimately, we could track the opaque stuff and disable the
            // assertion there I guess.
            error!("Found non-whitelisted item in code generation: {:?}", self);
        }

        result.set_seen(self.id());

        match *self.kind() {
            ItemKind::Module(ref module) => {
                module.codegen(ctx, result, self);
            }
            ItemKind::Function(ref fun) => {
                fun.codegen(ctx, result, self);
            }
            ItemKind::Var(ref var) => {
                var.codegen(ctx, result, self);
            }
            ItemKind::Type(ref ty) => {
                ty.codegen(ctx, result, self);
            }
        }
    }
}

impl CodeGenerator for Module {
    type Extra = Item;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        debug!("<Module as CodeGenerator>::codegen: item = {:?}", item);

        let codegen_self = |result: &mut CodegenResult,
                            found_any: &mut bool| {
            for child in self.children() {
                if ctx.codegen_items().contains(child) {
                    *found_any = true;
                    ctx.resolve_item(*child).codegen(ctx, result, &());
                }
            }

            if item.id() == ctx.root_module() {
                if result.saw_bindgen_union {
                    utils::prepend_union_types(ctx, &mut *result);
                }
                if result.saw_incomplete_array {
                    utils::prepend_incomplete_array_types(ctx, &mut *result);
                }
                if ctx.need_bindegen_complex_type() {
                    utils::prepend_complex_type(ctx, &mut *result);
                }
                if result.saw_objc {
                    utils::prepend_objc_header(ctx, &mut *result);
                }
            }
        };

        if !ctx.options().enable_cxx_namespaces ||
            (self.is_inline() &&
                !ctx.options().conservative_inline_namespaces)
        {
            codegen_self(result, &mut false);
            return;
        }

        let mut found_any = false;
        let inner_items = result.inner(|result| {
            result.push(root_import(ctx, item));
            codegen_self(result, &mut found_any);
        });

        // Don't bother creating an empty module.
        if !found_any {
            return;
        }

        let module = ast::ItemKind::Mod(ast::Mod {
            inner: ctx.span(),
            items: inner_items,
        });

        let name = item.canonical_name(ctx);
        let item_builder = aster::AstBuilder::new().item().pub_();
        let item = if name == "root" {
            let attrs = &[
                "non_snake_case",
                "non_camel_case_types",
                "non_upper_case_globals",
            ];
            item_builder
                .with_attr(attributes::allow(attrs))
                .build_item_kind(name, module)
        } else {
            item_builder.build_item_kind(name, module)
        };

        result.push(item);
    }
}

impl CodeGenerator for Var {
    type Extra = Item;
    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        use ir::var::VarType;
        debug!("<Var as CodeGenerator>::codegen: item = {:?}", item);
        debug_assert!(item.is_enabled_for_codegen(ctx));

        let canonical_name = item.canonical_name(ctx);

        if result.seen_var(&canonical_name) {
            return;
        }
        result.saw_var(&canonical_name);

        // We can't generate bindings to static variables of templates. The
        // number of actual variables for a single declaration are open ended
        // and we don't know what instantiations do or don't exist.
        let type_params = item.all_template_params(ctx);
        if let Some(params) = type_params {
            if !params.is_empty() {
                return;
            }
        }

        let ty = self.ty().to_rust_ty_or_opaque(ctx, &());

        if let Some(val) = self.val() {
            let const_item = aster::AstBuilder::new()
                .item()
                .pub_()
                .const_(canonical_name)
                .expr();
            let item = match *val {
                VarType::Bool(val) => {
                    const_item.build(helpers::ast_ty::bool_expr(val)).build(ty)
                }
                VarType::Int(val) => {
                    const_item.build(helpers::ast_ty::int_expr(val)).build(ty)
                }
                VarType::String(ref bytes) => {
                    // Account the trailing zero.
                    //
                    // TODO: Here we ignore the type we just made up, probably
                    // we should refactor how the variable type and ty id work.
                    let len = bytes.len() + 1;
                    let ty = quote_ty!(ctx.ext_cx(), [u8; $len]);

                    match String::from_utf8(bytes.clone()) {
                        Ok(string) => {
                            const_item
                                .build(helpers::ast_ty::cstr_expr(string))
                                .build(quote_ty!(ctx.ext_cx(), &'static $ty))
                        }
                        Err(..) => {
                            const_item
                                .build(helpers::ast_ty::byte_array_expr(bytes))
                                .build(ty)
                        }
                    }
                }
                VarType::Float(f) => {
                    match helpers::ast_ty::float_expr(ctx, f) {
                        Ok(expr) => const_item.build(expr).build(ty),
                        Err(..) => return,
                    }
                }
                VarType::Char(c) => {
                    const_item
                        .build(aster::AstBuilder::new().expr().lit().byte(c))
                        .build(ty)
                }
            };

            result.push(item);
        } else {
            let mut attrs = vec![];
            if let Some(mangled) = self.mangled_name() {
                attrs.push(attributes::link_name(mangled));
            } else if canonical_name != self.name() {
                attrs.push(attributes::link_name(self.name()));
            }

            let item = ast::ForeignItem {
                ident: ctx.rust_ident_raw(&canonical_name),
                attrs: attrs,
                node: ast::ForeignItemKind::Static(ty, !self.is_const()),
                id: ast::DUMMY_NODE_ID,
                span: ctx.span(),
                vis: ast::Visibility::Public,
            };

            let item = ForeignModBuilder::new(abi::Abi::C)
                .with_foreign_item(item)
                .build(ctx);
            result.push(item);
        }
    }
}

impl CodeGenerator for Type {
    type Extra = Item;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        debug!("<Type as CodeGenerator>::codegen: item = {:?}", item);
        debug_assert!(item.is_enabled_for_codegen(ctx));

        match *self.kind() {
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Array(..) |
            TypeKind::Pointer(..) |
            TypeKind::BlockPointer |
            TypeKind::Reference(..) |
            TypeKind::Function(..) |
            TypeKind::ResolvedTypeRef(..) |
            TypeKind::Opaque |
            TypeKind::TypeParam => {
                // These items don't need code generation, they only need to be
                // converted to rust types in fields, arguments, and such.
                return;
            }
            TypeKind::TemplateInstantiation(ref inst) => {
                inst.codegen(ctx, result, item)
            }
            TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
            TypeKind::TemplateAlias(inner, _) |
            TypeKind::Alias(inner) => {
                let inner_item = ctx.resolve_item(inner);
                let name = item.canonical_name(ctx);

                // Try to catch the common pattern:
                //
                // typedef struct foo { ... } foo;
                //
                // here.
                //
                if inner_item.canonical_name(ctx) == name {
                    return;
                }

                // If this is a known named type, disallow generating anything
                // for it too.
                let spelling = self.name().expect("Unnamed alias?");
                if utils::type_from_named(ctx, spelling, inner).is_some() {
                    return;
                }

                let mut used_template_params = item.used_template_params(ctx);
                let inner_rust_type = if item.is_opaque(ctx, &()) {
                    used_template_params = None;
                    self.to_opaque(ctx, item)
                } else {
                    // Its possible that we have better layout information than
                    // the inner type does, so fall back to an opaque blob based
                    // on our layout if converting the inner item fails.
                    inner_item
                        .try_to_rust_ty_or_opaque(ctx, &())
                        .unwrap_or_else(|_| self.to_opaque(ctx, item))
                };

                {
                    // FIXME(emilio): This is a workaround to avoid generating
                    // incorrect type aliases because of types that we haven't
                    // been able to resolve (because, eg, they depend on a
                    // template parameter).
                    //
                    // It's kind of a shame not generating them even when they
                    // could be referenced, but we already do the same for items
                    // with invalid template parameters, and at least this way
                    // they can be replaced, instead of generating plain invalid
                    // code.
                    let inner_canon_type =
                        inner_item.expect_type().canonical_type(ctx);
                    if inner_canon_type.is_invalid_type_param() {
                        warn!(
                            "Item contained invalid named type, skipping: \
                             {:?}, {:?}",
                            item,
                            inner_item
                        );
                        return;
                    }
                }

                let rust_name = ctx.rust_ident(&name);
                let mut typedef = aster::AstBuilder::new().item().pub_();

                if let Some(comment) = item.comment(ctx) {
                    typedef = typedef.with_attr(attributes::doc(comment));
                }

                // We prefer using `pub use` over `pub type` because of:
                // https://github.com/rust-lang/rust/issues/26264
                let simple_enum_path = match inner_rust_type.node {
                    ast::TyKind::Path(None, ref p) => {
                        if used_template_params.is_none() &&
                            inner_item
                                .expect_type()
                                .canonical_type(ctx)
                                .is_enum() &&
                            p.segments.iter().all(|p| p.parameters.is_none())
                        {
                            Some(p.clone())
                        } else {
                            None
                        }
                    }
                    _ => None,
                };

                let typedef = if let Some(mut p) = simple_enum_path {
                    for ident in top_level_path(ctx, item).into_iter().rev() {
                        p.segments.insert(
                            0,
                            ast::PathSegment {
                                identifier: ident,
                                parameters: None,
                            },
                        );
                    }
                    typedef.use_().build(p).as_(rust_name)
                } else {
                    let mut generics = typedef.type_(rust_name).generics();
                    if let Some(ref params) = used_template_params {
                        for template_param in params {
                            if let Some(id) = template_param
                                .as_template_param(ctx, &())
                            {
                                let template_param = ctx.resolve_type(id);
                                if template_param.is_invalid_type_param() {
                                    warn!(
                                        "Item contained invalid template \
                                         parameter: {:?}",
                                        item
                                    );
                                    return;
                                }
                                generics =
                                    generics.ty_param_id(
                                        template_param.name().unwrap(),
                                    );
                            }
                        }
                    }
                    generics.build().build_ty(inner_rust_type)
                };
                result.push(typedef)
            }
            TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
            TypeKind::ObjCId | TypeKind::ObjCSel => {
                result.saw_objc();
            }
            TypeKind::ObjCInterface(ref interface) => {
                interface.codegen(ctx, result, item)
            }
            ref u @ TypeKind::UnresolvedTypeRef(..) => {
                unreachable!("Should have been resolved after parsing {:?}!", u)
            }
        }
    }
}

struct Vtable<'a> {
    item_id: ItemId,
    #[allow(dead_code)]
    methods: &'a [Method],
    #[allow(dead_code)]
    base_classes: &'a [Base],
}

impl<'a> Vtable<'a> {
    fn new(
        item_id: ItemId,
        methods: &'a [Method],
        base_classes: &'a [Base],
    ) -> Self {
        Vtable {
            item_id: item_id,
            methods: methods,
            base_classes: base_classes,
        }
    }
}

impl<'a> CodeGenerator for Vtable<'a> {
    type Extra = Item;

    fn codegen<'b>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'b>,
        item: &Item,
    ) {
        assert_eq!(item.id(), self.item_id);
        debug_assert!(item.is_enabled_for_codegen(ctx));

        // For now, generate an empty struct, later we should generate function
        // pointers and whatnot.
        let attributes = vec![attributes::repr("C")];

        let vtable = aster::AstBuilder::new()
            .item()
            .pub_()
            .with_attrs(attributes)
            .tuple_struct(self.canonical_name(ctx))
            .field()
            .build_ty(helpers::ast_ty::raw_type(ctx, "c_void"))
            .build();
        result.push(vtable);
    }
}

impl<'a> ItemCanonicalName for Vtable<'a> {
    fn canonical_name(&self, ctx: &BindgenContext) -> String {
        format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx))
    }
}

impl<'a> TryToRustTy for Vtable<'a> {
    type Extra = ();

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<P<ast::Ty>> {
        Ok(aster::ty::TyBuilder::new().id(self.canonical_name(ctx)))
    }
}

impl CodeGenerator for TemplateInstantiation {
    type Extra = Item;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        debug_assert!(item.is_enabled_for_codegen(ctx));

        // 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 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;
        }

        // If there are any unbound type parameters, then we can't generate a
        // layout test because we aren't dealing with a concrete type with a
        // concrete size and alignment.
        if ctx.uses_any_template_parameters(item.id()) {
            return;
        }

        let layout = item.kind().expect_type().layout(ctx);

        if let Some(layout) = layout {
            let size = layout.size;
            let align = layout.align;

            let name = item.full_disambiguated_name(ctx);
            let mut fn_name =
                format!("__bindgen_test_layout_{}_instantiation", name);
            let times_seen = result.overload_number(&fn_name);
            if times_seen > 0 {
                write!(&mut fn_name, "_{}", times_seen).unwrap();
            }

            let fn_name = ctx.rust_ident_raw(&fn_name);

            let prefix = ctx.trait_prefix();
            let ident = item.to_rust_ty_or_opaque(ctx, &());
            let size_of_expr = quote_expr!(ctx.ext_cx(),
                                           ::$prefix::mem::size_of::<$ident>());
            let align_of_expr = quote_expr!(ctx.ext_cx(),
                                            ::$prefix::mem::align_of::<$ident>());

            let item = quote_item!(
                ctx.ext_cx(),
                #[test]
                fn $fn_name() {
                    assert_eq!($size_of_expr, $size,
                               concat!("Size of template specialization: ",
                                       stringify!($ident)));
                    assert_eq!($align_of_expr, $align,
                               concat!("Alignment of template specialization: ",
                                       stringify!($ident)));
                }).unwrap();

            result.push(item);
        }
    }
}

/// Generates an infinite number of anonymous field names.
struct AnonFieldNames(usize);

impl Default for AnonFieldNames {
    fn default() -> AnonFieldNames {
        AnonFieldNames(0)
    }
}

impl Iterator for AnonFieldNames {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        self.0 += 1;
        Some(format!("__bindgen_anon_{}", self.0))
    }
}

/// Trait for implementing the code generation of a struct or union field.
trait FieldCodegen<'a> {
    type Extra;

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        fields_should_be_private: bool,
        codegen_depth: usize,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        anon_field_names: &mut AnonFieldNames,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        extra: Self::Extra,
    ) where
        F: Extend<ast::StructField>,
        M: Extend<ast::ImplItem>;
}

impl<'a> FieldCodegen<'a> for Field {
    type Extra = ();

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        fields_should_be_private: bool,
        codegen_depth: usize,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        anon_field_names: &mut AnonFieldNames,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        _: (),
    ) where
        F: Extend<ast::StructField>,
        M: Extend<ast::ImplItem>,
    {
        match *self {
            Field::DataMember(ref data) => {
                data.codegen(
                    ctx,
                    fields_should_be_private,
                    codegen_depth,
                    accessor_kind,
                    parent,
                    anon_field_names,
                    result,
                    struct_layout,
                    fields,
                    methods,
                    (),
                );
            }
            Field::Bitfields(ref unit) => {
                unit.codegen(
                    ctx,
                    fields_should_be_private,
                    codegen_depth,
                    accessor_kind,
                    parent,
                    anon_field_names,
                    result,
                    struct_layout,
                    fields,
                    methods,
                    (),
                );
            }
        }
    }
}

impl<'a> FieldCodegen<'a> for FieldData {
    type Extra = ();

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        fields_should_be_private: bool,
        codegen_depth: usize,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        anon_field_names: &mut AnonFieldNames,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        _: (),
    ) where
        F: Extend<ast::StructField>,
        M: Extend<ast::ImplItem>,
    {
        // Bitfields are handled by `FieldCodegen` implementations for
        // `BitfieldUnit` and `Bitfield`.
        assert!(self.bitfield().is_none());

        let field_ty = ctx.resolve_type(self.ty());
        let ty = self.ty().to_rust_ty_or_opaque(ctx, &());

        // NB: If supported, we use proper `union` types.
        let ty = if parent.is_union() && !parent.can_be_rust_union(ctx) {
            if ctx.options().enable_cxx_namespaces {
                quote_ty!(ctx.ext_cx(), root::__BindgenUnionField<$ty>)
            } else {
                quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
            }
        } else if let Some(item) = field_ty.is_incomplete_array(ctx) {
            result.saw_incomplete_array();

            let inner = item.to_rust_ty_or_opaque(ctx, &());

            if ctx.options().enable_cxx_namespaces {
                quote_ty!(ctx.ext_cx(), root::__IncompleteArrayField<$inner>)
            } else {
                quote_ty!(ctx.ext_cx(), __IncompleteArrayField<$inner>)
            }
        } else {
            ty
        };

        let mut attrs = vec![];
        if ctx.options().generate_comments {
            if let Some(raw_comment) = self.comment() {
                let comment =
                    comment::preprocess(raw_comment, codegen_depth + 1);
                attrs.push(attributes::doc(comment))
            }
        }

        let field_name =
            self.name()
                .map(|name| ctx.rust_mangle(name).into_owned())
                .unwrap_or_else(|| anon_field_names.next().unwrap());

        if !parent.is_union() {
            if let Some(padding_field) =
                struct_layout.pad_field(&field_name, field_ty, self.offset())
            {
                fields.extend(Some(padding_field));
            }
        }

        let is_private = self.annotations().private_fields().unwrap_or(
            fields_should_be_private,
        );

        let accessor_kind =
            self.annotations().accessor_kind().unwrap_or(accessor_kind);

        let mut field = StructFieldBuilder::named(&field_name);

        if !is_private {
            field = field.pub_();
        }

        let field = field.with_attrs(attrs).build_ty(ty.clone());

        fields.extend(Some(field));

        // TODO: Factor the following code out, please!
        if accessor_kind == FieldAccessorKind::None {
            return;
        }

        let getter_name = ctx.rust_ident_raw(&format!("get_{}", field_name));
        let mutable_getter_name =
            ctx.rust_ident_raw(&format!("get_{}_mut", field_name));
        let field_name = ctx.rust_ident_raw(&field_name);

        let accessor_methods_impl = match accessor_kind {
            FieldAccessorKind::None => unreachable!(),
            FieldAccessorKind::Regular => {
                quote_item!(ctx.ext_cx(),
                    impl X {
                        #[inline]
                        pub fn $getter_name(&self) -> &$ty {
                            &self.$field_name
                        }

                        #[inline]
                        pub fn $mutable_getter_name(&mut self) -> &mut $ty {
                            &mut self.$field_name
                        }
                    }
                )
            }
            FieldAccessorKind::Unsafe => {
                quote_item!(ctx.ext_cx(),
                    impl X {
                        #[inline]
                        pub unsafe fn $getter_name(&self) -> &$ty {
                            &self.$field_name
                        }

                        #[inline]
                        pub unsafe fn $mutable_getter_name(&mut self)
                            -> &mut $ty {
                            &mut self.$field_name
                        }
                    }
                )
            }
            FieldAccessorKind::Immutable => {
                quote_item!(ctx.ext_cx(),
                    impl X {
                        #[inline]
                        pub fn $getter_name(&self) -> &$ty {
                            &self.$field_name
                        }
                    }
                )
            }
        };

        match accessor_methods_impl.unwrap().node {
            ast::ItemKind::Impl(_, _, _, _, _, ref items) => {
                methods.extend(items.clone())
            }
            _ => unreachable!(),
        }
    }
}

impl BitfieldUnit {
    /// Get the constructor name for this bitfield unit.
    fn ctor_name(&self, ctx: &BindgenContext) -> ast::Ident {
        let ctor_name = format!("new_bitfield_{}", self.nth());
        ctx.ext_cx().ident_of(&ctor_name)
    }

    /// Get the initial bitfield unit constructor that just returns 0. This will
    /// then be extended by each bitfield in the unit. See `extend_ctor_impl`
    /// below.
    fn initial_ctor_impl(
        &self,
        ctx: &BindgenContext,
        unit_field_int_ty: &P<ast::Ty>,
    ) -> P<ast::Item> {
        let ctor_name = self.ctor_name(ctx);

        // If supported, add the const.
        let fn_prefix = if ctx.options().rust_features().const_fn() {
            quote_tokens!(ctx.ext_cx(), pub const fn)
        } else {
            quote_tokens!(ctx.ext_cx(), pub fn)
        };

        quote_item!(
            ctx.ext_cx(),
            impl XxxUnused {
                #[inline]
                $fn_prefix $ctor_name() -> $unit_field_int_ty {
                    0
                }
            }
        ).unwrap()
    }
}

impl Bitfield {
    /// Extend an under construction bitfield unit constructor with this
    /// bitfield. This involves two things:
    ///
    /// 1. Adding a parameter with this bitfield's name and its type.
    ///
    /// 2. Bitwise or'ing the parameter into the final value of the constructed
    /// bitfield unit.
    fn extend_ctor_impl(
        &self,
        ctx: &BindgenContext,
        parent: &CompInfo,
        ctor_impl: P<ast::Item>,
        ctor_name: &ast::Ident,
        unit_field_int_ty: &P<ast::Ty>,
    ) -> P<ast::Item> {
        let items = match ctor_impl.unwrap().node {
            ast::ItemKind::Impl(_, _, _, _, _, items) => items,
            _ => unreachable!(),
        };

        assert_eq!(items.len(), 1);
        let (sig, body) = match items[0].node {
            ast::ImplItemKind::Method(ref sig, ref body) => (sig, body),
            _ => unreachable!(),
        };

        let params = sig.decl.clone().unwrap().inputs;
        let param_name = bitfield_getter_name(ctx, parent, self.name());

        let bitfield_ty_item = ctx.resolve_item(self.ty());
        let bitfield_ty = bitfield_ty_item.expect_type();
        let bitfield_ty_layout = bitfield_ty.layout(ctx).expect(
            "Bitfield without layout? Gah!",
        );
        let bitfield_int_ty = helpers::blob(bitfield_ty_layout);
        let bitfield_ty =
            bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);

        let offset = self.offset_into_unit();
        let mask = self.mask();

        // If supported, add the const.
        let fn_prefix = if ctx.options().rust_features().const_fn() {
            quote_tokens!(ctx.ext_cx(), pub const fn)
        } else {
            quote_tokens!(ctx.ext_cx(), pub fn)
        };

        // Don't use variables or blocks because const function does not allow them.
        quote_item!(
            ctx.ext_cx(),
            impl XxxUnused {
                #[inline]
                $fn_prefix $ctor_name($params $param_name : $bitfield_ty)
                                      -> $unit_field_int_ty {
                    ($body |
                        (($param_name as $bitfield_int_ty as $unit_field_int_ty) << $offset) &
                        ($mask as $unit_field_int_ty))
                }
            }
        ).unwrap()
    }
}

impl<'a> FieldCodegen<'a> for BitfieldUnit {
    type Extra = ();

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        fields_should_be_private: bool,
        codegen_depth: usize,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        anon_field_names: &mut AnonFieldNames,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        _: (),
    ) where
        F: Extend<ast::StructField>,
        M: Extend<ast::ImplItem>,
    {
        let field_ty = helpers::blob(self.layout());
        let unit_field_name = format!("_bitfield_{}", self.nth());

        let field = StructFieldBuilder::named(&unit_field_name)
            .pub_()
            .build_ty(field_ty.clone());
        fields.extend(Some(field));

        let mut field_int_size = self.layout().size;
        if !field_int_size.is_power_of_two() {
            field_int_size = field_int_size.next_power_of_two();
        }

        let unit_field_int_ty = match field_int_size {
            8 => quote_ty!(ctx.ext_cx(), u64),
            4 => quote_ty!(ctx.ext_cx(), u32),
            2 => quote_ty!(ctx.ext_cx(), u16),
            1 => quote_ty!(ctx.ext_cx(), u8),
            size => {
                debug_assert!(size > 8);
                // Can't generate bitfield accessors for unit sizes larget than
                // 64 bits at the moment.
                struct_layout.saw_bitfield_unit(self.layout());
                return;
            }
        };

        let ctor_name = self.ctor_name(ctx);
        let mut ctor_impl = self.initial_ctor_impl(ctx, &unit_field_int_ty);

        for bf in self.bitfields() {
            bf.codegen(
                ctx,
                fields_should_be_private,
                codegen_depth,
                accessor_kind,
                parent,
                anon_field_names,
                result,
                struct_layout,
                fields,
                methods,
                (&unit_field_name, unit_field_int_ty.clone()),
            );

            ctor_impl = bf.extend_ctor_impl(
                ctx,
                parent,
                ctor_impl,
                &ctor_name,
                &unit_field_int_ty,
            );
        }

        match ctor_impl.unwrap().node {
            ast::ItemKind::Impl(_, _, _, _, _, items) => {
                assert_eq!(items.len(), 1);
                methods.extend(items.into_iter());
            }
            _ => unreachable!(),
        };

        struct_layout.saw_bitfield_unit(self.layout());
    }
}

fn parent_has_method(
    ctx: &BindgenContext,
    parent: &CompInfo,
    name: &str,
) -> bool {
    parent.methods().iter().any(|method| {
        let method_name = match *ctx.resolve_item(method.signature()).kind() {
            ItemKind::Function(ref func) => func.name(),
            ref otherwise => {
                panic!(
                    "a method's signature should always be a \
                 item of kind ItemKind::Function, found: \
                 {:?}",
                    otherwise
                )
            }
        };

        method_name == name || ctx.rust_mangle(&method_name) == name
    })
}

fn bitfield_getter_name(
    ctx: &BindgenContext,
    parent: &CompInfo,
    bitfield_name: &str,
) -> ast::Ident {
    let name = ctx.rust_mangle(bitfield_name);

    if parent_has_method(ctx, parent, &name) {
        let mut name = name.to_string();
        name.push_str("_bindgen_bitfield");
        return ctx.ext_cx().ident_of(&name);
    }

    ctx.ext_cx().ident_of(&name)
}

fn bitfield_setter_name(
    ctx: &BindgenContext,
    parent: &CompInfo,
    bitfield_name: &str,
) -> ast::Ident {
    let setter = format!("set_{}", bitfield_name);
    let mut setter = ctx.rust_mangle(&setter).to_string();

    if parent_has_method(ctx, parent, &setter) {
        setter.push_str("_bindgen_bitfield");
    }

    ctx.ext_cx().ident_of(&setter)
}

impl<'a> FieldCodegen<'a> for Bitfield {
    type Extra = (&'a str, P<ast::Ty>);

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        _fields_should_be_private: bool,
        _codegen_depth: usize,
        _accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        _anon_field_names: &mut AnonFieldNames,
        _result: &mut CodegenResult,
        _struct_layout: &mut StructLayoutTracker,
        _fields: &mut F,
        methods: &mut M,
        (unit_field_name, unit_field_int_ty): (&'a str, P<ast::Ty>),
    ) where
        F: Extend<ast::StructField>,
        M: Extend<ast::ImplItem>,
    {
        let prefix = ctx.trait_prefix();
        let getter_name = bitfield_getter_name(ctx, parent, self.name());
        let setter_name = bitfield_setter_name(ctx, parent, self.name());
        let unit_field_ident = ctx.ext_cx().ident_of(unit_field_name);

        let bitfield_ty_item = ctx.resolve_item(self.ty());
        let bitfield_ty = bitfield_ty_item.expect_type();

        let bitfield_ty_layout = bitfield_ty.layout(ctx).expect(
            "Bitfield without layout? Gah!",
        );
        let bitfield_int_ty = helpers::blob(bitfield_ty_layout);

        let bitfield_ty =
            bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);

        let offset = self.offset_into_unit();
        let mask = self.mask();

        let impl_item = quote_item!(
            ctx.ext_cx(),
            impl XxxIgnored {
                #[inline]
                pub fn $getter_name(&self) -> $bitfield_ty {
                    let mut unit_field_val: $unit_field_int_ty = unsafe {
                        ::$prefix::mem::uninitialized()
                    };

                    unsafe {
                        ::$prefix::ptr::copy_nonoverlapping(
                            &self.$unit_field_ident as *const _ as *const u8,
                            &mut unit_field_val as *mut $unit_field_int_ty as *mut u8,
                            ::$prefix::mem::size_of::<$unit_field_int_ty>(),
                        )
                    };

                    let mask = $mask as $unit_field_int_ty;
                    let val = (unit_field_val & mask) >> $offset;
                    unsafe {
                        ::$prefix::mem::transmute(val as $bitfield_int_ty)
                    }
                }

                #[inline]
                pub fn $setter_name(&mut self, val: $bitfield_ty) {
                    let mask = $mask as $unit_field_int_ty;
                    let val = val as $bitfield_int_ty as $unit_field_int_ty;

                    let mut unit_field_val: $unit_field_int_ty = unsafe {
                        ::$prefix::mem::uninitialized()
                    };

                    unsafe {
                        ::$prefix::ptr::copy_nonoverlapping(
                            &self.$unit_field_ident as *const _ as *const u8,
                            &mut unit_field_val as *mut $unit_field_int_ty as *mut u8,
                            ::$prefix::mem::size_of::<$unit_field_int_ty>(),
                        )
                    };

                    unit_field_val &= !mask;
                    unit_field_val |= (val << $offset) & mask;

                    unsafe {
                        ::$prefix::ptr::copy_nonoverlapping(
                            &unit_field_val as *const _ as *const u8,
                            &mut self.$unit_field_ident as *mut _ as *mut u8,
                            ::$prefix::mem::size_of::<$unit_field_int_ty>(),
                        );
                    }
                }
            }
        ).unwrap();

        match impl_item.unwrap().node {
            ast::ItemKind::Impl(_, _, _, _, _, items) => {
                methods.extend(items.into_iter());
            }
            _ => unreachable!(),
        };
    }
}

impl CodeGenerator for CompInfo {
    type Extra = Item;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        debug!("<CompInfo as CodeGenerator>::codegen: item = {:?}", item);
        debug_assert!(item.is_enabled_for_codegen(ctx));

        // Don't output classes with template parameters that aren't types, and
        // also don't output template specializations, neither total or partial.
        if self.has_non_type_template_params() {
            return;
        }

        let used_template_params = item.used_template_params(ctx);

        // generate tuple struct if struct or union is a forward declaration,
        // skip for now if template parameters are needed.
        //
        // NB: We generate a proper struct to avoid struct/function name
        // collisions.
        if self.is_forward_declaration() && used_template_params.is_none() {
            let struct_name = item.canonical_name(ctx);
            let struct_name = ctx.rust_ident_raw(&struct_name);
            let tuple_struct = quote_item!(ctx.ext_cx(),
                                           #[repr(C)]
                                           #[derive(Debug, Copy, Clone)]
                                           pub struct $struct_name { _unused: [u8; 0] };
                                          )
                .unwrap();
            result.push(tuple_struct);
            return;
        }

        let mut attributes = vec![];
        let mut needs_clone_impl = false;
        let mut needs_default_impl = false;
        let mut needs_debug_impl = false;
        if let Some(comment) = item.comment(ctx) {
            attributes.push(attributes::doc(comment));
        }
        if self.packed() {
            attributes.push(attributes::repr_list(&["C", "packed"]));
        } else {
            attributes.push(attributes::repr("C"));
        }

        let is_union = self.kind() == CompKind::Union;
        let mut derives = vec![];
        if item.can_derive_debug(ctx) {
            derives.push("Debug");
        } else {
            needs_debug_impl = ctx.options().derive_debug &&
                ctx.options().impl_debug
        }

        if item.can_derive_default(ctx) {
            derives.push("Default");
        } else {
            needs_default_impl = ctx.options().derive_default;
        }

        if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
            derives.push("Copy");
            if used_template_params.is_some() {
                // FIXME: This requires extra logic if you have a big array in a
                // templated struct. The reason for this is that the magic:
                //     fn clone(&self) -> Self { *self }
                // doesn't work for templates.
                //
                // It's not hard to fix though.
                derives.push("Clone");
            } else {
                needs_clone_impl = true;
            }
        }

        if item.can_derive_hash(ctx) {
            derives.push("Hash");
        }

        if item.can_derive_partialeq(ctx) {
            derives.push("PartialEq");
        }

        if item.can_derive_eq(ctx) {
            derives.push("Eq");
        }

        if !derives.is_empty() {
            attributes.push(attributes::derives(&derives))
        }

        let canonical_name = item.canonical_name(ctx);
        let builder = if is_union && self.can_be_rust_union(ctx) {
            aster::AstBuilder::new()
                .item()
                .pub_()
                .with_attrs(attributes)
                .union_(&canonical_name)
        } else {
            aster::AstBuilder::new()
                .item()
                .pub_()
                .with_attrs(attributes)
                .struct_(&canonical_name)
        };

        // Generate the vtable from the method list if appropriate.
        //
        // TODO: I don't know how this could play with virtual methods that are
        // not in the list of methods found by us, we'll see. Also, could the
        // order of the vtable pointers vary?
        //
        // FIXME: Once we generate proper vtables, we need to codegen the
        // vtable, but *not* generate a field for it in the case that
        // needs_explicit_vtable is false but has_vtable is true.
        //
        // Also, we need to generate the vtable in such a way it "inherits" from
        // the parent too.
        let mut fields = vec![];
        let mut struct_layout =
            StructLayoutTracker::new(ctx, self, &canonical_name);
        if self.needs_explicit_vtable(ctx, item) {
            let vtable =
                Vtable::new(item.id(), self.methods(), self.base_members());
            vtable.codegen(ctx, result, item);

            let vtable_type = vtable
                .try_to_rust_ty(ctx, &())
                .expect("vtable to Rust type conversion is infallible")
                .to_ptr(true, ctx.span());

            let vtable_field = StructFieldBuilder::named("vtable_")
                .pub_()
                .build_ty(vtable_type);

            struct_layout.saw_vtable();

            fields.push(vtable_field);
        }

        for (i, base) in self.base_members().iter().enumerate() {
            // Virtual bases are already taken into account by the vtable
            // pointer.
            //
            // FIXME(emilio): Is this always right?
            if base.is_virtual() {
                continue;
            }

            let base_ty = ctx.resolve_type(base.ty);
            // NB: We won't include unsized types in our base chain because they
            // would contribute to our size given the dummy field we insert for
            // unsized types.
            if base_ty.is_unsized(ctx, &base.ty) {
                continue;
            }

            let inner = base.ty.to_rust_ty_or_opaque(ctx, &());
            let field_name = if i == 0 {
                "_base".into()
            } else {
                format!("_base_{}", i)
            };

            struct_layout.saw_base(base_ty);

            let field =
                StructFieldBuilder::named(field_name).pub_().build_ty(inner);
            fields.extend(Some(field));
        }
        if is_union {
            result.saw_union();
            if !self.can_be_rust_union(ctx) {
                result.saw_bindgen_union();
            }
        }

        let layout = item.kind().expect_type().layout(ctx);

        let fields_should_be_private =
            item.annotations().private_fields().unwrap_or(false);
        let struct_accessor_kind = item.annotations()
            .accessor_kind()
            .unwrap_or(FieldAccessorKind::None);

        let mut methods = vec![];
        let mut anon_field_names = AnonFieldNames::default();
        let codegen_depth = item.codegen_depth(ctx);
        for field in self.fields() {
            field.codegen(
                ctx,
                fields_should_be_private,
                codegen_depth,
                struct_accessor_kind,
                self,
                &mut anon_field_names,
                result,
                &mut struct_layout,
                &mut fields,
                &mut methods,
                (),
            );
        }

        if is_union {
            let layout = layout.expect("Unable to get layout information?");
            let ty = helpers::blob(layout);

            let field = if self.can_be_rust_union(ctx) {
                StructFieldBuilder::named("_bindgen_union_align").build_ty(ty)
            } else {
                struct_layout.saw_union(layout);

                StructFieldBuilder::named("bindgen_union_field")
                    .pub_()
                    .build_ty(ty)
            };

            fields.push(field);
        }

        // Yeah, sorry about that.
        let is_opaque = item.is_opaque(ctx, &());
        if is_opaque {
            fields.clear();
            methods.clear();

            match layout {
                Some(l) => {
                    let ty = helpers::blob(l);
                    let field = StructFieldBuilder::named(
                        "_bindgen_opaque_blob",
                    ).pub_()
                        .build_ty(ty);
                    fields.push(field);
                }
                None => {
                    warn!("Opaque type without layout! Expect dragons!");
                }
            }
        } else if !is_union && !self.is_unsized(ctx, &item.id()) {
            if let Some(padding_field) =
                layout.and_then(|layout| struct_layout.pad_struct(layout))
            {
                fields.push(padding_field);
            }

            if let Some(align_field) =
                layout.and_then(|layout| struct_layout.align_struct(layout))
            {
                fields.push(align_field);
            }
        }

        // C++ requires every struct to be addressable, so what C++ compilers do
        // is making the struct 1-byte sized.
        //
        // This is apparently not the case for C, see:
        // https://github.com/rust-lang-nursery/rust-bindgen/issues/551
        //
        // Just get the layout, and assume C++ if not.
        //
        // NOTE: This check is conveniently here to avoid the dummy fields we
        // may add for unused template parameters.
        if self.is_unsized(ctx, &item.id()) {
            let has_address = if is_opaque {
                // Generate the address field if it's an opaque type and
                // couldn't determine the layout of the blob.
                layout.is_none()
            } else {
                layout.map_or(true, |l| l.size != 0)
            };

            if has_address {
                let ty = helpers::blob(Layout::new(1, 1));
                let field =
                    StructFieldBuilder::named("_address").pub_().build_ty(ty);
                fields.push(field);
            }
        }

        let mut generics = aster::AstBuilder::new().generics();

        if let Some(ref params) = used_template_params {
            for (idx, ty) in params.iter().enumerate() {
                let param = ctx.resolve_type(*ty);
                let name = param.name().unwrap();
                let ident = ctx.rust_ident(name);

                generics = generics.ty_param_id(ident);

                let prefix = ctx.trait_prefix();
                let phantom_ty = quote_ty!(
                    ctx.ext_cx(),
                    ::$prefix::marker::PhantomData<::$prefix::cell::UnsafeCell<$ident>>);
                let phantom_field = StructFieldBuilder::named(
                    format!("_phantom_{}", idx),
                ).pub_()
                    .build_ty(phantom_ty);
                fields.push(phantom_field);
            }
        }

        let generics = generics.build();

        let rust_struct = builder
            .with_generics(generics.clone())
            .with_fields(fields)
            .build();
        result.push(rust_struct);

        // Generate the inner types and all that stuff.
        //
        // TODO: In the future we might want to be smart, and use nested
        // modules, and whatnot.
        for ty in self.inner_types() {
            let child_item = ctx.resolve_item(*ty);
            // assert_eq!(child_item.parent_id(), item.id());
            child_item.codegen(ctx, result, &());
        }

        // NOTE: Some unexposed attributes (like alignment attributes) may
        // affect layout, so we're bad and pray to the gods for avoid sending
        // all the tests to shit when parsing things like max_align_t.
        if self.found_unknown_attr() {
            warn!(
                "Type {} has an unkown attribute that may affect layout",
                canonical_name
            );
        }

        if used_template_params.is_none() {
            if !is_opaque {
                for var in self.inner_vars() {
                    ctx.resolve_item(*var).codegen(ctx, result, &());
                }
            }

            if ctx.options().layout_tests {
                if let Some(layout) = layout {
                    let fn_name =
                        format!("bindgen_test_layout_{}", canonical_name);
                    let fn_name = ctx.rust_ident_raw(&fn_name);
                    let type_name = ctx.rust_ident_raw(&canonical_name);
                    let prefix = ctx.trait_prefix();
                    let size_of_expr = quote_expr!(ctx.ext_cx(),
                                    ::$prefix::mem::size_of::<$type_name>());
                    let align_of_expr = quote_expr!(ctx.ext_cx(),
                                    ::$prefix::mem::align_of::<$type_name>());
                    let size = layout.size;
                    let align = layout.align;

                    let check_struct_align =
                        if align > mem::size_of::<*mut ()>() {
                            // FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready
                            None
                        } else {
                            quote_item!(ctx.ext_cx(),
                            assert_eq!($align_of_expr,
                                       $align,
                                       concat!("Alignment of ", stringify!($type_name)));
                        )
                        };

                    // FIXME when [issue #465](https://github.com/rust-lang-nursery/rust-bindgen/issues/465) ready
                    let too_many_base_vtables = self.base_members()
                        .iter()
                        .filter(|base| ctx.lookup_item_id_has_vtable(&base.ty))
                        .count() >
                        1;

                    let should_skip_field_offset_checks = is_opaque ||
                        too_many_base_vtables;

                    let check_field_offset =
                        if should_skip_field_offset_checks {
                            None
                        } else {
                            let asserts = self.fields()
                        .iter()
                        .filter_map(|field| match *field {
                            Field::DataMember(ref f) if f.name().is_some() => Some(f),
                            _ => None,
                        })
                        .flat_map(|field| {
                            let name = field.name().unwrap();
                            field.offset().and_then(|offset| {
                                let field_offset = offset / 8;
                                let field_name = ctx.rust_ident(name);

                                quote_item!(ctx.ext_cx(),
                                    assert_eq!(unsafe { &(*(0 as *const $type_name)).$field_name as *const _ as usize },
                                               $field_offset,
                                               concat!("Alignment of field: ", stringify!($type_name), "::", stringify!($field_name)));
                                )
                            })
                        })
                        .collect::<Vec<P<ast::Item>>>();

                            Some(asserts)
                        };

                    let item = quote_item!(ctx.ext_cx(),
                        #[test]
                        fn $fn_name() {
                            assert_eq!($size_of_expr,
                                       $size,
                                       concat!("Size of: ", stringify!($type_name)));

                            $check_struct_align
                            $check_field_offset
                        })
                        .unwrap();
                    result.push(item);
                }
            }

            let mut method_names = Default::default();
            if ctx.options().codegen_config.methods {
                for method in self.methods() {
                    assert!(method.kind() != MethodKind::Constructor);
                    method.codegen_method(
                        ctx,
                        &mut methods,
                        &mut method_names,
                        result,
                        self,
                    );
                }
            }

            if ctx.options().codegen_config.constructors {
                for sig in self.constructors() {
                    Method::new(
                        MethodKind::Constructor,
                        *sig,
                        /* const */
                        false,
                    ).codegen_method(
                        ctx,
                        &mut methods,
                        &mut method_names,
                        result,
                        self,
                    );
                }
            }

            if ctx.options().codegen_config.destructors {
                if let Some((is_virtual, destructor)) = self.destructor() {
                    let kind = if is_virtual {
                        MethodKind::VirtualDestructor
                    } else {
                        MethodKind::Destructor
                    };

                    Method::new(kind, destructor, false).codegen_method(
                        ctx,
                        &mut methods,
                        &mut method_names,
                        result,
                        self,
                    );
                }
            }
        }

        // NB: We can't use to_rust_ty here since for opaque types this tries to
        // use the specialization knowledge to generate a blob field.
        let ty_for_impl = aster::AstBuilder::new()
            .ty()
            .path()
            .segment(&canonical_name)
            .with_generics(generics.clone())
            .build()
            .build();

        if needs_clone_impl {
            let impl_ = quote_item!(ctx.ext_cx(),
                impl X {
                    fn clone(&self) -> Self { *self }
                }
            );

            let impl_ = match impl_.unwrap().node {
                ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
                _ => unreachable!(),
            };

            let clone_impl = aster::AstBuilder::new()
                .item()
                .impl_()
                .trait_()
                .id("Clone")
                .build()
                .with_generics(generics.clone())
                .with_items(impl_)
                .build_ty(ty_for_impl.clone());

            result.push(clone_impl);
        }

        if needs_default_impl {
            let prefix = ctx.trait_prefix();
            let impl_ = quote_item!(ctx.ext_cx(),
                impl X {
                    fn default() -> Self { unsafe { ::$prefix::mem::zeroed() } }
                }
            );

            let impl_ = match impl_.unwrap().node {
                ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
                _ => unreachable!(),
            };

            let default_impl = aster::AstBuilder::new()
                .item()
                .impl_()
                .trait_()
                .id("Default")
                .build()
                .with_generics(generics.clone())
                .with_items(impl_)
                .build_ty(ty_for_impl.clone());

            result.push(default_impl);
        }

        if needs_debug_impl {
            let impl_ = derive_debug::gen_debug_impl(
                ctx,
                self.fields(),
                item,
                self.kind(),
            );

            let debug_impl = aster::AstBuilder::new()
                .item()
                .impl_()
                .trait_()
                .id("::std::fmt::Debug")
                .build()
                .with_generics(generics.clone())
                .with_items(impl_)
                .build_ty(ty_for_impl.clone());

            result.push(debug_impl);
        }

        if !methods.is_empty() {
            let methods = aster::AstBuilder::new()
                .item()
                .impl_()
                .with_generics(generics)
                .with_items(methods)
                .build_ty(ty_for_impl);
            result.push(methods);
        }
    }
}

trait MethodCodegen {
    fn codegen_method<'a>(
        &self,
        ctx: &BindgenContext,
        methods: &mut Vec<ast::ImplItem>,
        method_names: &mut HashMap<String, usize>,
        result: &mut CodegenResult<'a>,
        parent: &CompInfo,
    );
}

impl MethodCodegen for Method {
    fn codegen_method<'a>(
        &self,
        ctx: &BindgenContext,
        methods: &mut Vec<ast::ImplItem>,
        method_names: &mut HashMap<String, usize>,
        result: &mut CodegenResult<'a>,
        _parent: &CompInfo,
    ) {
        assert!({
            let cc = &ctx.options().codegen_config;
            match self.kind() {
                MethodKind::Constructor => cc.constructors,
                MethodKind::Destructor => cc.destructors,
                MethodKind::VirtualDestructor => cc.destructors,
                MethodKind::Static | MethodKind::Normal |
                MethodKind::Virtual => cc.methods,
            }
        });

        if self.is_virtual() {
            return; // FIXME
        }

        // First of all, output the actual function.
        let function_item = ctx.resolve_item(self.signature());
        function_item.codegen(ctx, result, &());

        let function = function_item.expect_function();
        let signature_item = ctx.resolve_item(function.signature());
        let mut name = match self.kind() {
            MethodKind::Constructor => "new".into(),
            MethodKind::Destructor => "destruct".into(),
            _ => function.name().to_owned(),
        };

        let signature = match *signature_item.expect_type().kind() {
            TypeKind::Function(ref sig) => sig,
            _ => panic!("How in the world?"),
        };

        // Do not generate variadic methods, since rust does not allow
        // implementing them, and we don't do a good job at it anyway.
        if signature.is_variadic() {
            return;
        }

        let count = {
            let count = method_names.entry(name.clone()).or_insert(0);
            *count += 1;
            *count - 1
        };

        if count != 0 {
            name.push_str(&count.to_string());
        }

        let function_name = function_item.canonical_name(ctx);
        let mut fndecl = utils::rust_fndecl_from_signature(ctx, signature_item)
            .unwrap();
        if !self.is_static() && !self.is_constructor() {
            let mutability = if self.is_const() {
                ast::Mutability::Immutable
            } else {
                ast::Mutability::Mutable
            };

            assert!(!fndecl.inputs.is_empty());

            // FIXME: use aster here.
            fndecl.inputs[0] = ast::Arg {
                ty: P(ast::Ty {
                    id: ast::DUMMY_NODE_ID,
                    node: ast::TyKind::Rptr(
                        None,
                        ast::MutTy {
                            ty: P(ast::Ty {
                                id: ast::DUMMY_NODE_ID,
                                node: ast::TyKind::ImplicitSelf,
                                span: ctx.span(),
                            }),
                            mutbl: mutability,
                        },
                    ),
                    span: ctx.span(),
                }),
                pat: P(ast::Pat {
                    id: ast::DUMMY_NODE_ID,
                    node: ast::PatKind::Ident(
                        ast::BindingMode::ByValue(ast::Mutability::Immutable),
                        respan(ctx.span(), ctx.ext_cx().ident_of("self")),
                        None,
                    ),
                    span: ctx.span(),
                }),
                id: ast::DUMMY_NODE_ID,
            };
        }

        // If it's a constructor, we always return `Self`, and we inject the
        // "this" parameter, so there's no need to ask the user for it.
        //
        // Note that constructors in Clang are represented as functions with
        // return-type = void.
        if self.is_constructor() {
            fndecl.inputs.remove(0);
            fndecl.output =
                ast::FunctionRetTy::Ty(quote_ty!(ctx.ext_cx(), Self));
        }

        let sig = ast::MethodSig {
            unsafety: ast::Unsafety::Unsafe,
            abi: abi::Abi::Rust,
            decl: P(fndecl),
            generics: ast::Generics::default(),
            constness: respan(ctx.span(), ast::Constness::NotConst),
        };

        let mut exprs =
            helpers::ast_ty::arguments_from_signature(&signature, ctx);

        let mut stmts = vec![];

        // If it's a constructor, we need to insert an extra parameter with a
        // variable called `__bindgen_tmp` we're going to create.
        if self.is_constructor() {
            let prefix = ctx.trait_prefix();
            let tmp_variable_decl =
                quote_stmt!(ctx.ext_cx(),
                            let mut __bindgen_tmp = ::$prefix::mem::uninitialized())
                .unwrap();
            stmts.push(tmp_variable_decl);
            exprs[0] = quote_expr!(ctx.ext_cx(), &mut __bindgen_tmp);
        } else if !self.is_static() {
            assert!(!exprs.is_empty());
            exprs[0] = quote_expr!(ctx.ext_cx(), self);
        };

        let call = aster::expr::ExprBuilder::new()
            .call()
            .id(function_name)
            .with_args(exprs)
            .build();

        stmts.push(ast::Stmt {
            id: ast::DUMMY_NODE_ID,
            node: ast::StmtKind::Expr(call),
            span: ctx.span(),
        });

        if self.is_constructor() {
            stmts.push(quote_stmt!(ctx.ext_cx(), __bindgen_tmp).unwrap());
        }

        let block = ast::Block {
            stmts: stmts,
            id: ast::DUMMY_NODE_ID,
            rules: ast::BlockCheckMode::Default,
            span: ctx.span(),
        };

        let mut attrs = vec![];
        attrs.push(attributes::inline());

        let item = ast::ImplItem {
            id: ast::DUMMY_NODE_ID,
            ident: ctx.rust_ident(&name),
            vis: ast::Visibility::Public,
            attrs: attrs,
            node: ast::ImplItemKind::Method(sig, P(block)),
            defaultness: ast::Defaultness::Final,
            span: ctx.span(),
        };

        methods.push(item);
    }
}

/// A helper type to construct enums, either bitfield ones or rust-style ones.
enum EnumBuilder<'a> {
    Rust(aster::item::ItemEnumBuilder<aster::invoke::Identity>),
    Bitfield {
        canonical_name: &'a str,
        aster: P<ast::Item>,
    },
    Consts { aster: P<ast::Item> },
    ModuleConsts {
        module_name: &'a str,
        module_items: Vec<P<ast::Item>>,
    },
}

impl<'a> EnumBuilder<'a> {
    /// Create a new enum given an item builder, a canonical name, a name for
    /// the representation, and whether it should be represented as a rust enum.
    fn new(
        aster: aster::item::ItemBuilder<aster::invoke::Identity>,
        name: &'a str,
        repr: P<ast::Ty>,
        bitfield_like: bool,
        constify: bool,
        constify_module: bool,
    ) -> Self {
        if bitfield_like {
            EnumBuilder::Bitfield {
                canonical_name: name,
                aster: aster
                    .tuple_struct(name)
                    .field()
                    .pub_()
                    .build_ty(repr)
                    .build(),
            }
        } else if constify {
            if constify_module {
                let type_definition = aster::item::ItemBuilder::new()
                    .pub_()
                    .type_(CONSTIFIED_ENUM_MODULE_REPR_NAME)
                    .build_ty(repr);

                EnumBuilder::ModuleConsts {
                    module_name: name,
                    module_items: vec![type_definition],
                }
            } else {
                EnumBuilder::Consts {
                    aster: aster.type_(name).build_ty(repr),
                }
            }
        } else {
            EnumBuilder::Rust(aster.enum_(name))
        }
    }

    /// Add a variant to this enum.
    fn with_variant<'b>(
        self,
        ctx: &BindgenContext,
        variant: &EnumVariant,
        mangling_prefix: Option<&String>,
        rust_ty: P<ast::Ty>,
        result: &mut CodegenResult<'b>,
    ) -> Self {
        let variant_name = ctx.rust_mangle(variant.name());
        let expr = aster::AstBuilder::new().expr();
        let expr = match variant.val() {
            EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
            EnumVariantValue::Unsigned(v) => expr.uint(v),
        };

        match self {
            EnumBuilder::Rust(b) => {
                EnumBuilder::Rust(b.with_variant_(ast::Variant_ {
                    name: ctx.rust_ident(&*variant_name),
                    attrs: vec![],
                    data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
                    disr_expr: Some(expr),
                }))
            }
            EnumBuilder::Bitfield {
                canonical_name, ..
            } => {
                let constant_name = match mangling_prefix {
                    Some(prefix) => {
                        Cow::Owned(format!("{}_{}", prefix, variant_name))
                    }
                    None => variant_name,
                };

                let constant = aster::AstBuilder::new()
                    .item()
                    .pub_()
                    .const_(&*constant_name)
                    .expr()
                    .call()
                    .id(canonical_name)
                    .arg()
                    .build(expr)
                    .build()
                    .build(rust_ty);
                result.push(constant);
                self
            }
            EnumBuilder::Consts {
                ..
            } => {
                let constant_name = match mangling_prefix {
                    Some(prefix) => {
                        Cow::Owned(format!("{}_{}", prefix, variant_name))
                    }
                    None => variant_name,
                };

                let constant = aster::AstBuilder::new()
                    .item()
                    .pub_()
                    .const_(&*constant_name)
                    .expr()
                    .build(expr)
                    .build(rust_ty);

                result.push(constant);
                self
            }
            EnumBuilder::ModuleConsts {
                module_name,
                module_items,
                ..
            } => {
                // Variant type
                let inside_module_type = aster::AstBuilder::new().ty().id(
                    CONSTIFIED_ENUM_MODULE_REPR_NAME,
                );

                let constant = aster::AstBuilder::new()
                    .item()
                    .pub_()
                    .const_(&*variant_name)
                    .expr()
                    .build(expr)
                    .build(inside_module_type.clone());

                let mut module_items = module_items.clone();
                module_items.push(constant);

                EnumBuilder::ModuleConsts {
                    module_name,
                    module_items,
                }
            }
        }
    }

    fn build<'b>(
        self,
        ctx: &BindgenContext,
        rust_ty: P<ast::Ty>,
        result: &mut CodegenResult<'b>,
    ) -> P<ast::Item> {
        match self {
            EnumBuilder::Rust(b) => b.build(),
            EnumBuilder::Bitfield {
                canonical_name,
                aster,
            } => {
                let rust_ty_name = ctx.rust_ident_raw(canonical_name);
                let prefix = ctx.trait_prefix();

                let impl_ = quote_item!(ctx.ext_cx(),
                    impl ::$prefix::ops::BitOr<$rust_ty> for $rust_ty {
                        type Output = Self;

                        #[inline]
                        fn bitor(self, other: Self) -> Self {
                            $rust_ty_name(self.0 | other.0)
                        }
                    }
                ).unwrap();
                result.push(impl_);

                let impl_ = quote_item!(ctx.ext_cx(),
                    impl ::$prefix::ops::BitOrAssign for $rust_ty {
                        #[inline]
                        fn bitor_assign(&mut self, rhs: $rust_ty) {
                            self.0 |= rhs.0;
                        }
                    }
                ).unwrap();
                result.push(impl_);

                let impl_ = quote_item!(ctx.ext_cx(),
                    impl ::$prefix::ops::BitAnd<$rust_ty> for $rust_ty {
                        type Output = Self;

                        #[inline]
                        fn bitand(self, other: Self) -> Self {
                            $rust_ty_name(self.0 & other.0)
                        }
                    }
                ).unwrap();
                result.push(impl_);

                let impl_ = quote_item!(ctx.ext_cx(),
                    impl ::$prefix::ops::BitAndAssign for $rust_ty {
                        #[inline]
                        fn bitand_assign(&mut self, rhs: $rust_ty) {
                            self.0 &= rhs.0;
                        }
                    }
                ).unwrap();
                result.push(impl_);

                aster
            }
            EnumBuilder::Consts {
                aster, ..
            } => aster,
            EnumBuilder::ModuleConsts {
                module_items,
                module_name,
                ..
            } => {
                // Create module item with type and variant definitions
                let module_item = P(ast::Item {
                    ident: ast::Ident::from_str(module_name),
                    attrs: vec![],
                    id: ast::DUMMY_NODE_ID,
                    node: ast::ItemKind::Mod(ast::Mod {
                        inner: DUMMY_SP,
                        items: module_items,
                    }),
                    vis: ast::Visibility::Public,
                    span: DUMMY_SP,
                });

                module_item
            }
        }
    }
}

impl CodeGenerator for Enum {
    type Extra = Item;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        debug!("<Enum as CodeGenerator>::codegen: item = {:?}", item);
        debug_assert!(item.is_enabled_for_codegen(ctx));

        let name = item.canonical_name(ctx);
        let enum_ty = item.expect_type();
        let layout = enum_ty.layout(ctx);

        let repr = self.repr().map(|repr| ctx.resolve_type(repr));
        let repr = match repr {
            Some(repr) => {
                match *repr.canonical_type(ctx).kind() {
                    TypeKind::Int(int_kind) => int_kind,
                    _ => panic!("Unexpected type as enum repr"),
                }
            }
            None => {
                warn!(
                    "Guessing type of enum! Forward declarations of enums \
                     shouldn't be legal!"
                );
                IntKind::Int
            }
        };

        let signed = repr.is_signed();
        let size = layout
            .map(|l| l.size)
            .or_else(|| repr.known_size())
            .unwrap_or(0);

        let repr_name = match (signed, size) {
            (true, 1) => "i8",
            (false, 1) => "u8",
            (true, 2) => "i16",
            (false, 2) => "u16",
            (true, 4) => "i32",
            (false, 4) => "u32",
            (true, 8) => "i64",
            (false, 8) => "u64",
            _ => {
                warn!("invalid enum decl: signed: {}, size: {}", signed, size);
                "i32"
            }
        };

        let mut builder = aster::AstBuilder::new().item().pub_();

        // FIXME(emilio): These should probably use the path so it can
        // disambiguate between namespaces, just like is_opaque etc.
        let is_bitfield = {
            ctx.options().bitfield_enums.matches(&name) ||
                (enum_ty.name().is_none() &&
                     self.variants().iter().any(|v| {
                        ctx.options().bitfield_enums.matches(&v.name())
                    }))
        };

        let is_constified_enum_module =
            self.is_constified_enum_module(ctx, item);

        let is_constified_enum = {
            is_constified_enum_module ||
                ctx.options().constified_enums.matches(&name) ||
                (enum_ty.name().is_none() &&
                     self.variants().iter().any(|v| {
                        ctx.options().constified_enums.matches(&v.name())
                    }))
        };

        let is_rust_enum = !is_bitfield && !is_constified_enum;

        // FIXME: Rust forbids repr with empty enums. Remove this condition when
        // this is allowed.
        //
        // TODO(emilio): Delegate this to the builders?
        if is_rust_enum {
            if !self.variants().is_empty() {
                builder = builder.with_attr(attributes::repr(repr_name));
            }
        } else if is_bitfield {
            builder = builder.with_attr(attributes::repr("C"));
        }

        if let Some(comment) = item.comment(ctx) {
            builder = builder.with_attr(attributes::doc(comment));
        }

        if !is_constified_enum {
            let derives =
                attributes::derives(
                    &["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"],
                );

            builder = builder.with_attr(derives);
        }

        fn add_constant<'a>(
            ctx: &BindgenContext,
            enum_: &Type,
            // Only to avoid recomputing every time.
            enum_canonical_name: &str,
            // May be the same as "variant" if it's because the
            // enum is unnamed and we still haven't seen the
            // value.
            variant_name: &str,
            referenced_name: &str,
            enum_rust_ty: P<ast::Ty>,
            result: &mut CodegenResult<'a>,
        ) {
            let constant_name = if enum_.name().is_some() {
                if ctx.options().prepend_enum_name {
                    format!("{}_{}", enum_canonical_name, variant_name)
                } else {
                    variant_name.into()
                }
            } else {
                variant_name.into()
            };

            let constant = aster::AstBuilder::new()
                .item()
                .pub_()
                .const_(constant_name)
                .expr()
                .path()
                .ids(&[&*enum_canonical_name, referenced_name])
                .build()
                .build(enum_rust_ty);
            result.push(constant);
        }

        let repr =
            self.repr()
                .and_then(|repr| repr.try_to_rust_ty_or_opaque(ctx, &()).ok())
                .unwrap_or_else(|| helpers::ast_ty::raw_type(ctx, repr_name));

        let mut builder = EnumBuilder::new(
            builder,
            &name,
            repr,
            is_bitfield,
            is_constified_enum,
            is_constified_enum_module,
        );

        // A map where we keep a value -> variant relation.
        let mut seen_values = HashMap::<_, String>::new();
        let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &());
        let is_toplevel = item.is_toplevel(ctx);

        // Used to mangle the constants we generate in the unnamed-enum case.
        let parent_canonical_name = if is_toplevel {
            None
        } else {
            Some(item.parent_id().canonical_name(ctx))
        };

        let constant_mangling_prefix = if ctx.options().prepend_enum_name {
            if enum_ty.name().is_none() {
                parent_canonical_name.as_ref().map(|n| &*n)
            } else {
                Some(&name)
            }
        } else {
            None
        };

        // NB: We defer the creation of constified variants, in case we find
        // another variant with the same value (which is the common thing to
        // do).
        let mut constified_variants = VecDeque::new();

        let mut iter = self.variants().iter().peekable();
        while let Some(variant) = iter.next().or_else(|| {
            constified_variants.pop_front()
        })
        {
            if variant.hidden() {
                continue;
            }

            if variant.force_constification() && iter.peek().is_some() {
                constified_variants.push_back(variant);
                continue;
            }

            match seen_values.entry(variant.val()) {
                Entry::Occupied(ref entry) => {
                    if is_rust_enum {
                        let variant_name = ctx.rust_mangle(variant.name());
                        let mangled_name =
                            if is_toplevel || enum_ty.name().is_some() {
                                variant_name
                            } else {
                                let parent_name =
                                    parent_canonical_name.as_ref().unwrap();

                                Cow::Owned(
                                    format!("{}_{}", parent_name, variant_name),
                                )
                            };

                        let existing_variant_name = entry.get();
                        add_constant(
                            ctx,
                            enum_ty,
                            &name,
                            &*mangled_name,
                            existing_variant_name,
                            enum_rust_ty.clone(),
                            result,
                        );
                    } else {
                        builder = builder.with_variant(
                            ctx,
                            variant,
                            constant_mangling_prefix,
                            enum_rust_ty.clone(),
                            result,
                        );
                    }
                }
                Entry::Vacant(entry) => {
                    builder = builder.with_variant(
                        ctx,
                        variant,
                        constant_mangling_prefix,
                        enum_rust_ty.clone(),
                        result,
                    );

                    let variant_name = ctx.rust_mangle(variant.name());

                    // If it's an unnamed enum, or constification is enforced,
                    // we also generate a constant so it can be properly
                    // accessed.
                    if (is_rust_enum && enum_ty.name().is_none()) ||
                        variant.force_constification()
                    {
                        let mangled_name = if is_toplevel {
                            variant_name.clone()
                        } else {
                            let parent_name =
                                parent_canonical_name.as_ref().unwrap();

                            Cow::Owned(
                                format!("{}_{}", parent_name, variant_name),
                            )
                        };

                        add_constant(
                            ctx,
                            enum_ty,
                            &name,
                            &mangled_name,
                            &variant_name,
                            enum_rust_ty.clone(),
                            result,
                        );
                    }

                    entry.insert(variant_name.into_owned());
                }
            }
        }

        let enum_ = builder.build(ctx, enum_rust_ty, result);
        result.push(enum_);
    }
}

/// Fallible conversion to an opaque blob.
///
/// Implementors of this trait should provide the `try_get_layout` method to
/// fallibly get this thing's layout, which the provided `try_to_opaque` trait
/// method will use to convert the `Layout` into an opaque blob Rust type.
trait TryToOpaque {
    type Extra;

    /// Get the layout for this thing, if one is available.
    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> error::Result<Layout>;

    /// Do not override this provided trait method.
    fn try_to_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> error::Result<P<ast::Ty>> {
        self.try_get_layout(ctx, extra).map(|layout| {
            helpers::blob(layout)
        })
    }
}

/// Infallible conversion of an IR thing to an opaque blob.
///
/// The resulting layout is best effort, and is unfortunately not guaranteed to
/// be correct. When all else fails, we fall back to a single byte layout as a
/// last resort, because C++ does not permit zero-sized types. See the note in
/// the `ToRustTyOrOpaque` doc comment about fallible versus infallible traits
/// and when each is appropriate.
///
/// Don't implement this directly. Instead implement `TryToOpaque`, and then
/// leverage the blanket impl for this trait.
trait ToOpaque: TryToOpaque {
    fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout {
        self.try_get_layout(ctx, extra).unwrap_or_else(
            |_| Layout::for_size(1),
        )
    }

    fn to_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> P<ast::Ty> {
        let layout = self.get_layout(ctx, extra);
        helpers::blob(layout)
    }
}

impl<T> ToOpaque for T
where
    T: TryToOpaque,
{
}

/// Fallible conversion from an IR thing to an *equivalent* Rust type.
///
/// If the C/C++ construct represented by the IR thing cannot (currently) be
/// represented in Rust (for example, instantiations of templates with
/// const-value generic parameters) then the impl should return an `Err`. It
/// should *not* attempt to return an opaque blob with the correct size and
/// alignment. That is the responsibility of the `TryToOpaque` trait.
trait TryToRustTy {
    type Extra;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> error::Result<P<ast::Ty>>;
}

/// Fallible conversion to a Rust type or an opaque blob with the correct size
/// and alignment.
///
/// Don't implement this directly. Instead implement `TryToRustTy` and
/// `TryToOpaque`, and then leverage the blanket impl for this trait below.
trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque {
    type Extra;

    fn try_to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &<Self as TryToRustTyOrOpaque>::Extra,
    ) -> error::Result<P<ast::Ty>>;
}

impl<E, T> TryToRustTyOrOpaque for T
where
    T: TryToRustTy<Extra = E>
        + TryToOpaque<Extra = E>,
{
    type Extra = E;

    fn try_to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &E,
    ) -> error::Result<P<ast::Ty>> {
        self.try_to_rust_ty(ctx, extra).or_else(
            |_| if let Ok(layout) =
                self.try_get_layout(ctx, extra)
            {
                Ok(helpers::blob(layout))
            } else {
                Err(error::Error::NoLayoutForOpaqueBlob)
            },
        )
    }
}

/// Infallible conversion to a Rust type, or an opaque blob with a best effort
/// of correct size and alignment.
///
/// Don't implement this directly. Instead implement `TryToRustTy` and
/// `TryToOpaque`, and then leverage the blanket impl for this trait below.
///
/// ### Fallible vs. Infallible Conversions to Rust Types
///
/// When should one use this infallible `ToRustTyOrOpaque` trait versus the
/// fallible `TryTo{RustTy, Opaque, RustTyOrOpaque}` triats? All fallible trait
/// implementations that need to convert another thing into a Rust type or
/// opaque blob in a nested manner should also use fallible trait methods and
/// propagate failure up the stack. Only infallible functions and methods like
/// CodeGenerator implementations should use the infallible
/// `ToRustTyOrOpaque`. The further out we push error recovery, the more likely
/// we are to get a usable `Layout` even if we can't generate an equivalent Rust
/// type for a C++ construct.
trait ToRustTyOrOpaque: TryToRustTy + ToOpaque {
    type Extra;

    fn to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &<Self as ToRustTyOrOpaque>::Extra,
    ) -> P<ast::Ty>;
}

impl<E, T> ToRustTyOrOpaque for T
where
    T: TryToRustTy<Extra = E> + ToOpaque<Extra = E>,
{
    type Extra = E;

    fn to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &E,
    ) -> P<ast::Ty> {
        self.try_to_rust_ty(ctx, extra).unwrap_or_else(|_| {
            self.to_opaque(ctx, extra)
        })
    }
}

impl TryToOpaque for ItemId {
    type Extra = ();

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<Layout> {
        ctx.resolve_item(*self).try_get_layout(ctx, &())
    }
}

impl TryToRustTy for ItemId {
    type Extra = ();

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<P<ast::Ty>> {
        ctx.resolve_item(*self).try_to_rust_ty(ctx, &())
    }
}

impl TryToOpaque for Item {
    type Extra = ();

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<Layout> {
        self.kind().expect_type().try_get_layout(ctx, self)
    }
}

impl TryToRustTy for Item {
    type Extra = ();

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<P<ast::Ty>> {
        self.kind().expect_type().try_to_rust_ty(ctx, self)
    }
}

impl TryToOpaque for Type {
    type Extra = Item;

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        _: &Item,
    ) -> error::Result<Layout> {
        self.layout(ctx).ok_or(error::Error::NoLayoutForOpaqueBlob)
    }
}

impl TryToRustTy for Type {
    type Extra = Item;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> error::Result<P<ast::Ty>> {
        use self::helpers::ast_ty::*;

        match *self.kind() {
            TypeKind::Void => Ok(raw_type(ctx, "c_void")),
            // TODO: we should do something smart with nullptr, or maybe *const
            // c_void is enough?
            TypeKind::NullPtr => {
                Ok(raw_type(ctx, "c_void").to_ptr(true, ctx.span()))
            }
            TypeKind::Int(ik) => {
                match ik {
                    IntKind::Bool => Ok(aster::ty::TyBuilder::new().bool()),
                    IntKind::Char {
                        ..
                    } => Ok(raw_type(ctx, "c_char")),
                    IntKind::SChar => Ok(raw_type(ctx, "c_schar")),
                    IntKind::UChar => Ok(raw_type(ctx, "c_uchar")),
                    IntKind::Short => Ok(raw_type(ctx, "c_short")),
                    IntKind::UShort => Ok(raw_type(ctx, "c_ushort")),
                    IntKind::Int => Ok(raw_type(ctx, "c_int")),
                    IntKind::UInt => Ok(raw_type(ctx, "c_uint")),
                    IntKind::Long => Ok(raw_type(ctx, "c_long")),
                    IntKind::ULong => Ok(raw_type(ctx, "c_ulong")),
                    IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")),
                    IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")),

                    IntKind::I8 => Ok(aster::ty::TyBuilder::new().i8()),
                    IntKind::U8 => Ok(aster::ty::TyBuilder::new().u8()),
                    IntKind::I16 => Ok(aster::ty::TyBuilder::new().i16()),
                    IntKind::U16 => Ok(aster::ty::TyBuilder::new().u16()),
                    IntKind::I32 => Ok(aster::ty::TyBuilder::new().i32()),
                    IntKind::U32 => Ok(aster::ty::TyBuilder::new().u32()),
                    IntKind::I64 => Ok(aster::ty::TyBuilder::new().i64()),
                    IntKind::U64 => Ok(aster::ty::TyBuilder::new().u64()),
                    IntKind::Custom {
                        name, ..
                    } => {
                        let ident = ctx.rust_ident_raw(name);
                        Ok(quote_ty!(ctx.ext_cx(), $ident))
                    }
                    // FIXME: This doesn't generate the proper alignment, but we
                    // can't do better right now. We should be able to use
                    // i128/u128 when they're available.
                    IntKind::U128 | IntKind::I128 => {
                        Ok(aster::ty::TyBuilder::new().array(2).u64())
                    }
                }
            }
            TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk)),
            TypeKind::Complex(fk) => {
                let float_path = float_kind_rust_type(ctx, fk);

                ctx.generated_bindegen_complex();
                Ok(if ctx.options().enable_cxx_namespaces {
                    quote_ty!(ctx.ext_cx(), root::__BindgenComplex<$float_path>)
                } else {
                    quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>)
                })
            }
            TypeKind::Function(ref fs) => {
                // We can't rely on the sizeof(Option<NonZero<_>>) ==
                // sizeof(NonZero<_>) optimization with opaque blobs (because
                // they aren't NonZero), so don't *ever* use an or_opaque
                // variant here.
                let ty = fs.try_to_rust_ty(ctx, item)?;

                let prefix = ctx.trait_prefix();
                Ok(quote_ty!(ctx.ext_cx(), ::$prefix::option::Option<$ty>))
            }
            TypeKind::Array(item, len) => {
                let ty = item.try_to_rust_ty(ctx, &())?;
                Ok(aster::ty::TyBuilder::new().array(len).build(ty))
            }
            TypeKind::Enum(..) => {
                let path = item.namespace_aware_canonical_path(ctx);
                Ok(aster::AstBuilder::new().ty().path().ids(path).build())
            }
            TypeKind::TemplateInstantiation(ref inst) => {
                inst.try_to_rust_ty(ctx, item)
            }
            TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
            TypeKind::TemplateAlias(inner, _) |
            TypeKind::Alias(inner) => {
                let template_params = item.used_template_params(ctx)
                    .unwrap_or(vec![])
                    .into_iter()
                    .filter(|param| param.is_template_param(ctx, &()))
                    .collect::<Vec<_>>();

                let spelling = self.name().expect("Unnamed alias?");
                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,
                    inner,
                )
                {
                    Ok(ty)
                } else {
                    utils::build_templated_path(item, ctx, template_params)
                }
            }
            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())
                {
                    return self.try_to_opaque(ctx, item);
                }

                let template_params = template_params.unwrap_or(vec![]);
                utils::build_templated_path(item, ctx, template_params)
            }
            TypeKind::Opaque => self.try_to_opaque(ctx, item),
            TypeKind::BlockPointer => {
                let void = raw_type(ctx, "c_void");
                Ok(void.to_ptr(
                    /* is_const = */
                    false,
                    ctx.span(),
                ))
            }
            TypeKind::Pointer(inner) |
            TypeKind::Reference(inner) => {
                let inner = ctx.resolve_item(inner);
                let inner_ty = inner.expect_type();

                // Regardless if we can properly represent the inner type, we
                // should always generate a proper pointer here, so use
                // infallible conversion of the inner type.
                let ty = inner.to_rust_ty_or_opaque(ctx, &());

                // Avoid the first function pointer level, since it's already
                // represented in Rust.
                if inner_ty.canonical_type(ctx).is_function() {
                    Ok(ty)
                } else {
                    let is_const = self.is_const() ||
                        inner.expect_type().is_const();
                    Ok(ty.to_ptr(is_const, ctx.span()))
                }
            }
            TypeKind::TypeParam => {
                let name = item.canonical_name(ctx);
                let ident = ctx.rust_ident(&name);
                Ok(quote_ty!(ctx.ext_cx(), $ident))
            }
            TypeKind::ObjCSel => {
                Ok(quote_ty!(ctx.ext_cx(), objc::runtime::Sel))
            }
            TypeKind::ObjCId |
            TypeKind::ObjCInterface(..) => Ok(quote_ty!(ctx.ext_cx(), id)),
            ref u @ TypeKind::UnresolvedTypeRef(..) => {
                unreachable!("Should have been resolved after parsing {:?}!", u)
            }
        }
    }
}

impl TryToOpaque for TemplateInstantiation {
    type Extra = Item;

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> error::Result<Layout> {
        item.expect_type().layout(ctx).ok_or(
            error::Error::NoLayoutForOpaqueBlob,
        )
    }
}

impl TryToRustTy for TemplateInstantiation {
    type Extra = Item;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        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();

        let decl_params = match decl.self_template_params(ctx) {
            Some(params) => params,
            None => {
                // This can happen if we generated an opaque type for a partial
                // template specialization, and we've hit an instantiation of
                // that partial specialization.
                extra_assert!(
                    decl.into_resolver()
                        .through_type_refs()
                        .resolve(ctx)
                        .is_opaque(ctx, &())
                );
                return Err(error::Error::InstantiationOfOpaqueType);
            }
        };

        // TODO: If the decl type is a template class/struct
        // declaration's member template declaration, it could rely on
        // generic template parameters from its outer template
        // class/struct. When we emit bindings for it, it could require
        // *more* type arguments than we have here, and we will need to
        // reconstruct them somehow. We don't have any means of doing
        // that reconstruction at this time.

        if let ast::TyKind::Path(_, ref mut path) = ty.node {
            let template_args = self.template_arguments()
                .iter()
                .zip(decl_params.iter())
                // Only pass type arguments for the type parameters that
                // the decl uses.
                .filter(|&(_, param)| ctx.uses_template_parameter(decl, *param))
                .map(|(arg, _)| arg.try_to_rust_ty(ctx, &()))
                .collect::<error::Result<Vec<_>>>()?;

            path.segments.last_mut().unwrap().parameters =
                if template_args.is_empty() {
                    None
                } else {
                    Some(P(ast::PathParameters::AngleBracketed(
                        ast::AngleBracketedParameterData {
                            lifetimes: vec![],
                            types: template_args,
                            bindings: vec![],
                        },
                    )))
                }
        }

        Ok(P(ty))
    }
}

impl TryToRustTy for FunctionSig {
    type Extra = Item;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> error::Result<P<ast::Ty>> {
        // TODO: we might want to consider ignoring the reference return value.
        let ret = utils::fnsig_return_ty(ctx, &self);
        let arguments = utils::fnsig_arguments(ctx, &self);

        let decl = P(ast::FnDecl {
            inputs: arguments,
            output: ret,
            variadic: self.is_variadic(),
        });

        let abi = match self.abi() {
            Abi::Known(abi) => abi,
            Abi::Unknown(unknown_abi) => {
                panic!(
                    "Invalid or unknown abi {:?} for function {:?} {:?}",
                    unknown_abi,
                    item.canonical_name(ctx),
                    self
                );
            }
        };

        let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
            unsafety: ast::Unsafety::Unsafe,
            abi: abi,
            lifetimes: vec![],
            decl: decl,
        }));

        Ok(P(ast::Ty {
            id: ast::DUMMY_NODE_ID,
            node: fnty,
            span: ctx.span(),
        }))
    }
}

impl CodeGenerator for Function {
    type Extra = Item;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        debug!("<Function as CodeGenerator>::codegen: item = {:?}", item);
        debug_assert!(item.is_enabled_for_codegen(ctx));

        // Similar to static member variables in a class template, we can't
        // generate bindings to template functions, because the set of
        // instantiations is open ended and we have no way of knowing which
        // monomorphizations actually exist.
        let type_params = item.all_template_params(ctx);
        if let Some(params) = type_params {
            if !params.is_empty() {
                return;
            }
        }

        let name = self.name();
        let mut canonical_name = item.canonical_name(ctx);
        let mangled_name = self.mangled_name();

        {
            let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);

            // TODO: Maybe warn here if there's a type/argument mismatch, or
            // something?
            if result.seen_function(seen_symbol_name) {
                return;
            }
            result.saw_function(seen_symbol_name);
        }

        let signature_item = ctx.resolve_item(self.signature());
        let signature = signature_item.kind().expect_type().canonical_type(ctx);
        let signature = match *signature.kind() {
            TypeKind::Function(ref sig) => sig,
            _ => panic!("Signature kind is not a Function: {:?}", signature),
        };

        let fndecl = utils::rust_fndecl_from_signature(ctx, signature_item);

        let mut attributes = vec![];

        if let Some(comment) = item.comment(ctx) {
            attributes.push(attributes::doc(comment));
        }

        if let Some(mangled) = mangled_name {
            attributes.push(attributes::link_name(mangled));
        } else if name != canonical_name {
            attributes.push(attributes::link_name(name));
        }

        let foreign_item_kind =
            ast::ForeignItemKind::Fn(fndecl, ast::Generics::default());

        // Handle overloaded functions by giving each overload its own unique
        // suffix.
        let times_seen = result.overload_number(&canonical_name);
        if times_seen > 0 {
            write!(&mut canonical_name, "{}", times_seen).unwrap();
        }

        let foreign_item = ast::ForeignItem {
            ident: ctx.rust_ident_raw(&canonical_name),
            attrs: attributes,
            node: foreign_item_kind,
            id: ast::DUMMY_NODE_ID,
            span: ctx.span(),
            vis: ast::Visibility::Public,
        };

        let abi = match signature.abi() {
            Abi::Known(abi) => abi,
            Abi::Unknown(unknown_abi) => {
                panic!(
                    "Invalid or unknown abi {:?} for function {:?} ({:?})",
                    unknown_abi,
                    canonical_name,
                    self
                );
            }
        };

        let item = ForeignModBuilder::new(abi)
            .with_foreign_item(foreign_item)
            .build(ctx);

        result.push(item);
    }
}


fn objc_method_codegen(
    ctx: &BindgenContext,
    method: &ObjCMethod,
    class_name: Option<&str>,
    prefix: &str,
) -> (ast::ImplItem, ast::TraitItem) {
    let signature = method.signature();
    let fn_args = utils::fnsig_arguments(ctx, signature);
    let fn_ret = utils::fnsig_return_ty(ctx, signature);

    let sig = if method.is_class_method() {
        aster::AstBuilder::new()
            .method_sig()
            .unsafe_()
            .fn_decl()
            .with_args(fn_args.clone())
            .build(fn_ret)
    } else {
        aster::AstBuilder::new()
            .method_sig()
            .unsafe_()
            .fn_decl()
            .self_()
            .build(ast::SelfKind::Value(ast::Mutability::Immutable))
            .with_args(fn_args.clone())
            .build(fn_ret)
    };

    // Collect the actual used argument names
    let arg_names: Vec<_> = fn_args
        .iter()
        .map(|ref arg| match arg.pat.node {
            ast::PatKind::Ident(_, ref spanning, _) => {
                spanning.node.name.as_str().to_string()
            }
            _ => {
                panic!("odd argument!");
            }
        })
        .collect();

    let methods_and_args =
        ctx.rust_ident(&method.format_method_call(&arg_names));

    let body = if method.is_class_method() {
        let class_name = class_name
            .expect("Generating a class method without class name?")
            .to_owned();
        let expect_msg = format!("Couldn't find {}", class_name);
        quote_stmt!(ctx.ext_cx(),
                    msg_send![objc::runtime::Class::get($class_name).expect($expect_msg), $methods_and_args])
            .unwrap()
    } else {
        quote_stmt!(ctx.ext_cx(), msg_send![self, $methods_and_args]).unwrap()
    };
    let block = ast::Block {
        stmts: vec![body],
        id: ast::DUMMY_NODE_ID,
        rules: ast::BlockCheckMode::Default,
        span: ctx.span(),
    };

    let attrs = vec![];

    let method_name = format!("{}{}", prefix, method.rust_name());

    let impl_item = ast::ImplItem {
        id: ast::DUMMY_NODE_ID,
        ident: ctx.rust_ident(&method_name),
        vis: ast::Visibility::Inherited, // Public,
        attrs: attrs.clone(),
        node: ast::ImplItemKind::Method(sig.clone(), P(block)),
        defaultness: ast::Defaultness::Final,
        span: ctx.span(),
    };

    let trait_item = ast::TraitItem {
        id: ast::DUMMY_NODE_ID,
        ident: ctx.rust_ident(&method_name),
        attrs: attrs,
        node: ast::TraitItemKind::Method(sig, None),
        span: ctx.span(),
    };

    (impl_item, trait_item)
}

impl CodeGenerator for ObjCInterface {
    type Extra = Item;

    fn codegen<'a>(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'a>,
        item: &Item,
    ) {
        debug_assert!(item.is_enabled_for_codegen(ctx));

        let mut impl_items = vec![];
        let mut trait_items = vec![];

        for method in self.methods() {
            let (impl_item, trait_item) =
                objc_method_codegen(ctx, method, None, "");
            impl_items.push(impl_item);
            trait_items.push(trait_item)
        }

        let instance_method_names: Vec<_> = self.methods()
            .iter()
            .map({
                |m| m.rust_name()
            })
            .collect();

        for class_method in self.class_methods() {

            let ambiquity =
                instance_method_names.contains(&class_method.rust_name());
            let prefix = if ambiquity { "class_" } else { "" };
            let (impl_item, trait_item) = objc_method_codegen(
                ctx,
                class_method,
                Some(self.name()),
                prefix,
            );
            impl_items.push(impl_item);
            trait_items.push(trait_item)
        }

        let trait_name = self.rust_name();

        let trait_block = aster::AstBuilder::new()
            .item()
            .pub_()
            .trait_(&trait_name)
            .with_items(trait_items)
            .build();

        let ty_for_impl = quote_ty!(ctx.ext_cx(), id);
        let impl_block = aster::AstBuilder::new()
            .item()
            .impl_()
            .trait_()
            .id(&trait_name)
            .build()
            .with_items(impl_items)
            .build_ty(ty_for_impl);

        result.push(trait_block);
        result.push(impl_block);
        result.saw_objc();
    }
}

pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
    context.gen(|context| {
        let counter = Cell::new(0);
        let mut result = CodegenResult::new(&counter);

        debug!("codegen: {:?}", context.options());

        let codegen_items = context.codegen_items();
        if context.options().emit_ir {
            for &id in codegen_items {
                let item = context.resolve_item(id);
                println!("ir: {:?} = {:#?}", id, item);
            }
        }

        if let Some(path) = context.options().emit_ir_graphviz.as_ref() {
            match dot::write_dot_file(context, path) {
                Ok(()) => info!("Your dot file was generated successfully into: {}", path),
                Err(e) => error!("{}", e),
            }
        }

        context.resolve_item(context.root_module())
            .codegen(context, &mut result, &());

        result.items
    })
}

mod utils {
    use super::{ToRustTyOrOpaque, TryToRustTy, error};
    use aster;
    use ir::context::{BindgenContext, ItemId};
    use ir::function::FunctionSig;
    use ir::item::{Item, ItemCanonicalPath};
    use ir::ty::TypeKind;
    use std::mem;
    use syntax::ast;
    use syntax::ptr::P;

    pub fn prepend_objc_header(
        ctx: &BindgenContext,
        result: &mut Vec<P<ast::Item>>,
    ) {
        let use_objc = if ctx.options().objc_extern_crate {
            quote_item!(ctx.ext_cx(),
                #[macro_use]
                extern crate objc;
            ).unwrap()
        } else {
            quote_item!(ctx.ext_cx(),
                use objc;
            ).unwrap()
        };


        let id_type = quote_item!(ctx.ext_cx(),
            #[allow(non_camel_case_types)]
            pub type id = *mut objc::runtime::Object;
        ).unwrap();

        let items = vec![use_objc, id_type];
        let old_items = mem::replace(result, items);
        result.extend(old_items.into_iter());
    }

    pub fn prepend_union_types(
        ctx: &BindgenContext,
        result: &mut Vec<P<ast::Item>>,
    ) {
        let prefix = ctx.trait_prefix();

        // TODO(emilio): The fmt::Debug impl could be way nicer with
        // std::intrinsics::type_name, but...
        let union_field_decl = quote_item!(ctx.ext_cx(),
            #[repr(C)]
            pub struct __BindgenUnionField<T>(
                ::$prefix::marker::PhantomData<T>);
        ).unwrap();

        let union_field_impl = quote_item!(&ctx.ext_cx(),
            impl<T> __BindgenUnionField<T> {
                #[inline]
                pub fn new() -> Self {
                    __BindgenUnionField(::$prefix::marker::PhantomData)
                }

                #[inline]
                pub unsafe fn as_ref(&self) -> &T {
                    ::$prefix::mem::transmute(self)
                }

                #[inline]
                pub unsafe fn as_mut(&mut self) -> &mut T {
                    ::$prefix::mem::transmute(self)
                }
            }
        ).unwrap();

        let union_field_default_impl = quote_item!(&ctx.ext_cx(),
            impl<T> ::$prefix::default::Default for __BindgenUnionField<T> {
                #[inline]
                fn default() -> Self {
                    Self::new()
                }
            }
        ).unwrap();

        let union_field_clone_impl = quote_item!(&ctx.ext_cx(),
            impl<T> ::$prefix::clone::Clone for __BindgenUnionField<T> {
                #[inline]
                fn clone(&self) -> Self {
                    Self::new()
                }
            }
        ).unwrap();

        let union_field_copy_impl = quote_item!(&ctx.ext_cx(),
            impl<T> ::$prefix::marker::Copy for __BindgenUnionField<T> {}
        ).unwrap();

        let union_field_debug_impl = quote_item!(ctx.ext_cx(),
            impl<T> ::$prefix::fmt::Debug for __BindgenUnionField<T> {
                fn fmt(&self, fmt: &mut ::$prefix::fmt::Formatter)
                       -> ::$prefix::fmt::Result {
                    fmt.write_str("__BindgenUnionField")
                }
            }
        ).unwrap();

        // The actual memory of the filed will be hashed, so that's why these
        // field doesn't do anything with the hash.
        let union_field_hash_impl = quote_item!(&ctx.ext_cx(),
            impl<T> ::$prefix::hash::Hash for __BindgenUnionField<T> {
                fn hash<H: ::$prefix::hash::Hasher>(&self, _state: &mut H) {
                }
            }
        ).unwrap();

        let union_field_partialeq_impl = quote_item!(&ctx.ext_cx(),
           impl<T> ::$prefix::cmp::PartialEq for __BindgenUnionField<T> {
               fn eq(&self, _other: &__BindgenUnionField<T>) -> bool {
                   true
               }
           }
        ).unwrap();

        let union_field_eq_impl = quote_item!(&ctx.ext_cx(),
           impl<T> ::$prefix::cmp::Eq for __BindgenUnionField<T> {
           }
        )
            .unwrap();

        let items = vec![union_field_decl,
                         union_field_impl,
                         union_field_default_impl,
                         union_field_clone_impl,
                         union_field_copy_impl,
                         union_field_debug_impl,
                         union_field_hash_impl,
                         union_field_partialeq_impl,
                         union_field_eq_impl];

        let old_items = mem::replace(result, items);
        result.extend(old_items.into_iter());
    }

    pub fn prepend_incomplete_array_types(
        ctx: &BindgenContext,
        result: &mut Vec<P<ast::Item>>,
    ) {
        let prefix = ctx.trait_prefix();

        let incomplete_array_decl = quote_item!(ctx.ext_cx(),
            #[repr(C)]
            #[derive(Default)]
            pub struct __IncompleteArrayField<T>(
                ::$prefix::marker::PhantomData<T>);
        ).unwrap();

        let incomplete_array_impl = quote_item!(&ctx.ext_cx(),
            impl<T> __IncompleteArrayField<T> {
                #[inline]
                pub fn new() -> Self {
                    __IncompleteArrayField(::$prefix::marker::PhantomData)
                }

                #[inline]
                pub unsafe fn as_ptr(&self) -> *const T {
                    ::$prefix::mem::transmute(self)
                }

                #[inline]
                pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
                    ::$prefix::mem::transmute(self)
                }

                #[inline]
                pub unsafe fn as_slice(&self, len: usize) -> &[T] {
                    ::$prefix::slice::from_raw_parts(self.as_ptr(), len)
                }

                #[inline]
                pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
                    ::$prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
                }
            }
        ).unwrap();

        let incomplete_array_debug_impl = quote_item!(ctx.ext_cx(),
            impl<T> ::$prefix::fmt::Debug for __IncompleteArrayField<T> {
                fn fmt(&self, fmt: &mut ::$prefix::fmt::Formatter)
                       -> ::$prefix::fmt::Result {
                    fmt.write_str("__IncompleteArrayField")
                }
            }
        ).unwrap();

        let incomplete_array_clone_impl = quote_item!(&ctx.ext_cx(),
            impl<T> ::$prefix::clone::Clone for __IncompleteArrayField<T> {
                #[inline]
                fn clone(&self) -> Self {
                    Self::new()
                }
            }
        ).unwrap();

        let incomplete_array_copy_impl = quote_item!(&ctx.ext_cx(),
            impl<T> ::$prefix::marker::Copy for __IncompleteArrayField<T> {}
        ).unwrap();

        let items = vec![incomplete_array_decl,
                         incomplete_array_impl,
                         incomplete_array_debug_impl,
                         incomplete_array_clone_impl,
                         incomplete_array_copy_impl];

        let old_items = mem::replace(result, items);
        result.extend(old_items.into_iter());
    }

    pub fn prepend_complex_type(
        ctx: &BindgenContext,
        result: &mut Vec<P<ast::Item>>,
    ) {
        let complex_type = quote_item!(ctx.ext_cx(),
            #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
            #[repr(C)]
            pub struct __BindgenComplex<T> {
                pub re: T,
                pub im: T
            }
        ).unwrap();

        let items = vec![complex_type];
        let old_items = mem::replace(result, items);
        result.extend(old_items.into_iter());
    }

    pub fn build_templated_path(
        item: &Item,
        ctx: &BindgenContext,
        template_params: Vec<ItemId>,
    ) -> error::Result<P<ast::Ty>> {
        let path = item.namespace_aware_canonical_path(ctx);
        let builder = aster::AstBuilder::new().ty().path();

        let template_params = template_params
            .iter()
            .map(|param| param.try_to_rust_ty(ctx, &()))
            .collect::<error::Result<Vec<_>>>()?;

        // XXX: I suck at aster.
        if path.len() == 1 {
            return Ok(
                builder
                    .segment(&path[0])
                    .with_tys(template_params)
                    .build()
                    .build(),
            );
        }

        let mut builder = builder.id(&path[0]);
        for (i, segment) in path.iter().skip(1).enumerate() {
            // Take into account the skip(1)
            builder = if i == path.len() - 2 {
                // XXX Extra clone courtesy of the borrow checker.
                builder
                    .segment(&segment)
                    .with_tys(template_params.clone())
                    .build()
            } else {
                builder.segment(&segment).build()
            }
        }

        Ok(builder.build())
    }

    fn primitive_ty(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
        let ident = ctx.rust_ident_raw(&name);
        quote_ty!(ctx.ext_cx(), $ident)
    }

    pub fn type_from_named(
        ctx: &BindgenContext,
        name: &str,
        _inner: ItemId,
    ) -> Option<P<ast::Ty>> {
        // FIXME: We could use the inner item to check this is really a
        // primitive type but, who the heck overrides these anyway?
        Some(match name {
            "int8_t" => primitive_ty(ctx, "i8"),
            "uint8_t" => primitive_ty(ctx, "u8"),
            "int16_t" => primitive_ty(ctx, "i16"),
            "uint16_t" => primitive_ty(ctx, "u16"),
            "int32_t" => primitive_ty(ctx, "i32"),
            "uint32_t" => primitive_ty(ctx, "u32"),
            "int64_t" => primitive_ty(ctx, "i64"),
            "uint64_t" => primitive_ty(ctx, "u64"),

            "uintptr_t" | "size_t" => primitive_ty(ctx, "usize"),

            "intptr_t" | "ptrdiff_t" | "ssize_t" => primitive_ty(ctx, "isize"),
            _ => return None,
        })
    }

    pub fn rust_fndecl_from_signature(
        ctx: &BindgenContext,
        sig: &Item,
    ) -> P<ast::FnDecl> {
        let signature = sig.kind().expect_type().canonical_type(ctx);
        let signature = match *signature.kind() {
            TypeKind::Function(ref sig) => sig,
            _ => panic!("How?"),
        };

        let decl_ty = signature.try_to_rust_ty(ctx, sig).expect(
            "function signature to Rust type conversion is infallible",
        );
        match decl_ty.unwrap().node {
            ast::TyKind::BareFn(bare_fn) => bare_fn.unwrap().decl,
            _ => panic!("How did this happen exactly?"),
        }
    }

    pub fn fnsig_return_ty(
        ctx: &BindgenContext,
        sig: &FunctionSig,
    ) -> ast::FunctionRetTy {
        let return_item = ctx.resolve_item(sig.return_type());
        if let TypeKind::Void = *return_item.kind().expect_type().kind() {
            ast::FunctionRetTy::Default(ctx.span())
        } else {
            ast::FunctionRetTy::Ty(return_item.to_rust_ty_or_opaque(ctx, &()))
        }
    }

    pub fn fnsig_arguments(
        ctx: &BindgenContext,
        sig: &FunctionSig,
    ) -> Vec<ast::Arg> {
        use super::ToPtr;
        let mut unnamed_arguments = 0;
        sig.argument_types().iter().map(|&(ref name, ty)| {
            let arg_item = ctx.resolve_item(ty);
            let arg_ty = arg_item.kind().expect_type();

            // From the C90 standard[1]:
            //
            //     A declaration of a parameter as "array of type" shall be
            //     adjusted to "qualified pointer to type", where the type
            //     qualifiers (if any) are those specified within the [ and ] of
            //     the array type derivation.
            //
            // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html
            let arg_ty = match *arg_ty.canonical_type(ctx).kind() {
                TypeKind::Array(t, _) => {
                    t.to_rust_ty_or_opaque(ctx, &())
                        .to_ptr(ctx.resolve_type(t).is_const(), ctx.span())
                },
                TypeKind::Pointer(inner) => {
                    let inner = ctx.resolve_item(inner);
                    let inner_ty = inner.expect_type();
                    if let TypeKind::ObjCInterface(_) = *inner_ty.canonical_type(ctx).kind() {
                        quote_ty!(ctx.ext_cx(), id)
                    } else {
                        arg_item.to_rust_ty_or_opaque(ctx, &())
                    }
                },
                _ => {
                    arg_item.to_rust_ty_or_opaque(ctx, &())
                }
            };

            let arg_name = match *name {
                Some(ref name) => ctx.rust_mangle(name).into_owned(),
                None => {
                    unnamed_arguments += 1;
                    format!("arg{}", unnamed_arguments)
                }
            };

            assert!(!arg_name.is_empty());

            ast::Arg {
                ty: arg_ty,
                pat: aster::AstBuilder::new().pat().id(arg_name),
                id: ast::DUMMY_NODE_ID,
            }
        }).collect::<Vec<_>>()
    }
}