summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clang.rs13
-rw-r--r--src/codegen/mod.rs10
-rw-r--r--src/ir/context.rs2
-rw-r--r--src/ir/function.rs3
-rw-r--r--src/lib.rs30
-rw-r--r--src/options.rs7
-rw-r--r--tests/expectations/tests/enum_and_vtable_mangling.rs4
-rw-r--r--tests/expectations/tests/generate-inline.rs33
-rw-r--r--tests/expectations/tests/nested_vtable.rs4
-rw-r--r--tests/expectations/tests/ref_argument_array.rs4
-rw-r--r--tests/expectations/tests/virtual_dtor.rs4
-rw-r--r--tests/expectations/tests/virtual_inheritance.rs8
-rw-r--r--tests/expectations/tests/virtual_overloaded.rs4
-rw-r--r--tests/expectations/tests/vtable_recursive_sig.rs4
-rw-r--r--tests/headers/generate-inline.hpp12
-rw-r--r--tests/tests.rs18
16 files changed, 126 insertions, 34 deletions
diff --git a/src/clang.rs b/src/clang.rs
index 669db207..2dbe5e51 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -1429,7 +1429,9 @@ impl Drop for Diagnostic {
/// A file which has not been saved to disk.
pub struct UnsavedFile {
x: CXUnsavedFile,
- name: CString,
+ /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in
+ /// `CXUnsavedFile`.
+ pub name: CString,
contents: CString,
}
@@ -1451,6 +1453,15 @@ impl UnsavedFile {
}
}
+impl fmt::Debug for UnsavedFile {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt,
+ "UnsavedFile(name: {:?}, contents: {:?})",
+ self.name,
+ self.contents)
+ }
+}
+
/// Convert a cursor kind into a static string.
pub fn kind_to_str(x: CXCursorKind) -> String {
unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 7db083e7..fb6c839d 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -706,17 +706,15 @@ impl<'a> CodeGenerator for Vtable<'a> {
assert_eq!(item.id(), self.item_id);
// For now, generate an empty struct, later we should generate function
// pointers and whatnot.
- let mut attributes = vec![attributes::repr("C")];
-
- if ctx.options().derive_default {
- attributes.push(attributes::derives(&["Default"]))
- }
+ let attributes = vec![attributes::repr("C")];
let vtable = aster::AstBuilder::new()
.item()
.pub_()
.with_attrs(attributes)
- .struct_(self.canonical_name(ctx))
+ .tuple_struct(self.canonical_name(ctx))
+ .field()
+ .build_ty(helpers::ast_ty::raw_type(ctx, "c_void"))
.build();
result.push(vtable);
}
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 4a6785b1..c95d5179 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -182,7 +182,7 @@ impl<'ctx> BindgenContext<'ctx> {
clang::TranslationUnit::parse(&index,
"",
&options.clang_args,
- &[],
+ &options.input_unsaved_files,
parse_options)
.expect("TranslationUnit::parse failed");
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 941694ff..fd88b657 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -310,7 +310,8 @@ impl ClangSubItemParser for Function {
return Err(ParseError::Continue);
}
- if cursor.is_inlined_function() {
+ if !context.options().generate_inline_functions &&
+ cursor.is_inlined_function() {
return Err(ParseError::Continue);
}
diff --git a/src/lib.rs b/src/lib.rs
index e92be92b..8f838c15 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -175,6 +175,14 @@ impl Builder {
self
}
+ /// Add `contents` as an input C/C++ header named `name`.
+ ///
+ /// The file `name` will be added to the clang arguments.
+ pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
+ self.options.input_unsaved_files.push(clang::UnsavedFile::new(name, contents));
+ self
+ }
+
/// Set the output graphviz file.
pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
let path = path.into();
@@ -415,6 +423,16 @@ impl Builder {
self
}
+ /// Whether inline functions should be generated or not.
+ ///
+ /// Note that they will usually not work. However you can use
+ /// `-fkeep-inline-functions` or `-fno-inline-functions` if you are
+ /// responsible of compiling the library to make them callable.
+ pub fn generate_inline_functions(mut self, doit: bool) -> Self {
+ self.options.generate_inline_functions = doit;
+ self
+ }
+
/// Ignore functions.
pub fn ignore_functions(mut self) -> Builder {
self.options.codegen_config.functions = false;
@@ -563,6 +581,9 @@ pub struct BindgenOptions {
/// The input header file.
pub input_header: Option<String>,
+ /// 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>,
@@ -584,6 +605,9 @@ pub struct BindgenOptions {
/// documentation for more details.
pub generate_comments: bool,
+ /// Whether to generate inline functions. Defaults to false.
+ pub generate_inline_functions: bool,
+
/// Wether to whitelist types recursively. Defaults to true.
pub whitelist_recursively: bool,
@@ -649,11 +673,13 @@ impl Default for BindgenOptions {
raw_lines: vec![],
clang_args: vec![],
input_header: None,
+ input_unsaved_files: vec![],
dummy_uses: None,
parse_callbacks: None,
codegen_config: CodegenConfig::all(),
conservative_inline_namespaces: false,
generate_comments: true,
+ generate_inline_functions: false,
whitelist_recursively: true,
objc_extern_crate: false,
enable_mangling: true,
@@ -740,6 +766,10 @@ impl<'ctx> Bindings<'ctx> {
options.clang_args.push(h.clone())
}
+ for f in options.input_unsaved_files.iter() {
+ options.clang_args.push(f.name.to_str().unwrap().to_owned())
+ }
+
let mut context = BindgenContext::new(options);
try!(parse(&mut context));
diff --git a/src/options.rs b/src/options.rs
index 15146b39..f1c8479a 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -177,6 +177,9 @@ pub fn builder_from_flags<I>
.takes_value(true)
.multiple(true)
.number_of_values(1),
+ Arg::with_name("generate-inline-functions")
+ .long("generate-inline-functions")
+ .help("Whether inline functions should be generated."),
Arg::with_name("whitelist-type")
.long("whitelist-type")
.help("Whitelist the type. Other non-whitelisted types will \
@@ -357,6 +360,10 @@ pub fn builder_from_flags<I>
builder = builder.conservative_inline_namespaces();
}
+ if matches.is_present("generate-inline-functions") {
+ builder = builder.generate_inline_functions(true);
+ }
+
if let Some(whitelist) = matches.values_of("whitelist-function") {
for regex in whitelist {
builder = builder.whitelisted_function(regex);
diff --git a/tests/expectations/tests/enum_and_vtable_mangling.rs b/tests/expectations/tests/enum_and_vtable_mangling.rs
index 300edd39..b34e217f 100644
--- a/tests/expectations/tests/enum_and_vtable_mangling.rs
+++ b/tests/expectations/tests/enum_and_vtable_mangling.rs
@@ -10,9 +10,7 @@ pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 { match_ = 0, whatever_else = 1, }
#[repr(C)]
-#[derive(Default)]
-pub struct C__bindgen_vtable {
-}
+pub struct C__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct C {
diff --git a/tests/expectations/tests/generate-inline.rs b/tests/expectations/tests/generate-inline.rs
new file mode 100644
index 00000000..72057414
--- /dev/null
+++ b/tests/expectations/tests/generate-inline.rs
@@ -0,0 +1,33 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct Foo {
+ pub _address: u8,
+}
+#[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 ) ));
+}
+extern "C" {
+ #[link_name = "_ZN3Foo3barEv"]
+ pub fn Foo_bar() -> ::std::os::raw::c_int;
+}
+impl Clone for Foo {
+ fn clone(&self) -> Self { *self }
+}
+impl Foo {
+ #[inline]
+ pub unsafe fn bar() -> ::std::os::raw::c_int { Foo_bar() }
+}
+extern "C" {
+ #[link_name = "_Z3foov"]
+ pub fn foo() -> ::std::os::raw::c_int;
+}
diff --git a/tests/expectations/tests/nested_vtable.rs b/tests/expectations/tests/nested_vtable.rs
index e16a23d7..4c9dc8f6 100644
--- a/tests/expectations/tests/nested_vtable.rs
+++ b/tests/expectations/tests/nested_vtable.rs
@@ -5,9 +5,7 @@
#[repr(C)]
-#[derive(Default)]
-pub struct nsISupports__bindgen_vtable {
-}
+pub struct nsISupports__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsISupports {
diff --git a/tests/expectations/tests/ref_argument_array.rs b/tests/expectations/tests/ref_argument_array.rs
index 714467f6..51531824 100644
--- a/tests/expectations/tests/ref_argument_array.rs
+++ b/tests/expectations/tests/ref_argument_array.rs
@@ -6,9 +6,7 @@
pub const NSID_LENGTH: ::std::os::raw::c_uint = 10;
#[repr(C)]
-#[derive(Default)]
-pub struct nsID__bindgen_vtable {
-}
+pub struct nsID__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsID {
diff --git a/tests/expectations/tests/virtual_dtor.rs b/tests/expectations/tests/virtual_dtor.rs
index 0c410977..e5d3ace2 100644
--- a/tests/expectations/tests/virtual_dtor.rs
+++ b/tests/expectations/tests/virtual_dtor.rs
@@ -5,9 +5,7 @@
#[repr(C)]
-#[derive(Default)]
-pub struct nsSlots__bindgen_vtable {
-}
+pub struct nsSlots__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug)]
pub struct nsSlots {
diff --git a/tests/expectations/tests/virtual_inheritance.rs b/tests/expectations/tests/virtual_inheritance.rs
index 6896eb31..b3119ca7 100644
--- a/tests/expectations/tests/virtual_inheritance.rs
+++ b/tests/expectations/tests/virtual_inheritance.rs
@@ -25,9 +25,7 @@ impl Clone for A {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
-#[derive(Default)]
-pub struct B__bindgen_vtable {
-}
+pub struct B__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct B {
@@ -53,9 +51,7 @@ impl Default for B {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
-#[derive(Default)]
-pub struct C__bindgen_vtable {
-}
+pub struct C__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct C {
diff --git a/tests/expectations/tests/virtual_overloaded.rs b/tests/expectations/tests/virtual_overloaded.rs
index e7ae9f4a..625abe3b 100644
--- a/tests/expectations/tests/virtual_overloaded.rs
+++ b/tests/expectations/tests/virtual_overloaded.rs
@@ -5,9 +5,7 @@
#[repr(C)]
-#[derive(Default)]
-pub struct C__bindgen_vtable {
-}
+pub struct C__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct C {
diff --git a/tests/expectations/tests/vtable_recursive_sig.rs b/tests/expectations/tests/vtable_recursive_sig.rs
index 716ce39f..0faf37ac 100644
--- a/tests/expectations/tests/vtable_recursive_sig.rs
+++ b/tests/expectations/tests/vtable_recursive_sig.rs
@@ -23,9 +23,7 @@ impl Default for Derived {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
-#[derive(Default)]
-pub struct Base__bindgen_vtable {
-}
+pub struct Base__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Base {
diff --git a/tests/headers/generate-inline.hpp b/tests/headers/generate-inline.hpp
new file mode 100644
index 00000000..922ee1ca
--- /dev/null
+++ b/tests/headers/generate-inline.hpp
@@ -0,0 +1,12 @@
+// bindgen-flags: --generate-inline-functions
+
+class Foo {
+ public:
+ static inline int bar() {
+ return 42;
+ }
+};
+
+inline int foo() {
+ return 42;
+}
diff --git a/tests/tests.rs b/tests/tests.rs
index 6b69e0d4..84b5e076 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -3,7 +3,7 @@ extern crate diff;
extern crate bindgen;
extern crate shlex;
-use bindgen::Builder;
+use bindgen::{Builder, builder};
use std::fs;
use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write};
use std::path::PathBuf;
@@ -144,3 +144,19 @@ macro_rules! test_header {
// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
+
+#[test]
+fn test_header_contents() {
+ let bindings = builder()
+ .header_contents("test.h", "int foo(const char* a);")
+ .no_unstable_rust()
+ .generate()
+ .unwrap()
+ .to_string();
+ assert_eq!(bindings, "/* automatically generated by rust-bindgen */
+
+extern \"C\" {
+ pub fn foo(a: *const ::std::os::raw::c_schar) -> ::std::os::raw::c_int;
+}
+");
+}