summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rwxr-xr-xreleases/friends.sh19
-rw-r--r--releases/release-announcement-template.md72
-rw-r--r--src/ir/item.rs19
-rw-r--r--src/lib.rs71
-rw-r--r--src/main.rs4
-rw-r--r--src/options.rs9
-rw-r--r--src/uses.rs105
-rw-r--r--tests/expectations/tests/issue-848-replacement-system-include.rs24
-rw-r--r--tests/expectations/tests/template.rs23
-rw-r--r--tests/headers/issue-848-replacement-system-include.hpp7
-rw-r--r--tests/headers/issue-848/an-include.h17
-rw-r--r--tests/headers/template.hpp4
14 files changed, 208 insertions, 170 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 690c0a16..3f0f65df 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,6 @@
[root]
name = "bindgen"
-version = "0.28.0"
+version = "0.29.0"
dependencies = [
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index 91ef7279..d384b8bf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@ name = "bindgen"
readme = "README.md"
repository = "https://github.com/rust-lang-nursery/rust-bindgen"
documentation = "https://docs.rs/bindgen"
-version = "0.28.0"
+version = "0.29.0"
build = "build.rs"
exclude = [
diff --git a/releases/friends.sh b/releases/friends.sh
new file mode 100755
index 00000000..453f5d37
--- /dev/null
+++ b/releases/friends.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+set -eu
+set -o pipefail
+
+cd "$(dirname $0)"
+
+if [[ -z "${1+x}" ]]; then
+ read -p "List friends since which commit/tag? " since
+ echo
+else
+ since=$1
+fi
+
+git shortlog -s -n "$since.." \
+ | cut -f 2- \
+ | sort -u \
+ | grep -v bors\-servo \
+ | xargs -I{} echo "- {}"
diff --git a/releases/release-announcement-template.md b/releases/release-announcement-template.md
new file mode 100644
index 00000000..c9d5eae2
--- /dev/null
+++ b/releases/release-announcement-template.md
@@ -0,0 +1,72 @@
+# Announcing `bindgen` $TODO_VERSION
+
+`bindgen` automatically generates Rust FFI bindings to C and C++ libraries.
+
+Upgrade to this release by updating your `Cargo.toml`:
+
+```toml
+bindgen = "$TODO_VERSION"
+```
+
+* [GitHub][]
+* [crates.io][]
+* [Users Guide][guide]
+* [API Documentation][docs]
+
+## Changelog
+
+### Added
+
+* TODO (or remove section if none)
+
+### Changed
+
+* TODO (or remove section if none)
+
+### Deprecated
+
+* TODO (or remove section if none)
+
+### Removed
+
+* TODO (or remove section if none)
+
+### Fixed
+
+* TODO (or remove section if none)
+
+### Security
+
+* TODO (or remove section if none)
+
+
+## Friends
+
+Thanks to everyone who contributed to this release!
+
+<insert the output of friends.sh here>
+
+## Contributing
+
+Want to join us? Check out our [CONTRIBUTING.md][contributing] and take a look
+at some of these issues:
+
+* [Issues labeled "easy"][easy]
+* [Issues labeled "less easy"][less-easy]
+* Still can't find something to work on? [Drop a comment here.][looking]
+
+Want to help improve our documentation?
+[Check out the issues labeled "docs".][docs-issues]
+
+Found a bug with `bindgen`? [File an issue here.][file-issue]
+
+[GitHub]: https://github.com/rust-lang-nursery/rust-bindgen
+[crates.io]: https://crates.io/crates/bindgen
+[guide]: https://rust-lang-nursery.github.io/rust-bindgen
+[docs]: https://docs.rs/bindgen
+[contributing]: https://github.com/rust-lang-nursery/rust-bindgen/blob/master/CONTRIBUTING.md
+[easy]: https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy
+[less-easy]: https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-less-easy
+[looking]: https://github.com/rust-lang-nursery/rust-bindgen/issues/747
+[docs-issues]: https://github.com/rust-lang-nursery/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AI-needs-docs
+[file-issue]: https://github.com/rust-lang-nursery/rust-bindgen/issues/new
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 8a210e38..ff692fdb 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -728,12 +728,21 @@ impl Item {
ItemKind::Type(ref ty) => {
let name = match *ty.kind() {
TypeKind::ResolvedTypeRef(..) => panic!("should have resolved this in name_target()"),
- _ => ty.name(),
+ TypeKind::Pointer(inner) => {
+ ctx.resolve_item(inner)
+ .expect_type().name()
+ .map(|name| format!("ptr_{}", name))
+ }
+ TypeKind::Array(inner, length) => {
+ ctx.resolve_item(inner)
+ .expect_type().name()
+ .map(|name| format!("array_{}_{}", name, length))
+ }
+ _ => ty.name().map(ToOwned::to_owned)
};
- name.map(ToOwned::to_owned)
- .unwrap_or_else(|| {
- format!("_bindgen_ty_{}", self.exposed_id(ctx))
- })
+ name.unwrap_or_else(|| {
+ format!("_bindgen_ty_{}", self.exposed_id(ctx))
+ })
}
ItemKind::Function(ref fun) => {
let mut name = fun.name().to_owned();
diff --git a/src/lib.rs b/src/lib.rs
index 4eeb95f4..3a853829 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -65,7 +65,6 @@ mod clang;
mod ir;
mod parse;
mod regex_set;
-mod uses;
pub mod callbacks;
@@ -76,7 +75,6 @@ doc_mod!(clang, clang_docs);
doc_mod!(ir, ir_docs);
doc_mod!(parse, parse_docs);
doc_mod!(regex_set, regex_set_docs);
-doc_mod!(uses, uses_docs);
mod codegen {
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
@@ -265,11 +263,6 @@ impl Builder {
output_vector.push(prefix.clone());
}
- if let Some(ref dummy) = self.options.dummy_uses {
- output_vector.push("--dummy-uses".into());
- output_vector.push(dummy.clone());
- }
-
if self.options.emit_ast {
output_vector.push("--emit-clang-ast".into());
}
@@ -519,13 +512,6 @@ impl Builder {
self
}
- /// Generate a C/C++ file that includes the header and has dummy uses of
- /// every type defined in the header.
- pub fn dummy_uses<T: Into<String>>(mut self, dummy_uses: T) -> Builder {
- self.options.dummy_uses = Some(dummy_uses.into());
- self
- }
-
/// Hide the given type from the generated bindings. Regular expressions are
/// supported.
pub fn hide_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
@@ -1001,10 +987,6 @@ pub struct BindgenOptions {
/// Unsaved files for input.
pub input_unsaved_files: Vec<clang::UnsavedFile>,
- /// Generate a dummy C/C++ file that includes the header and has dummy uses
- /// of all types defined therein. See the `uses` module for more.
- pub dummy_uses: Option<String>,
-
/// A user-provided visitor to allow customizing different kinds of
/// situations.
pub parse_callbacks: Option<Box<callbacks::ParseCallbacks>>,
@@ -1094,7 +1076,6 @@ impl Default for BindgenOptions {
clang_args: vec![],
input_header: None,
input_unsaved_files: vec![],
- dummy_uses: None,
parse_callbacks: None,
codegen_config: CodegenConfig::all(),
conservative_inline_namespaces: false,
@@ -1162,8 +1143,35 @@ impl<'ctx> Bindings<'ctx> {
options.build();
+ // Filter out include paths and similar stuff, so we don't incorrectly
+ // promote them to `-isystem`.
+ let clang_args_for_clang_sys = {
+ let mut last_was_include_prefix = false;
+ options.clang_args.iter().filter(|arg| {
+ if last_was_include_prefix {
+ last_was_include_prefix = false;
+ return false;
+ }
+
+ let arg = &**arg;
+
+ // https://clang.llvm.org/docs/ClangCommandLineReference.html
+ // -isystem and -isystem-after are harmless.
+ if arg == "-I" || arg == "--include-directory" {
+ last_was_include_prefix = true;
+ return false;
+ }
+
+ if arg.starts_with("-I") || arg.starts_with("--include-directory=") {
+ return false;
+ }
+
+ true
+ }).cloned().collect::<Vec<_>>()
+ };
+
// TODO: Make this path fixup configurable?
- if let Some(clang) = clang_sys::support::Clang::find(None, &options.clang_args) {
+ if let Some(clang) = clang_sys::support::Clang::find(None, &clang_args_for_clang_sys) {
// If --target is specified, assume caller knows what they're doing
// and don't mess with include paths for them
let has_target_arg = options.clang_args
@@ -1250,29 +1258,6 @@ impl<'ctx> Bindings<'ctx> {
try!(eof(&mut ps.s));
ps.s.out.flush()
}
-
- /// Generate and write dummy uses of all the types we parsed, if we've been
- /// requested to do so in the options.
- ///
- /// See the `uses` module for more information.
- pub fn write_dummy_uses(&mut self) -> io::Result<()> {
- let file = if let Some(ref dummy_path) =
- self.context.options().dummy_uses {
- Some(try!(OpenOptions::new()
- .write(true)
- .truncate(true)
- .create(true)
- .open(dummy_path)))
- } else {
- None
- };
-
- if let Some(file) = file {
- try!(uses::generate_dummy_uses(&mut self.context, file));
- }
-
- Ok(())
- }
}
/// Determines whether the given cursor is in any of the files matched by the
diff --git a/src/main.rs b/src/main.rs
index 9cd4f806..32248cb0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -64,11 +64,9 @@ pub fn main() {
std::process::exit(1);
}
- let mut bindings = builder_result.unwrap();
+ let bindings = builder_result.unwrap();
bindings.write(output)
.expect("Unable to write output");
- bindings.write_dummy_uses()
- .expect("Unable to write dummy uses to file.");
}
Err(error) => {
println!("{}", error);
diff --git a/src/options.rs b/src/options.rs
index 3d54eb39..f2ed5494 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -88,11 +88,6 @@ pub fn builder_from_flags<I>
// All positional arguments after the end of options marker, `--`
Arg::with_name("clang-args")
.multiple(true),
- Arg::with_name("dummy-uses")
- .long("dummy-uses")
- .help("For testing purposes, generate a C/C++ file containing \
- dummy uses of all types defined in the input header.")
- .takes_value(true),
Arg::with_name("emit-clang-ast")
.long("emit-clang-ast")
.help("Output the Clang AST for debugging purposes."),
@@ -282,10 +277,6 @@ pub fn builder_from_flags<I>
builder = builder.ctypes_prefix(prefix);
}
- if let Some(dummy) = matches.value_of("dummy-uses") {
- builder = builder.dummy_uses(dummy);
- }
-
if let Some(links) = matches.values_of("dynamic") {
for library in links {
builder = builder.link(library);
diff --git a/src/uses.rs b/src/uses.rs
deleted file mode 100644
index fc7c126e..00000000
--- a/src/uses.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-//! 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 ir::template::TemplateParameters;
-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<W>(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()
- .iter()
- .cloned()
- .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
- // instantiations, so ignore template declarations and
- // instantiations.
- item.all_template_params(ctx).is_none()
- } else {
- false
- }
- })
- .map(|item| namespaced_name(ctx, item))
- .enumerate();
-
- for (idx, name) in type_items {
- try!(writeln!(dest, "void dummy{}({}*) {{ }}", idx, name));
- }
-
- Ok(())
- })
-}
diff --git a/tests/expectations/tests/issue-848-replacement-system-include.rs b/tests/expectations/tests/issue-848-replacement-system-include.rs
new file mode 100644
index 00000000..14083705
--- /dev/null
+++ b/tests/expectations/tests/issue-848-replacement-system-include.rs
@@ -0,0 +1,24 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+/// This is intended to replace another type, but won't if we treat this include
+/// as a system include, because clang doesn't parse comments there.
+///
+/// See #848.
+///
+/// <div rustbindgen replaces="nsTArray"></div>
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct nsTArray<T> {
+ pub m: *mut T,
+ pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
+}
+impl <T> Default for nsTArray<T> {
+ fn default() -> Self { unsafe { ::std::mem::zeroed() } }
+}
+extern "C" {
+ pub fn func() -> *mut nsTArray<::std::os::raw::c_int>;
+}
diff --git a/tests/expectations/tests/template.rs b/tests/expectations/tests/template.rs
index 8e432167..275f45ea 100644
--- a/tests/expectations/tests/template.rs
+++ b/tests/expectations/tests/template.rs
@@ -37,6 +37,7 @@ pub struct C {
pub mBVolatile: B<::std::os::raw::c_int>,
pub mBConstBool: B<bool>,
pub mBConstChar: B<u16>,
+ pub mBArray: B<[::std::os::raw::c_int; 1usize]>,
}
#[test]
fn bindgen_test_layout_C() {
@@ -73,6 +74,11 @@ fn bindgen_test_layout_C() {
} , 26usize , concat ! (
"Alignment of field: " , stringify ! ( C ) , "::" , stringify
! ( mBConstChar ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const C ) ) . mBArray as * const _ as usize } ,
+ 28usize , concat ! (
+ "Alignment of field: " , stringify ! ( C ) , "::" , stringify
+ ! ( mBArray ) ));
}
impl Clone for C {
fn clone(&self) -> Self { *self }
@@ -317,7 +323,7 @@ fn __bindgen_test_layout_B_open0_unsigned_int_close0_instantiation() {
B<::std::os::raw::c_uint> ) ));
}
#[test]
-fn __bindgen_test_layout_B_open0__bindgen_ty_id_113_close0_instantiation() {
+fn __bindgen_test_layout_B_open0_ptr_const_int_close0_instantiation() {
assert_eq!(::std::mem::size_of::<B<*const ::std::os::raw::c_int>>() ,
8usize , concat ! (
"Size of template specialization: " , stringify ! (
@@ -368,6 +374,17 @@ fn __bindgen_test_layout_B_open0_const_char16_t_close0_instantiation() {
) ));
}
#[test]
+fn __bindgen_test_layout_B_open0_array_int_1_close0_instantiation() {
+ assert_eq!(::std::mem::size_of::<B<[::std::os::raw::c_int; 1usize]>>() ,
+ 4usize , concat ! (
+ "Size of template specialization: " , stringify ! (
+ B<[::std::os::raw::c_int; 1usize]> ) ));
+ assert_eq!(::std::mem::align_of::<B<[::std::os::raw::c_int; 1usize]>>() ,
+ 4usize , concat ! (
+ "Alignment of template specialization: " , stringify ! (
+ B<[::std::os::raw::c_int; 1usize]> ) ));
+}
+#[test]
fn __bindgen_test_layout_Foo_open0_int_int_close0_instantiation_1() {
assert_eq!(::std::mem::size_of::<Foo<::std::os::raw::c_int>>() , 24usize ,
concat ! (
@@ -379,7 +396,7 @@ fn __bindgen_test_layout_Foo_open0_int_int_close0_instantiation_1() {
Foo<::std::os::raw::c_int> ) ));
}
#[test]
-fn __bindgen_test_layout_Rooted_open0__bindgen_ty_id_144_close0_instantiation() {
+fn __bindgen_test_layout_Rooted_open0_ptr_void_close0_instantiation() {
assert_eq!(::std::mem::size_of::<Rooted<*mut ::std::os::raw::c_void>>() ,
24usize , concat ! (
"Size of template specialization: " , stringify ! (
@@ -390,7 +407,7 @@ fn __bindgen_test_layout_Rooted_open0__bindgen_ty_id_144_close0_instantiation()
Rooted<*mut ::std::os::raw::c_void> ) ));
}
#[test]
-fn __bindgen_test_layout_Rooted_open0__bindgen_ty_id_150_close0_instantiation() {
+fn __bindgen_test_layout_Rooted_open0_ptr_void_close0_instantiation_1() {
assert_eq!(::std::mem::size_of::<Rooted<*mut ::std::os::raw::c_void>>() ,
24usize , concat ! (
"Size of template specialization: " , stringify ! (
diff --git a/tests/headers/issue-848-replacement-system-include.hpp b/tests/headers/issue-848-replacement-system-include.hpp
new file mode 100644
index 00000000..e95c823f
--- /dev/null
+++ b/tests/headers/issue-848-replacement-system-include.hpp
@@ -0,0 +1,7 @@
+// bindgen-flags: -- -Itests/headers/issue-848
+
+#include "an-include.h"
+
+extern "C" {
+ nsTArray<int>* func();
+}
diff --git a/tests/headers/issue-848/an-include.h b/tests/headers/issue-848/an-include.h
new file mode 100644
index 00000000..0421d19f
--- /dev/null
+++ b/tests/headers/issue-848/an-include.h
@@ -0,0 +1,17 @@
+template<typename T>
+class nsTArray {
+ void* mBuffer;
+};
+
+/**
+ * This is intended to replace another type, but won't if we treat this include
+ * as a system include, because clang doesn't parse comments there.
+ *
+ * See #848.
+ *
+ * <div rustbindgen replaces="nsTArray"></div>
+ */
+template<typename T>
+class nsTArray_Simple {
+ T* m;
+};
diff --git a/tests/headers/template.hpp b/tests/headers/template.hpp
index 7d373152..168eac9c 100644
--- a/tests/headers/template.hpp
+++ b/tests/headers/template.hpp
@@ -19,6 +19,10 @@ struct C {
B<volatile int> mBVolatile;
B<const bool> mBConstBool;
B<const char16_t> mBConstChar;
+ B<int[1]> mBArray;
+ // clang 3.x ignores const in this case, so they generate different
+ // result than clang 4.0.
+ // B<const int[1]> mBConstArray;
};
template<typename T>