summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Drysdale <drysdale@google.com>2021-11-29 13:03:26 +0000
committerEmilio Cobos Álvarez <emilio@crisal.io>2022-02-18 19:34:58 +0100
commite180d145a49b09c6d521cdc7989d1a1d4f173541 (patch)
treed871f3c94e3525dc198fbc1e21c76fd2e0dec247
parentddfa28f91f6db2580c2a09c90b06c02455a84229 (diff)
Add --allowlist-file option
-rw-r--r--book/src/allowlisting.md2
-rw-r--r--src/ir/context.rs20
-rw-r--r--src/ir/item.rs5
-rw-r--r--src/lib.rs12
-rw-r--r--src/options.rs14
-rw-r--r--tests/expectations/tests/allowlist-file.rs154
-rw-r--r--tests/headers/allowlist-file.hpp21
-rw-r--r--tests/headers/allowlisted/file.hpp22
8 files changed, 249 insertions, 1 deletions
diff --git a/book/src/allowlisting.md b/book/src/allowlisting.md
index 2e28d80f..edf93df0 100644
--- a/book/src/allowlisting.md
+++ b/book/src/allowlisting.md
@@ -19,12 +19,14 @@ transitively used by a definition that matches them.
* [`bindgen::Builder::allowlist_type`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_type)
* [`bindgen::Builder::allowlist_function`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_function)
* [`bindgen::Builder::allowlist_var`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_var)
+* [`bindgen::Builder::allowlist_file`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_file)
### Command Line
* `--allowlist-type <type>`
* `--allowlist-function <function>`
* `--allowlist-var <var>`
+* `--allowlist-file <path>`
### Annotations
diff --git a/src/ir/context.rs b/src/ir/context.rs
index b2e6f985..9afd16d6 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -2296,7 +2296,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
// game.
if self.options().allowlisted_types.is_empty() &&
self.options().allowlisted_functions.is_empty() &&
- self.options().allowlisted_vars.is_empty()
+ self.options().allowlisted_vars.is_empty() &&
+ self.options().allowlisted_files.is_empty()
{
return true;
}
@@ -2307,6 +2308,23 @@ If you encounter an error missing from this list, please file an issue or a PR!"
return true;
}
+ // Items with a source location in an explicitly allowlisted file
+ // are always included.
+ if !self.options().allowlisted_files.is_empty() {
+ if let Some(location) = item.location() {
+ let (file, _, _, _) = location.location();
+ if let Some(filename) = file.name() {
+ if self
+ .options()
+ .allowlisted_files
+ .matches(&filename)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
let name = item.path_for_allowlisting(self)[1..].join("::");
debug!("allowlisted_items: testing {:?}", name);
match *item.kind() {
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 8692575f..aed575ca 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -530,6 +530,11 @@ impl Item {
&mut self.kind
}
+ /// Where in the source is this item located?
+ pub fn location(&self) -> Option<&clang::SourceLocation> {
+ self.location.as_ref()
+ }
+
/// Get an identifier that differentiates this item from its siblings.
///
/// This should stay relatively stable in the face of code motion outside or
diff --git a/src/lib.rs b/src/lib.rs
index 39f55f04..ea5c61b4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -313,6 +313,7 @@ impl Builder {
(&self.options.allowlisted_functions, "--allowlist-function"),
(&self.options.allowlisted_types, "--allowlist-type"),
(&self.options.allowlisted_vars, "--allowlist-var"),
+ (&self.options.allowlisted_files, "--allowlist-file"),
(&self.options.no_partialeq_types, "--no-partialeq"),
(&self.options.no_copy_types, "--no-copy"),
(&self.options.no_debug_types, "--no-debug"),
@@ -908,6 +909,12 @@ impl Builder {
self
}
+ /// Allowlist the given file so that its contents appear in the generated bindings.
+ pub fn allowlist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.allowlisted_files.insert(arg);
+ self
+ }
+
/// Deprecated: use allowlist_var instead.
#[deprecated(note = "use allowlist_var instead")]
pub fn whitelist_var<T: AsRef<str>>(self, arg: T) -> Builder {
@@ -1705,6 +1712,9 @@ struct BindgenOptions {
/// Allowlisted variables. See docs for `allowlisted_types` for more.
allowlisted_vars: RegexSet,
+ /// The set of files whose contents should be allowlisted.
+ allowlisted_files: RegexSet,
+
/// The default style of code to generate for enums
default_enum_style: codegen::EnumVariation,
@@ -1984,6 +1994,7 @@ impl BindgenOptions {
&mut self.allowlisted_vars,
&mut self.allowlisted_types,
&mut self.allowlisted_functions,
+ &mut self.allowlisted_files,
&mut self.blocklisted_types,
&mut self.blocklisted_functions,
&mut self.blocklisted_items,
@@ -2042,6 +2053,7 @@ impl Default for BindgenOptions {
allowlisted_types: Default::default(),
allowlisted_functions: Default::default(),
allowlisted_vars: Default::default(),
+ allowlisted_files: Default::default(),
default_enum_style: Default::default(),
bitfield_enums: Default::default(),
newtype_enums: Default::default(),
diff --git a/src/options.rs b/src/options.rs
index 67bcda74..04d42ed5 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -418,6 +418,14 @@ where
.takes_value(true)
.multiple_occurrences(true)
.number_of_values(1),
+ Arg::new("allowlist-file")
+ .alias("allowlist-file")
+ .long("allowlist-file")
+ .help("Allowlist all contents of <path>.")
+ .value_name("path")
+ .takes_value(true)
+ .multiple_occurrences(true)
+ .number_of_values(1),
Arg::new("verbose")
.long("verbose")
.help("Print verbose error messages."),
@@ -871,6 +879,12 @@ where
}
}
+ if let Some(hidden_files) = matches.values_of("allowlist-file") {
+ for file in hidden_files {
+ builder = builder.allowlist_file(file);
+ }
+ }
+
if let Some(args) = matches.values_of("clang-args") {
for arg in args {
builder = builder.clang_arg(arg);
diff --git a/tests/expectations/tests/allowlist-file.rs b/tests/expectations/tests/allowlist-file.rs
new file mode 100644
index 00000000..2c2660a6
--- /dev/null
+++ b/tests/expectations/tests/allowlist-file.rs
@@ -0,0 +1,154 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+pub const SOME_DEFUN: u32 = 123;
+extern "C" {
+ #[link_name = "\u{1}_Z12SomeFunctionv"]
+ pub fn SomeFunction();
+}
+extern "C" {
+ pub static mut someVar: ::std::os::raw::c_int;
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct someClass {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_someClass() {
+ assert_eq!(
+ ::std::mem::size_of::<someClass>(),
+ 1usize,
+ concat!("Size of: ", stringify!(someClass))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<someClass>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(someClass))
+ );
+}
+extern "C" {
+ #[link_name = "\u{1}_ZN9someClass16somePublicMethodEi"]
+ pub fn someClass_somePublicMethod(
+ this: *mut someClass,
+ foo: ::std::os::raw::c_int,
+ );
+}
+impl someClass {
+ #[inline]
+ pub unsafe fn somePublicMethod(&mut self, foo: ::std::os::raw::c_int) {
+ someClass_somePublicMethod(self, foo)
+ }
+}
+extern "C" {
+ pub fn ExternFunction();
+}
+extern "C" {
+ #[link_name = "\u{1}_ZN3foo18NamespacedFunctionEv"]
+ pub fn foo_NamespacedFunction();
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct StructWithAllowlistedDefinition {
+ pub other: *mut StructWithAllowlistedFwdDecl,
+}
+#[test]
+fn bindgen_test_layout_StructWithAllowlistedDefinition() {
+ assert_eq!(
+ ::std::mem::size_of::<StructWithAllowlistedDefinition>(),
+ 8usize,
+ concat!("Size of: ", stringify!(StructWithAllowlistedDefinition))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<StructWithAllowlistedDefinition>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(StructWithAllowlistedDefinition))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<StructWithAllowlistedDefinition>())).other
+ as *const _ as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(StructWithAllowlistedDefinition),
+ "::",
+ stringify!(other)
+ )
+ );
+}
+impl Default for StructWithAllowlistedDefinition {
+ fn default() -> Self {
+ let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
+ unsafe {
+ ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct StructWithAllowlistedFwdDecl {
+ pub b: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_StructWithAllowlistedFwdDecl() {
+ assert_eq!(
+ ::std::mem::size_of::<StructWithAllowlistedFwdDecl>(),
+ 4usize,
+ concat!("Size of: ", stringify!(StructWithAllowlistedFwdDecl))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<StructWithAllowlistedFwdDecl>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(StructWithAllowlistedFwdDecl))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<StructWithAllowlistedFwdDecl>())).b
+ as *const _ as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(StructWithAllowlistedFwdDecl),
+ "::",
+ stringify!(b)
+ )
+ );
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct AllowlistMe {
+ pub foo: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_AllowlistMe() {
+ assert_eq!(
+ ::std::mem::size_of::<AllowlistMe>(),
+ 4usize,
+ concat!("Size of: ", stringify!(AllowlistMe))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<AllowlistMe>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(AllowlistMe))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<AllowlistMe>())).foo as *const _ as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(AllowlistMe),
+ "::",
+ stringify!(foo)
+ )
+ );
+}
diff --git a/tests/headers/allowlist-file.hpp b/tests/headers/allowlist-file.hpp
new file mode 100644
index 00000000..b0354a04
--- /dev/null
+++ b/tests/headers/allowlist-file.hpp
@@ -0,0 +1,21 @@
+// bindgen-flags: --allowlist-file ".*/allowlisted/file.*" --allowlist-type AllowlistMe -- -Itests/headers
+
+
+// Forward declaration of struct that's defined in an allowlisted file.
+struct StructWithAllowlistedDefinition;
+
+#include "allowlisted/file.hpp"
+
+// Actual definition of struct that has a forward declaration in an allowlisted file.
+struct StructWithAllowlistedFwdDecl {
+ int b;
+};
+
+class Ignored {
+ char c;
+};
+
+// Also have an explicitly allowlisted type
+class AllowlistMe {
+ int foo;
+};
diff --git a/tests/headers/allowlisted/file.hpp b/tests/headers/allowlisted/file.hpp
new file mode 100644
index 00000000..5f360e5e
--- /dev/null
+++ b/tests/headers/allowlisted/file.hpp
@@ -0,0 +1,22 @@
+void SomeFunction();
+extern int someVar;
+#define SOME_DEFUN 123
+
+class someClass {
+ void somePrivateMethod();
+public:
+ void somePublicMethod(int foo);
+};
+
+extern "C" void ExternFunction();
+
+namespace foo {
+ void NamespacedFunction();
+}
+
+
+struct StructWithAllowlistedFwdDecl;
+
+struct StructWithAllowlistedDefinition {
+ StructWithAllowlistedFwdDecl* other;
+};