diff options
37 files changed, 876 insertions, 221 deletions
diff --git a/.travis.yml b/.travis.yml index ee3f970b..d8bc595d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,29 +10,33 @@ env: global: - CARGO_TARGET_DIR=/tmp/bindgen matrix: - - LLVM_VERSION="3.8.1" BINDGEN_JOB="test" BINDGEN_PROFILE= - - LLVM_VERSION="3.8.1" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" - - LLVM_VERSION="3.8.1" BINDGEN_JOB="integration" BINDGEN_PROFILE= - - LLVM_VERSION="3.8.1" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" - - LLVM_VERSION="3.9.0" BINDGEN_JOB="test" BINDGEN_PROFILE= - - LLVM_VERSION="3.9.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" - - LLVM_VERSION="3.9.0" BINDGEN_JOB="integration" BINDGEN_PROFILE= - - LLVM_VERSION="3.9.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" - - LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE= - - LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" - - LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE= BINDGEN_FEATURES="testing_only_extra_assertions" - - LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" BINDGEN_FEATURES="testing_only_extra_assertions" - - LLVM_VERSION="4.0.0" BINDGEN_JOB="integration" BINDGEN_PROFILE= - - LLVM_VERSION="4.0.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" - - LLVM_VERSION="4.0.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE= - - LLVM_VERSION="4.0.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release" - - LLVM_VERSION="4.0.0" BINDGEN_JOB="misc" - - LLVM_VERSION="4.0.0" BINDGEN_JOB="quickchecking" + - LLVM_VERSION="3.8" BINDGEN_JOB="test" BINDGEN_PROFILE= + - LLVM_VERSION="3.8" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" + - LLVM_VERSION="3.8" BINDGEN_JOB="integration" BINDGEN_PROFILE= + - LLVM_VERSION="3.8" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" + - LLVM_VERSION="3.9" BINDGEN_JOB="test" BINDGEN_PROFILE= + - LLVM_VERSION="3.9" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" + - LLVM_VERSION="3.9" BINDGEN_JOB="integration" BINDGEN_PROFILE= + - LLVM_VERSION="3.9" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" + - LLVM_VERSION="4.0" BINDGEN_JOB="test" BINDGEN_PROFILE= + - LLVM_VERSION="4.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" + - LLVM_VERSION="4.0" BINDGEN_JOB="integration" BINDGEN_PROFILE= + - LLVM_VERSION="4.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" + - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE= + - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" + - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE= BINDGEN_FEATURES="testing_only_extra_assertions" + - LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" BINDGEN_FEATURES="testing_only_extra_assertions" + - LLVM_VERSION="5.0" BINDGEN_JOB="integration" BINDGEN_PROFILE= + - LLVM_VERSION="5.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release" + - LLVM_VERSION="5.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE= + - LLVM_VERSION="5.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release" + - LLVM_VERSION="5.0" BINDGEN_JOB="misc" + - LLVM_VERSION="5.0" BINDGEN_JOB="quickchecking" matrix: fast_finish: true allow_failures: - - env: LLVM_VERSION=4.0.0 BINDGEN_JOB=rustfmt + - env: LLVM_VERSION=5.0 BINDGEN_JOB=rustfmt cache: directories: @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.35.0" +version = "0.36.0" dependencies = [ "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -13,10 +13,13 @@ name = "bindgen" readme = "README.md" repository = "https://github.com/rust-lang-nursery/rust-bindgen" documentation = "https://docs.rs/bindgen" -version = "0.35.0" +homepage = "https://rust-lang-nursery.github.io/rust-bindgen/" +version = "0.36.0" build = "build.rs" include = [ + "LICENSE", + "README.md", "Cargo.toml", "build.rs", "src/*.rs", @@ -44,7 +47,7 @@ cexpr = "0.2" cfg-if = "0.1.0" # This kinda sucks: https://github.com/rust-lang/cargo/issues/1982 clap = "2" -clang-sys = { version = "0.22.0", features = ["runtime", "clang_3_9"] } +clang-sys = { version = "0.22.0", features = ["runtime", "clang_6_0"] } lazy_static = "1" peeking_take_while = "0.1.2" quote = "0.3.15" @@ -68,6 +71,7 @@ static = [] # on bindgen! testing_only_docs = [] testing_only_extra_assertions = [] +testing_only_libclang_5 = [] testing_only_libclang_4 = [] testing_only_libclang_3_9 = [] testing_only_libclang_3_8 = [] @@ -2,7 +2,7 @@ [`impl period`](https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html) has been started! Join us at [Gitter.im](https://gitter.im/rust-impl-period/WG-dev-tools-bindgen). -**`bindgen` automatically generates Rust FFI bindings to C and C++ libraries.** +**`bindgen` automatically generates Rust FFI bindings to C (and some C++) libraries.** For example, given the C header `doggo.h`: diff --git a/appveyor.yml b/appveyor.yml index 5006b0c4..91009f68 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,11 +9,17 @@ environment: LLVM_VERSION: 4.0.0-1 BINDGEN_FEATURES: testing_only_libclang_4 - TARGET: msvc + LLVM_VERSION: 5.0.0-1 + BINDGEN_FEATURES: testing_only_libclang_5 + - TARGET: msvc LLVM_VERSION: 3.9.0 BINDGEN_FEATURES: testing_only_libclang_3_9 - TARGET: msvc LLVM_VERSION: 4.0.0 BINDGEN_FEATURES: testing_only_libclang_4 + - TARGET: msvc + LLVM_VERSION: 5.0.0 + BINDGEN_FEATURES: testing_only_libclang_5 configuration: - stable diff --git a/bindgen-integration/Cargo.toml b/bindgen-integration/Cargo.toml index 304d1b0d..126cb363 100644 --- a/bindgen-integration/Cargo.toml +++ b/bindgen-integration/Cargo.toml @@ -11,6 +11,7 @@ bindgen = { path = ".." } gcc = "0.3" [features] +testing_only_libclang_5 = ["bindgen/testing_only_libclang_5"] testing_only_libclang_4 = ["bindgen/testing_only_libclang_4"] testing_only_libclang_3_9 = ["bindgen/testing_only_libclang_3_9"] testing_only_libclang_3_8 = ["bindgen/testing_only_libclang_3_8"] diff --git a/ci/before_install.sh b/ci/before_install.sh index 0a2535ea..fcc00ea2 100644 --- a/ci/before_install.sh +++ b/ci/before_install.sh @@ -6,31 +6,55 @@ if [ "${TRAVIS_OS_NAME}" == "osx" ]; then rvm get head || true fi -function llvm_download_if_needed() { - export LLVM_VERSION_TRIPLE="${LLVM_VERSION}" - export LLVM=clang+llvm-${LLVM_VERSION_TRIPLE}-x86_64-$1 - - local llvm_build_dir="$HOME/.llvm-builds/${LLVM}" - - if [ -d "${llvm_build_dir}" ]; then - echo "Using cached LLVM build for ${LLVM} in ${llvm_build_dir}"; +function llvm_linux_target_triple() { + if [ "$1" == "5.0" ]; then + echo "linux-x86_64-ubuntu14.04" else - wget http://llvm.org/releases/${LLVM_VERSION_TRIPLE}/${LLVM}.tar.xz - mkdir -p "${llvm_build_dir}" - tar -xf ${LLVM}.tar.xz -C "${llvm_build_dir}" --strip-components=1 + echo "x86_64-linux-gnu-ubuntu-14.04" fi +} - export LLVM_CONFIG_PATH="${llvm_build_dir}/bin/llvm-config" - if [ "${TRAVIS_OS_NAME}" == "osx" ]; then - cp "${llvm_build_dir}/lib/libclang.dylib" /usr/local/lib/libclang.dylib +function llvm_version_triple() { + if [ "$1" == "3.5" ]; then + echo "3.5.2" + elif [ "$1" == "3.6" ]; then + echo "3.6.2" + elif [ "$1" == "3.7" ]; then + echo "3.7.1" + elif [ "$1" == "3.8" ]; then + echo "3.8.1" + elif [ "$1" == "3.9" ]; then + echo "3.9.0" + elif [ "$1" == "4.0" ]; then + echo "4.0.0" + elif [ "$1" == "5.0" ]; then + echo "5.0.0" fi } +function llvm_download() { + export LLVM_VERSION_TRIPLE=`llvm_version_triple ${LLVM_VERSION}` + export LLVM=clang+llvm-${LLVM_VERSION_TRIPLE}-$1 + export LLVM_DIRECTORY="$HOME/.llvm/${LLVM}" + + if [ -d "${LLVM_DIRECTORY}" ]; then + echo "Using cached LLVM download for ${LLVM}..." + else + wget http://releases.llvm.org/${LLVM_VERSION_TRIPLE}/${LLVM}.tar.xz + mkdir -p "${LLVM_DIRECTORY}" + tar xf ${LLVM}.tar.xz -C "${LLVM_DIRECTORY}" --strip-components=1 + fi + + export LLVM_CONFIG_PATH="${LLVM_DIRECTORY}/bin/llvm-config" +} if [ "${TRAVIS_OS_NAME}" == "linux" ]; then - llvm_download_if_needed linux-gnu-ubuntu-14.04 + llvm_download `llvm_linux_target_triple ${LLVM_VERSION}` + export LD_LIBRARY_PATH="${LLVM_DIRECTORY}/lib":$LD_LIBRARY_PATH else - llvm_download_if_needed apple-darwin + llvm_download x86_64-apple-darwin + cp "${LLVM_DIRECTORY}/lib/libclang.dylib" /usr/local/lib/libclang.dylib + export DYLD_LIBRARY_PATH="${LLVM_DIRECTORY}/lib":$DYLD_LIBRARY_PATH fi popd diff --git a/src/clang.rs b/src/clang.rs index cb873994..04d5c9d3 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -1812,3 +1812,35 @@ impl Drop for EvalResult { unsafe { clang_EvalResult_dispose(self.x) }; } } + +/// Target information obtained from libclang. +#[derive(Debug)] +pub struct TargetInfo { + /// The target triple. + pub triple: String, + /// The width of the pointer _in bits_. + pub pointer_width: usize, +} + +impl TargetInfo { + /// Tries to obtain target information from libclang. + pub fn new(tu: &TranslationUnit) -> Option<Self> { + if !clang_getTranslationUnitTargetInfo::is_loaded() { + return None; + } + let triple; + let pointer_width; + unsafe { + let ti = clang_getTranslationUnitTargetInfo(tu.x); + triple = cxstring_into_string(clang_TargetInfo_getTriple(ti)); + pointer_width = clang_TargetInfo_getPointerWidth(ti); + clang_TargetInfo_dispose(ti); + } + assert!(pointer_width > 0); + assert_eq!(pointer_width % 8, 0); + Some(TargetInfo { + triple, + pointer_width: pointer_width as usize, + }) + } +} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index f84fb701..b30da19b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -45,7 +45,6 @@ use std::collections::{HashSet, VecDeque}; use std::collections::hash_map::{Entry, HashMap}; use std::fmt::Write; use std::iter; -use std::mem; use std::ops; // Name of type defined in constified enum module @@ -1777,8 +1776,9 @@ impl CodeGenerator for CompInfo { 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 + if align > ctx.target_pointer_size() && + !ctx.options().rust_features().repr_align + { None } else { Some(quote! { @@ -2732,9 +2732,8 @@ trait TryToOpaque { /// 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), - ) + self.try_get_layout(ctx, extra) + .unwrap_or_else(|_| Layout::for_size(ctx, 1)) } fn to_opaque( diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index a538c35f..3a641f4a 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -8,7 +8,6 @@ use ir::layout::Layout; use ir::ty::{Type, TypeKind}; use quote; use std::cmp; -use std::mem; /// Trace the layout of struct. #[derive(Debug)] @@ -101,7 +100,7 @@ impl<'a> StructLayoutTracker<'a> { pub fn saw_vtable(&mut self) { debug!("saw vtable for {}", self.name); - let ptr_size = mem::size_of::<*mut ()>(); + let ptr_size = self.ctx.target_pointer_size(); self.latest_offset += ptr_size; self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size)); self.max_field_align = ptr_size; @@ -165,15 +164,13 @@ impl<'a> StructLayoutTracker<'a> { // can support. // // This means that the structs in the array are super-unsafe to - // access, since they won't be properly aligned, but *shrug*. - if let Some(layout) = self.ctx.resolve_type(inner).layout( - self.ctx, - ) - { - if layout.align > mem::size_of::<*mut ()>() { - field_layout.size = align_to(layout.size, layout.align) * - len; - field_layout.align = mem::size_of::<*mut ()>(); + // access, since they won't be properly aligned, but there's not too + // much we can do about it. + if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) { + if layout.align > self.ctx.target_pointer_size() { + field_layout.size = + align_to(layout.size, layout.align) * len; + field_layout.align = self.ctx.target_pointer_size(); } } } @@ -193,7 +190,7 @@ impl<'a> StructLayoutTracker<'a> { // Otherwise the padding is useless. let need_padding = padding_bytes >= field_layout.align || - field_layout.align > mem::size_of::<*mut ()>(); + field_layout.align > self.ctx.target_pointer_size(); self.latest_offset += padding_bytes; @@ -215,7 +212,7 @@ impl<'a> StructLayoutTracker<'a> { if need_padding && padding_bytes != 0 { Some(Layout::new( padding_bytes, - cmp::min(field_layout.align, mem::size_of::<*mut ()>()), + cmp::min(field_layout.align, self.ctx.target_pointer_size()) )) } else { None @@ -267,15 +264,15 @@ impl<'a> StructLayoutTracker<'a> { (self.last_field_was_bitfield && padding_bytes >= self.latest_field_layout.unwrap().align) || - layout.align > mem::size_of::<*mut ()>()) + layout.align > self.ctx.target_pointer_size()) { let layout = if self.is_packed { Layout::new(padding_bytes, 1) } else if self.last_field_was_bitfield || - layout.align > mem::size_of::<*mut ()>() + layout.align > self.ctx.target_pointer_size() { // We've already given up on alignment here. - Layout::for_size(padding_bytes) + Layout::for_size(self.ctx, padding_bytes) } else { Layout::new(padding_bytes, layout.align) }; @@ -289,8 +286,18 @@ impl<'a> StructLayoutTracker<'a> { } pub fn requires_explicit_align(&self, layout: Layout) -> bool { - self.max_field_align < layout.align && - layout.align <= mem::size_of::<*mut ()>() + if self.max_field_align >= layout.align { + return false; + } + // At this point we require explicit alignment, but we may not be able + // to generate the right bits, let's double check. + if self.ctx.options().rust_features().repr_align { + return true; + } + + // We can only generate up-to a word of alignment unless we support + // repr(align). + layout.align <= self.ctx.target_pointer_size() } fn padding_bytes(&self, layout: Layout) -> usize { diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 131851fd..8c2be498 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1290,9 +1290,10 @@ impl CompInfo { return CXChildVisit_Continue; } + // Even if this is a definition, we may not be the semantic + // parent, see #1281. let inner = Item::parse(cur, Some(potential_id), ctx) .expect("Inner ClassDecl"); - assert_eq!(ctx.resolve_item(inner).parent_id(), potential_id); let inner = inner.expect_type_id(ctx); diff --git a/src/ir/context.rs b/src/ir/context.rs index b453378d..8bcfdeda 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -366,6 +366,9 @@ pub struct BindgenContext { /// The translation unit for parsing. translation_unit: clang::TranslationUnit, + /// Target information that can be useful for some stuff. + target_info: Option<clang::TargetInfo>, + /// The options given by the user via cli or other medium. options: BindgenOptions, @@ -503,6 +506,9 @@ impl<'ctx> WhitelistedItemsTraversal<'ctx> { } } +const HOST_TARGET: &'static str = + include_str!(concat!(env!("OUT_DIR"), "/host-target.txt")); + /// Returns the effective target, and whether it was explicitly specified on the /// clang flags. fn find_effective_target(clang_args: &[String]) -> (String, bool) { @@ -521,8 +527,6 @@ fn find_effective_target(clang_args: &[String]) -> (String, bool) { return (t, false) } - const HOST_TARGET: &'static str = - include_str!(concat!(env!("OUT_DIR"), "/host-target.txt")); (HOST_TARGET.to_owned(), false) } @@ -561,6 +565,17 @@ impl BindgenContext { ).expect("TranslationUnit::parse failed") }; + let target_info = clang::TargetInfo::new(&translation_unit); + + #[cfg(debug_assertions)] + { + if let Some(ref ti) = target_info { + if effective_target == HOST_TARGET { + assert_eq!(ti.pointer_width / 8, mem::size_of::<*mut ()>()); + } + } + } + let root_module = Self::build_root_module(ItemId(0)); let root_module_id = root_module.id().as_module_id_unchecked(); @@ -578,9 +593,10 @@ impl BindgenContext { replacements: Default::default(), collected_typerefs: false, in_codegen: false, - index: index, - translation_unit: translation_unit, - options: options, + index, + translation_unit, + target_info, + options, generated_bindegen_complex: Cell::new(false), whitelisted: None, codegen_items: None, @@ -611,6 +627,15 @@ impl BindgenContext { Timer::new(name).with_output(self.options.time_phases) } + /// Returns the pointer width to use for the target for the current + /// translation. + pub fn target_pointer_size(&self) -> usize { + if let Some(ref ti) = self.target_info { + return ti.pointer_width / 8; + } + mem::size_of::<*mut ()>() + } + /// Get the stack of partially parsed types that we are in the middle of /// parsing. pub fn currently_parsed_types(&self) -> &[PartialType] { @@ -2291,7 +2316,11 @@ impl BindgenContext { if self.options().whitelist_recursively { traversal::all_edges } else { - traversal::no_edges + // Only follow InnerType edges from the whitelisted roots. + // Such inner types (e.g. anonymous structs/unions) are + // always emitted by codegen, and they need to be whitelisted + // to make sure they are processed by e.g. the derive analysis. + traversal::only_inner_type_edges }; let whitelisted = WhitelistedItemsTraversal::new( diff --git a/src/ir/layout.rs b/src/ir/layout.rs index 0c99c7e7..bc3f8a5a 100644 --- a/src/ir/layout.rs +++ b/src/ir/layout.rs @@ -4,8 +4,9 @@ use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug, CanTriviallyDeriveDefault, CanTriviallyDeriveHash, CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind}; +use ir::context::BindgenContext; use clang; -use std::{cmp, mem}; +use std::cmp; /// A type that represents the struct layout of a type. #[derive(Debug, Clone, Copy, PartialEq)] @@ -20,10 +21,15 @@ pub struct Layout { #[test] fn test_layout_for_size() { + use std::mem; + let ptr_size = mem::size_of::<*mut ()>(); - assert_eq!(Layout::for_size(ptr_size), Layout::new(ptr_size, ptr_size)); assert_eq!( - Layout::for_size(3 * ptr_size), + Layout::for_size_internal(ptr_size, ptr_size), + Layout::new(ptr_size, ptr_size) + ); + assert_eq!( + Layout::for_size_internal(ptr_size, 3 * ptr_size), Layout::new(3 * ptr_size, ptr_size) ); } @@ -39,13 +45,9 @@ impl Layout { } } - /// Creates a non-packed layout for a given size, trying to use the maximum - /// alignment possible. - pub fn for_size(size: usize) -> Self { + fn for_size_internal(ptr_size: usize, size: usize) -> Self { let mut next_align = 2; - while size % next_align == 0 && - next_align <= mem::size_of::<*mut ()>() - { + while size % next_align == 0 && next_align <= ptr_size { next_align *= 2; } Layout { @@ -55,6 +57,12 @@ impl Layout { } } + /// Creates a non-packed layout for a given size, trying to use the maximum + /// alignment possible. + pub fn for_size(ctx: &BindgenContext, size: usize) -> Self { + Self::for_size_internal(ctx.target_pointer_size(), size) + } + /// Is this a zero-sized layout? pub fn is_zero(&self) -> bool { self.size == 0 && self.align == 0 diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs index 491a15f8..c37b0b5f 100644 --- a/src/ir/traversal.rs +++ b/src/ir/traversal.rs @@ -201,11 +201,13 @@ pub fn all_edges(_: &BindgenContext, _: Edge) -> bool { true } -/// A `TraversalPredicate` implementation that never follows any edges, and -/// therefore traversals using this predicate will only visit the traversal's -/// roots. -pub fn no_edges(_: &BindgenContext, _: Edge) -> bool { - false +/// A `TraversalPredicate` implementation that only follows +/// `EdgeKind::InnerType` edges, and therefore traversals using this predicate +/// will only visit the traversal's roots and their inner types. This is used +/// in no-recursive-whitelist mode, where inner types such as anonymous +/// structs/unions still need to be processed. +pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool { + edge.kind == EdgeKind::InnerType } /// A `TraversalPredicate` implementation that only follows edges to items that diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 2fab41be..b42f4424 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -16,7 +16,6 @@ use clang::{self, Cursor}; use parse::{ClangItemParser, ParseError, ParseResult}; use std::borrow::Cow; use std::io; -use std::mem; /// The base representation of a type in bindgen. /// @@ -232,8 +231,6 @@ impl Type { /// What is the layout of this type? pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> { - use std::mem; - self.layout.or_else(|| { match self.kind { TypeKind::Comp(ref ci) => ci.layout(ctx), @@ -242,8 +239,8 @@ impl Type { TypeKind::Pointer(..) | TypeKind::BlockPointer => { Some(Layout::new( - mem::size_of::<*mut ()>(), - mem::align_of::<*mut ()>(), + ctx.target_pointer_size(), + ctx.target_pointer_size(), )) } TypeKind::ResolvedTypeRef(inner) => { @@ -596,17 +593,6 @@ pub enum FloatKind { Float128, } -impl FloatKind { - /// If this type has a known size, return it (in bytes). - pub fn known_size(&self) -> usize { - match *self { - FloatKind::Float => mem::size_of::<f32>(), - FloatKind::Double | FloatKind::LongDouble => mem::size_of::<f64>(), - FloatKind::Float128 => mem::size_of::<f64>() * 2, - } - } -} - /// The different kinds of types that we can parse. #[derive(Debug)] pub enum TypeKind { @@ -4,6 +4,9 @@ //! functions and use types defined in the header. //! //! See the [`Builder`](./struct.Builder.html) struct for usage. +//! +//! See the [Users Guide](https://rust-lang-nursery.github.io/rust-bindgen/) for +//! additional documentation. #![deny(missing_docs)] #![deny(warnings)] #![deny(unused_extern_crates)] @@ -343,19 +346,6 @@ impl Builder { output_vector.push("--disable-name-namespacing".into()); } - self.options - .links - .iter() - .map(|&(ref item, _)| { - output_vector.push("--framework".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - if !self.options.codegen_config.functions { output_vector.push("--ignore-functions".into()); } @@ -389,19 +379,6 @@ impl Builder { output_vector.push("--ignore-methods".into()); } - self.options - .links - .iter() - .map(|&(ref item, _)| { - output_vector.push("--clang-args".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - if !self.options.convert_floats { output_vector.push("--no-convert-floats".into()); } @@ -437,19 +414,6 @@ impl Builder { }) .count(); - self.options - .links - .iter() - .map(|&(ref item, _)| { - output_vector.push("--static".into()); - output_vector.push( - item.trim_left_matches("^") - .trim_right_matches("$") - .into(), - ); - }) - .count(); - if self.options.use_core { output_vector.push("--use-core".into()); } @@ -824,26 +788,6 @@ impl Builder { self } - /// Make the generated bindings link the given shared library. - pub fn link<T: Into<String>>(mut self, library: T) -> Builder { - self.options.links.push((library.into(), LinkType::Default)); - self - } - - /// Make the generated bindings link the given static library. - pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder { - self.options.links.push((library.into(), LinkType::Static)); - self - } - - /// Make the generated bindings link the given framework. - pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder { - self.options.links.push( - (library.into(), LinkType::Framework), - ); - self - } - /// Emit bindings for builtin definitions (for example `__builtin_va_list`) /// in the generated Rust. pub fn emit_builtins(mut self) -> Builder { @@ -1277,9 +1221,6 @@ struct BindgenOptions { /// Whether we should generate builtins or not. builtins: bool, - /// The set of libraries we should link in the generated Rust code. - links: Vec<(String, LinkType)>, - /// True if we should dump the Clang AST for debugging purposes. emit_ast: bool, @@ -1484,7 +1425,6 @@ impl Default for BindgenOptions { rustified_enums: Default::default(), constified_enum_modules: Default::default(), builtins: false, - links: vec![], emit_ast: false, emit_ir: false, emit_ir_graphviz: None, @@ -1529,19 +1469,6 @@ impl Default for BindgenOptions { } } -/// The linking type to use with a given library. -/// -/// TODO: #104: This is ignored at the moment, but shouldn't be. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum LinkType { - /// Use shared library linking. This is the default. - Default, - /// Use static linking. - Static, - /// The library is an OSX framework. - Framework, -} - fn ensure_libclang_is_loaded() { if clang_sys::is_loaded() { return; diff --git a/src/options.rs b/src/options.rs index dbd7c17e..b3ddbbfd 100644 --- a/src/options.rs +++ b/src/options.rs @@ -149,12 +149,6 @@ where .help("Disable namespacing via mangling, causing bindgen to \ generate names like \"Baz\" instead of \"foo_bar_Baz\" \ for an input name \"foo::bar::Baz\"."), - Arg::with_name("framework") - .long("framework-link") - .help("Link to framework.") - .takes_value(true) - .multiple(true) - .number_of_values(1), Arg::with_name("ignore-functions") .long("ignore-functions") .help("Do not generate bindings for functions or methods. This \ @@ -168,13 +162,6 @@ where Arg::with_name("ignore-methods") .long("ignore-methods") .help("Do not generate bindings for methods."), - Arg::with_name("dynamic") - .short("l") - .long("link") - .help("Link to dynamic library.") - .takes_value(true) - .multiple(true) - .number_of_values(1), Arg::with_name("no-convert-floats") .long("no-convert-floats") .help("Do not automatically convert floats to f32/f64."), @@ -207,12 +194,6 @@ where .long("rust-target") .help(&rust_target_help) .takes_value(true), - Arg::with_name("static") - .long("static-link") - .help("Link to static library.") - .takes_value(true) - .multiple(true) - .number_of_values(1), Arg::with_name("use-core") .long("use-core") .help("Use types from Rust core instead of std."), @@ -409,12 +390,6 @@ where builder = builder.ctypes_prefix(prefix); } - if let Some(links) = matches.values_of("dynamic") { - for library in links { - builder = builder.link(library); - } - } - if let Some(what_to_generate) = matches.value_of("generate") { let mut config = CodegenConfig::nothing(); for what in what_to_generate.split(",") { @@ -456,12 +431,6 @@ where builder = builder.disable_name_namespacing(); } - if let Some(links) = matches.values_of("framework") { - for framework in links { - builder = builder.link_framework(framework); - } - } - if matches.is_present("ignore-functions") { builder = builder.ignore_functions(); } @@ -498,12 +467,6 @@ where } } - if let Some(links) = matches.values_of("static") { - for library in links { - builder = builder.link_static(library); - } - } - if matches.is_present("use-core") { builder = builder.use_core(); } diff --git a/tests/expectations/build.rs b/tests/expectations/build.rs index 0727ce51..4f5e5a5e 100644 --- a/tests/expectations/build.rs +++ b/tests/expectations/build.rs @@ -9,7 +9,7 @@ use std::io::Write; use std::path::Path; const LIBCLANG_VERSION_DIRS: &'static [&'static str] = - &["libclang-3.8", "libclang-3.9", "libclang-4"]; + &["libclang-3.8", "libclang-3.9", "libclang-4", "libclang-5"]; fn main() { println!("cargo:rerun-if-changed=build.rs"); diff --git a/tests/expectations/tests/issue-1281.rs b/tests/expectations/tests/issue-1281.rs new file mode 100644 index 00000000..cfc8ca40 --- /dev/null +++ b/tests/expectations/tests/issue-1281.rs @@ -0,0 +1,74 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct bar { + pub u: foo, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub foo: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!( + ::std::mem::size_of::<foo>(), + 4usize, + concat!("Size of: ", stringify!(foo)) + ); + assert_eq!( + ::std::mem::align_of::<foo>(), + 4usize, + concat!("Alignment of ", stringify!(foo)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<foo>())).foo as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(foo), "::", stringify!(foo)) + ); +} +#[test] +fn bindgen_test_layout_bar() { + assert_eq!( + ::std::mem::size_of::<bar>(), + 4usize, + concat!("Size of: ", stringify!(bar)) + ); + assert_eq!( + ::std::mem::align_of::<bar>(), + 4usize, + concat!("Alignment of ", stringify!(bar)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<bar>())).u as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(bar), "::", stringify!(u)) + ); +} +pub type bar_t = bar; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct baz { + pub f: foo, +} +#[test] +fn bindgen_test_layout_baz() { + assert_eq!( + ::std::mem::size_of::<baz>(), + 4usize, + concat!("Size of: ", stringify!(baz)) + ); + assert_eq!( + ::std::mem::align_of::<baz>(), + 4usize, + concat!("Alignment of ", stringify!(baz)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<baz>())).f as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(baz), "::", stringify!(f)) + ); +} diff --git a/tests/expectations/tests/issue-1285.rs b/tests/expectations/tests/issue-1285.rs new file mode 100644 index 00000000..7b2c0ae9 --- /dev/null +++ b/tests/expectations/tests/issue-1285.rs @@ -0,0 +1,75 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +#[repr(C)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +pub union foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_ushort, + _bindgen_union_align: u32, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::<foo__bindgen_ty_1>(), + 4usize, + concat!("Size of: ", stringify!(foo__bindgen_ty_1)) + ); + assert_eq!( + ::std::mem::align_of::<foo__bindgen_ty_1>(), + 4usize, + concat!("Alignment of ", stringify!(foo__bindgen_ty_1)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<foo__bindgen_ty_1>())).a as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(foo__bindgen_ty_1), + "::", + stringify!(a) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<foo__bindgen_ty_1>())).b as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(foo__bindgen_ty_1), + "::", + stringify!(b) + ) + ); +} +impl Default for foo__bindgen_ty_1 { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!( + ::std::mem::size_of::<foo>(), + 4usize, + concat!("Size of: ", stringify!(foo)) + ); + assert_eq!( + ::std::mem::align_of::<foo>(), + 4usize, + concat!("Alignment of ", stringify!(foo)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<foo>())).bar as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) + ); +} +impl Default for foo { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} diff --git a/tests/expectations/tests/issue-1291.rs b/tests/expectations/tests/issue-1291.rs new file mode 100644 index 00000000..a2330541 --- /dev/null +++ b/tests/expectations/tests/issue-1291.rs @@ -0,0 +1,179 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct RTCRay { + pub org: [f32; 3usize], + pub align0: f32, + pub dir: [f32; 3usize], + pub align1: f32, + pub tnear: f32, + pub tfar: f32, + pub time: f32, + pub mask: ::std::os::raw::c_uint, + pub Ng: [f32; 3usize], + pub align2: f32, + pub u: f32, + pub v: f32, + pub geomID: ::std::os::raw::c_uint, + pub primID: ::std::os::raw::c_uint, + pub instID: ::std::os::raw::c_uint, + pub __bindgen_padding_0: [u32; 3usize], + pub __bindgen_align: [u8; 0usize], +} +#[test] +fn bindgen_test_layout_RTCRay() { + assert_eq!( + ::std::mem::size_of::<RTCRay>(), + 96usize, + concat!("Size of: ", stringify!(RTCRay)) + ); + assert_eq!( + ::std::mem::align_of::<RTCRay>(), + 16usize, + concat!("Alignment of ", stringify!(RTCRay)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).org as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(org) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).align0 as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(align0) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).dir as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(dir) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).align1 as *const _ as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(align1) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).tnear as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(tnear) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).tfar as *const _ as usize }, + 36usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(tfar) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).time as *const _ as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(time) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).mask as *const _ as usize }, + 44usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(mask) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).Ng as *const _ as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(Ng) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).align2 as *const _ as usize }, + 60usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(align2) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).u as *const _ as usize }, + 64usize, + concat!("Offset of field: ", stringify!(RTCRay), "::", stringify!(u)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).v as *const _ as usize }, + 68usize, + concat!("Offset of field: ", stringify!(RTCRay), "::", stringify!(v)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).geomID as *const _ as usize }, + 72usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(geomID) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).primID as *const _ as usize }, + 76usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(primID) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<RTCRay>())).instID as *const _ as usize }, + 80usize, + concat!( + "Offset of field: ", + stringify!(RTCRay), + "::", + stringify!(instID) + ) + ); +} diff --git a/tests/expectations/tests/libclang-3.8/call-conv-field.rs b/tests/expectations/tests/libclang-3.8/call-conv-field.rs index ddc1c202..bad20dea 100644 --- a/tests/expectations/tests/libclang-3.8/call-conv-field.rs +++ b/tests/expectations/tests/libclang-3.8/call-conv-field.rs @@ -2,6 +2,7 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(test))] #[repr(C)] diff --git a/tests/expectations/tests/libclang-3.9/call-conv-field.rs b/tests/expectations/tests/libclang-3.9/call-conv-field.rs index c22f5aa6..375eb9ad 100644 --- a/tests/expectations/tests/libclang-3.9/call-conv-field.rs +++ b/tests/expectations/tests/libclang-3.9/call-conv-field.rs @@ -2,6 +2,7 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(test))] #[repr(C)] diff --git a/tests/expectations/tests/libclang-4/call-conv-field.rs b/tests/expectations/tests/libclang-4/call-conv-field.rs index c22f5aa6..375eb9ad 100644 --- a/tests/expectations/tests/libclang-4/call-conv-field.rs +++ b/tests/expectations/tests/libclang-4/call-conv-field.rs @@ -2,6 +2,7 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(test))] #[repr(C)] diff --git a/tests/expectations/tests/libclang-5/auto.rs b/tests/expectations/tests/libclang-5/auto.rs new file mode 100644 index 00000000..2d7dfa3a --- /dev/null +++ b/tests/expectations/tests/libclang-5/auto.rs @@ -0,0 +1,34 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Foo { + pub _address: u8, +} +pub const Foo_kFoo: bool = true; +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!( + ::std::mem::size_of::<Foo>(), + 1usize, + concat!("Size of: ", stringify!(Foo)) + ); + assert_eq!( + ::std::mem::align_of::<Foo>(), + 1usize, + concat!("Alignment of ", stringify!(Foo)) + ); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub _address: u8, +} +extern "C" { + #[link_name = "\u{1}_Z5Test2v"] + pub fn Test2() -> ::std::os::raw::c_uint; +} diff --git a/tests/expectations/tests/libclang-5/call-conv-field.rs b/tests/expectations/tests/libclang-5/call-conv-field.rs new file mode 100644 index 00000000..295a23f9 --- /dev/null +++ b/tests/expectations/tests/libclang-5/call-conv-field.rs @@ -0,0 +1,51 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![cfg(not(test))] + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct JNINativeInterface_ { + pub GetVersion: ::std::option::Option< + unsafe extern "stdcall" fn(env: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, + >, + pub __bindgen_padding_0: u32, + pub __hack: ::std::os::raw::c_ulonglong, +} +#[test] +fn bindgen_test_layout_JNINativeInterface_() { + assert_eq!( + ::std::mem::size_of::<JNINativeInterface_>(), + 16usize, + concat!("Size of: ", stringify!(JNINativeInterface_)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<JNINativeInterface_>())).GetVersion as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(JNINativeInterface_), + "::", + stringify!(GetVersion) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<JNINativeInterface_>())).__hack as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(JNINativeInterface_), + "::", + stringify!(__hack) + ) + ); +} +impl Default for JNINativeInterface_ { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +extern "stdcall" { + #[link_name = "\u{1}_bar@0"] + pub fn bar(); +} diff --git a/tests/expectations/tests/libclang-5/const_bool.rs b/tests/expectations/tests/libclang-5/const_bool.rs new file mode 100644 index 00000000..14f51394 --- /dev/null +++ b/tests/expectations/tests/libclang-5/const_bool.rs @@ -0,0 +1,28 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +pub const k: bool = true; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct A { + pub _address: u8, +} +pub const A_k: bool = false; +#[test] +fn bindgen_test_layout_A() { + assert_eq!( + ::std::mem::size_of::<A>(), + 1usize, + concat!("Size of: ", stringify!(A)) + ); + assert_eq!( + ::std::mem::align_of::<A>(), + 1usize, + concat!("Alignment of ", stringify!(A)) + ); +} +pub type foo = bool; +pub const k2: foo = true; diff --git a/tests/expectations/tests/libclang-5/constant-evaluate.rs b/tests/expectations/tests/libclang-5/constant-evaluate.rs new file mode 100644 index 00000000..51365df5 --- /dev/null +++ b/tests/expectations/tests/libclang-5/constant-evaluate.rs @@ -0,0 +1,21 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo; +pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum _bindgen_ty_1 { + foo = 4, + bar = 8, +} +pub type EasyToOverflow = ::std::os::raw::c_ulonglong; +pub const k: EasyToOverflow = 2147483648; +pub const k_expr: EasyToOverflow = 0; +pub const BAZ: ::std::os::raw::c_longlong = 24; +pub const fuzz: f64 = 51.; +pub const BAZZ: ::std::os::raw::c_char = 53; +pub const WAT: ::std::os::raw::c_char = 0; +pub const bytestring: &'static [u8; 4usize] = b"Foo\0"; +pub const NOT_UTF8: [u8; 5usize] = [240u8, 40u8, 140u8, 40u8, 0u8]; diff --git a/tests/expectations/tests/libclang-5/issue-769-bad-instantiation-test.rs b/tests/expectations/tests/libclang-5/issue-769-bad-instantiation-test.rs new file mode 100644 index 00000000..86fad78d --- /dev/null +++ b/tests/expectations/tests/libclang-5/issue-769-bad-instantiation-test.rs @@ -0,0 +1,40 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct Rooted<T> { + pub member: T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, + } + impl<T> Default for Rooted<T> { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } + } + pub type AutoValueVector_Alias = ::std::os::raw::c_int; + #[test] + fn __bindgen_test_layout_Rooted_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::<root::Rooted<::std::os::raw::c_int>>(), + 4usize, + concat!( + "Size of template specialization: ", + stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) + ) + ); + assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < :: std :: os :: raw :: c_int > ) ) ); + } + #[test] + fn __bindgen_test_layout_Rooted_open0_AutoValueVector_Alias_close0_instantiation() { + assert_eq ! ( :: std :: mem :: size_of :: < root :: Rooted < root :: AutoValueVector_Alias > > ( ) , 4usize , concat ! ( "Size of template specialization: " , stringify ! ( root :: Rooted < root :: AutoValueVector_Alias > ) ) ); + assert_eq ! ( :: std :: mem :: align_of :: < root :: Rooted < root :: AutoValueVector_Alias > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( root :: Rooted < root :: AutoValueVector_Alias > ) ) ); + } +} diff --git a/tests/expectations/tests/libclang-5/objc_template.rs b/tests/expectations/tests/libclang-5/objc_template.rs new file mode 100644 index 00000000..06a9a55f --- /dev/null +++ b/tests/expectations/tests/libclang-5/objc_template.rs @@ -0,0 +1,18 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +#![cfg(target_os="macos")] + +#[macro_use] +extern crate objc; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +pub trait Foo { + unsafe fn get(self) + -> *mut ObjectType; +} +impl Foo for id { + unsafe fn get(self) -> *mut ObjectType { msg_send!(self , get) } +} diff --git a/tests/expectations/tests/libclang-5/partial-specialization-and-inheritance.rs b/tests/expectations/tests/libclang-5/partial-specialization-and-inheritance.rs new file mode 100644 index 00000000..97d2eabe --- /dev/null +++ b/tests/expectations/tests/libclang-5/partial-specialization-and-inheritance.rs @@ -0,0 +1,38 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Base { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Derived { + pub b: bool, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Usage { + pub _address: u8, +} +extern "C" { + #[link_name = "\u{1}_ZN5Usage13static_memberE"] + pub static mut Usage_static_member: [u32; 2usize]; +} +#[test] +fn bindgen_test_layout_Usage() { + assert_eq!( + ::std::mem::size_of::<Usage>(), + 1usize, + concat!("Size of: ", stringify!(Usage)) + ); + assert_eq!( + ::std::mem::align_of::<Usage>(), + 1usize, + concat!("Alignment of ", stringify!(Usage)) + ); +} diff --git a/tests/expectations/tests/libclang-5/type_alias_template_specialized.rs b/tests/expectations/tests/libclang-5/type_alias_template_specialized.rs new file mode 100644 index 00000000..a09323a8 --- /dev/null +++ b/tests/expectations/tests/libclang-5/type_alias_template_specialized.rs @@ -0,0 +1,60 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub ptr: MaybeWrapped<::std::os::raw::c_int>, +} +#[test] +fn bindgen_test_layout_Rooted() { + assert_eq!( + ::std::mem::size_of::<Rooted>(), + 4usize, + concat!("Size of: ", stringify!(Rooted)) + ); + assert_eq!( + ::std::mem::align_of::<Rooted>(), + 4usize, + concat!("Alignment of ", stringify!(Rooted)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Rooted>())).ptr as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(Rooted), + "::", + stringify!(ptr) + ) + ); +} +impl Default for Rooted { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +/// <div rustbindgen replaces="MaybeWrapped"></div> +pub type MaybeWrapped<a> = a; +#[test] +fn __bindgen_test_layout_MaybeWrapped_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::<MaybeWrapped<::std::os::raw::c_int>>(), + 4usize, + concat!( + "Size of template specialization: ", + stringify!(MaybeWrapped<::std::os::raw::c_int>) + ) + ); + assert_eq!( + ::std::mem::align_of::<MaybeWrapped<::std::os::raw::c_int>>(), + 4usize, + concat!( + "Alignment of template specialization: ", + stringify!(MaybeWrapped<::std::os::raw::c_int>) + ) + ); +} diff --git a/tests/headers/call-conv-field.h b/tests/headers/call-conv-field.h index 6fa5c46f..da45ba1d 100644 --- a/tests/headers/call-conv-field.h +++ b/tests/headers/call-conv-field.h @@ -1,11 +1,8 @@ -// bindgen-flags: -- --target=i686-pc-win32 +// bindgen-flags: --raw-line "#![cfg(not(test))]" -- --target=i686-pc-win32 // bindgen-unstable -// bindgen-generate-bindings-on-linux-only // -// The linux-only thing is a hack around our lack of understanding when -// bindgen's target_os != the bindings' target_os :( -// -// https://github.com/rust-lang-nursery/rust-bindgen/issues/593 +// We can only check that this builds, but not that it actually passes, because +// we have no CI on the target platform. struct JNINativeInterface_ { int (__stdcall *GetVersion)(void *env); diff --git a/tests/headers/issue-1281.h b/tests/headers/issue-1281.h new file mode 100644 index 00000000..4a3aaab0 --- /dev/null +++ b/tests/headers/issue-1281.h @@ -0,0 +1,11 @@ +struct foo; + +typedef struct bar { + struct foo { + int foo; + } u; +} bar_t; + +struct baz { + struct foo f; +}; diff --git a/tests/headers/issue-1285.h b/tests/headers/issue-1285.h new file mode 100644 index 00000000..7fb742ec --- /dev/null +++ b/tests/headers/issue-1285.h @@ -0,0 +1,8 @@ +// bindgen-flags: --with-derive-hash --no-recursive-whitelist --whitelist-type "foo" + +struct foo { + union { + unsigned int a; + unsigned short b; + } bar; +};
\ No newline at end of file diff --git a/tests/headers/issue-1291.hpp b/tests/headers/issue-1291.hpp new file mode 100644 index 00000000..4ec524f1 --- /dev/null +++ b/tests/headers/issue-1291.hpp @@ -0,0 +1,21 @@ +// bindgen-flags: --rust-target 1.25 +// bindgen-unstable + +struct __attribute__((aligned(16))) RTCRay + { + float org[3]; + float align0; + float dir[3]; + float align1; + float tnear; + float tfar; + float time; + unsigned mask; + float Ng[3]; + float align2; + float u; + float v; + unsigned geomID; + unsigned primID; + unsigned instID; +}; diff --git a/tests/tests.rs b/tests/tests.rs index 6ee67fed..fd53f068 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -118,6 +118,8 @@ fn compare_generated_header( if cfg!(feature = "testing_only_libclang_4") { expectation.push("libclang-4"); + } else if cfg!(feature = "testing_only_libclang_5") { + expectation.push("libclang-5"); } else if cfg!(feature = "testing_only_libclang_3_9") { expectation.push("libclang-3.9"); } else if cfg!(feature = "testing_only_libclang_3_8") { @@ -127,7 +129,9 @@ fn compare_generated_header( None => {} Some(version) => { let (maj, min) = version; - let version_str = if maj >= 4 { + let version_str = if maj >= 5 { + "5".to_owned() + } else if maj == 4 { "4".to_owned() } else { format!("{}.{}", maj, min) |