//! Take in our IR and output a C/C++ file with dummy uses of each IR type. //! //! Say that we had this C++ header, `header.hpp`: //! //! ```c++ //! class Point { //! int x; //! int y; //! } //! //! enum Bar { //! THIS, //! THAT, //! OTHER //! } //! ``` //! //! If we generated dummy uses for this header, we would get a `.cpp` file like //! this: //! //! ```c++ //! #include "header.hpp" //! //! void dummy(Point*) {} //! void dummy(Bar*) {} //! ``` //! //! This is useful because we can compile this `.cpp` file into an object file, //! and then compare its debugging information to the debugging information //! generated for our Rust bindings. These two sets of debugging information had //! better agree on the C/C++ types' physical layout, or else our bindings are //! incorrect! //! //! "But you still haven't explained why we have to generate the dummy uses" you //! complain. Well if the types are never used, then they are elided when the //! C/C++ compiler generates debugging information. use ir::context::BindgenContext; use ir::item::{Item, ItemAncestors, ItemCanonicalName}; use std::io; // Like `canonical_path`, except we always take namespaces into account, ignore // the generated names of anonymous items, and return a `String`. // // TODO: Would it be easier to try and demangle the USR? fn namespaced_name(ctx: &BindgenContext, item: &Item) -> String { let mut names: Vec<_> = item.ancestors(ctx) .map(|id| ctx.resolve_item(id).canonical_name(ctx)) .filter(|name| !name.starts_with("_bindgen_")) .collect(); names.reverse(); names.join("::") } /// Generate the dummy uses for all the items in the given context, and write /// the dummy uses to `dest`. pub fn generate_dummy_uses(ctx: &mut BindgenContext, mut dest: W) -> io::Result<()> where W: io::Write, { ctx.gen(|ctx| { let input_header = ctx.options() .input_header .as_ref() .expect("Should not generate dummy uses without an input header"); try!(writeln!(dest, "/* automatically generated by rust-bindgen */")); try!(writeln!(dest, "")); try!(writeln!(dest, "#include \"{}\"", input_header)); try!(writeln!(dest, "")); let type_items = ctx.whitelisted_items() .map(|id| ctx.resolve_item(id)) .filter(|item| { // We only want type items. if let Some(ty) = item.kind().as_type() { // However, we don't want anonymous types, as we can't // generate dummy uses for them. ty.name().is_some() && // Nor do we want builtin types or named template type // arguments. Again, we can't generate dummy uses for // these. !ty.is_builtin_or_named() && // And finally, we won't be creating any dummy // specializations, so ignore template declarations and // partial specializations. item.applicable_template_args(ctx).is_empty() } else { false } }) .map(|item| namespaced_name(ctx, item)) .enumerate(); for (idx, name) in type_items { try!(writeln!(dest, "void dummy{}({}*) {{ }}", idx, name)); } Ok(()) }) }