Skip to content

Commit e180d14

Browse files
daviddrysdaleemilio
authored andcommitted
Add --allowlist-file option
1 parent ddfa28f commit e180d14

File tree

8 files changed

+249
-1
lines changed

8 files changed

+249
-1
lines changed

book/src/allowlisting.md

+2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ transitively used by a definition that matches them.
1919
* [`bindgen::Builder::allowlist_type`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_type)
2020
* [`bindgen::Builder::allowlist_function`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_function)
2121
* [`bindgen::Builder::allowlist_var`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_var)
22+
* [`bindgen::Builder::allowlist_file`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_file)
2223

2324
### Command Line
2425

2526
* `--allowlist-type <type>`
2627
* `--allowlist-function <function>`
2728
* `--allowlist-var <var>`
29+
* `--allowlist-file <path>`
2830

2931
### Annotations
3032

src/ir/context.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -2296,7 +2296,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
22962296
// game.
22972297
if self.options().allowlisted_types.is_empty() &&
22982298
self.options().allowlisted_functions.is_empty() &&
2299-
self.options().allowlisted_vars.is_empty()
2299+
self.options().allowlisted_vars.is_empty() &&
2300+
self.options().allowlisted_files.is_empty()
23002301
{
23012302
return true;
23022303
}
@@ -2307,6 +2308,23 @@ If you encounter an error missing from this list, please file an issue or a PR!"
23072308
return true;
23082309
}
23092310

2311+
// Items with a source location in an explicitly allowlisted file
2312+
// are always included.
2313+
if !self.options().allowlisted_files.is_empty() {
2314+
if let Some(location) = item.location() {
2315+
let (file, _, _, _) = location.location();
2316+
if let Some(filename) = file.name() {
2317+
if self
2318+
.options()
2319+
.allowlisted_files
2320+
.matches(&filename)
2321+
{
2322+
return true;
2323+
}
2324+
}
2325+
}
2326+
}
2327+
23102328
let name = item.path_for_allowlisting(self)[1..].join("::");
23112329
debug!("allowlisted_items: testing {:?}", name);
23122330
match *item.kind() {

src/ir/item.rs

+5
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,11 @@ impl Item {
530530
&mut self.kind
531531
}
532532

533+
/// Where in the source is this item located?
534+
pub fn location(&self) -> Option<&clang::SourceLocation> {
535+
self.location.as_ref()
536+
}
537+
533538
/// Get an identifier that differentiates this item from its siblings.
534539
///
535540
/// This should stay relatively stable in the face of code motion outside or

src/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ impl Builder {
313313
(&self.options.allowlisted_functions, "--allowlist-function"),
314314
(&self.options.allowlisted_types, "--allowlist-type"),
315315
(&self.options.allowlisted_vars, "--allowlist-var"),
316+
(&self.options.allowlisted_files, "--allowlist-file"),
316317
(&self.options.no_partialeq_types, "--no-partialeq"),
317318
(&self.options.no_copy_types, "--no-copy"),
318319
(&self.options.no_debug_types, "--no-debug"),
@@ -908,6 +909,12 @@ impl Builder {
908909
self
909910
}
910911

912+
/// Allowlist the given file so that its contents appear in the generated bindings.
913+
pub fn allowlist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
914+
self.options.allowlisted_files.insert(arg);
915+
self
916+
}
917+
911918
/// Deprecated: use allowlist_var instead.
912919
#[deprecated(note = "use allowlist_var instead")]
913920
pub fn whitelist_var<T: AsRef<str>>(self, arg: T) -> Builder {
@@ -1705,6 +1712,9 @@ struct BindgenOptions {
17051712
/// Allowlisted variables. See docs for `allowlisted_types` for more.
17061713
allowlisted_vars: RegexSet,
17071714

1715+
/// The set of files whose contents should be allowlisted.
1716+
allowlisted_files: RegexSet,
1717+
17081718
/// The default style of code to generate for enums
17091719
default_enum_style: codegen::EnumVariation,
17101720

@@ -1984,6 +1994,7 @@ impl BindgenOptions {
19841994
&mut self.allowlisted_vars,
19851995
&mut self.allowlisted_types,
19861996
&mut self.allowlisted_functions,
1997+
&mut self.allowlisted_files,
19871998
&mut self.blocklisted_types,
19881999
&mut self.blocklisted_functions,
19892000
&mut self.blocklisted_items,
@@ -2042,6 +2053,7 @@ impl Default for BindgenOptions {
20422053
allowlisted_types: Default::default(),
20432054
allowlisted_functions: Default::default(),
20442055
allowlisted_vars: Default::default(),
2056+
allowlisted_files: Default::default(),
20452057
default_enum_style: Default::default(),
20462058
bitfield_enums: Default::default(),
20472059
newtype_enums: Default::default(),

src/options.rs

+14
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,14 @@ where
418418
.takes_value(true)
419419
.multiple_occurrences(true)
420420
.number_of_values(1),
421+
Arg::new("allowlist-file")
422+
.alias("allowlist-file")
423+
.long("allowlist-file")
424+
.help("Allowlist all contents of <path>.")
425+
.value_name("path")
426+
.takes_value(true)
427+
.multiple_occurrences(true)
428+
.number_of_values(1),
421429
Arg::new("verbose")
422430
.long("verbose")
423431
.help("Print verbose error messages."),
@@ -871,6 +879,12 @@ where
871879
}
872880
}
873881

882+
if let Some(hidden_files) = matches.values_of("allowlist-file") {
883+
for file in hidden_files {
884+
builder = builder.allowlist_file(file);
885+
}
886+
}
887+
874888
if let Some(args) = matches.values_of("clang-args") {
875889
for arg in args {
876890
builder = builder.clang_arg(arg);
+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#![allow(
2+
dead_code,
3+
non_snake_case,
4+
non_camel_case_types,
5+
non_upper_case_globals
6+
)]
7+
8+
pub const SOME_DEFUN: u32 = 123;
9+
extern "C" {
10+
#[link_name = "\u{1}_Z12SomeFunctionv"]
11+
pub fn SomeFunction();
12+
}
13+
extern "C" {
14+
pub static mut someVar: ::std::os::raw::c_int;
15+
}
16+
#[repr(C)]
17+
#[derive(Debug, Default, Copy, Clone)]
18+
pub struct someClass {
19+
pub _address: u8,
20+
}
21+
#[test]
22+
fn bindgen_test_layout_someClass() {
23+
assert_eq!(
24+
::std::mem::size_of::<someClass>(),
25+
1usize,
26+
concat!("Size of: ", stringify!(someClass))
27+
);
28+
assert_eq!(
29+
::std::mem::align_of::<someClass>(),
30+
1usize,
31+
concat!("Alignment of ", stringify!(someClass))
32+
);
33+
}
34+
extern "C" {
35+
#[link_name = "\u{1}_ZN9someClass16somePublicMethodEi"]
36+
pub fn someClass_somePublicMethod(
37+
this: *mut someClass,
38+
foo: ::std::os::raw::c_int,
39+
);
40+
}
41+
impl someClass {
42+
#[inline]
43+
pub unsafe fn somePublicMethod(&mut self, foo: ::std::os::raw::c_int) {
44+
someClass_somePublicMethod(self, foo)
45+
}
46+
}
47+
extern "C" {
48+
pub fn ExternFunction();
49+
}
50+
extern "C" {
51+
#[link_name = "\u{1}_ZN3foo18NamespacedFunctionEv"]
52+
pub fn foo_NamespacedFunction();
53+
}
54+
#[repr(C)]
55+
#[derive(Debug, Copy, Clone)]
56+
pub struct StructWithAllowlistedDefinition {
57+
pub other: *mut StructWithAllowlistedFwdDecl,
58+
}
59+
#[test]
60+
fn bindgen_test_layout_StructWithAllowlistedDefinition() {
61+
assert_eq!(
62+
::std::mem::size_of::<StructWithAllowlistedDefinition>(),
63+
8usize,
64+
concat!("Size of: ", stringify!(StructWithAllowlistedDefinition))
65+
);
66+
assert_eq!(
67+
::std::mem::align_of::<StructWithAllowlistedDefinition>(),
68+
8usize,
69+
concat!("Alignment of ", stringify!(StructWithAllowlistedDefinition))
70+
);
71+
assert_eq!(
72+
unsafe {
73+
&(*(::std::ptr::null::<StructWithAllowlistedDefinition>())).other
74+
as *const _ as usize
75+
},
76+
0usize,
77+
concat!(
78+
"Offset of field: ",
79+
stringify!(StructWithAllowlistedDefinition),
80+
"::",
81+
stringify!(other)
82+
)
83+
);
84+
}
85+
impl Default for StructWithAllowlistedDefinition {
86+
fn default() -> Self {
87+
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
88+
unsafe {
89+
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
90+
s.assume_init()
91+
}
92+
}
93+
}
94+
#[repr(C)]
95+
#[derive(Debug, Default, Copy, Clone)]
96+
pub struct StructWithAllowlistedFwdDecl {
97+
pub b: ::std::os::raw::c_int,
98+
}
99+
#[test]
100+
fn bindgen_test_layout_StructWithAllowlistedFwdDecl() {
101+
assert_eq!(
102+
::std::mem::size_of::<StructWithAllowlistedFwdDecl>(),
103+
4usize,
104+
concat!("Size of: ", stringify!(StructWithAllowlistedFwdDecl))
105+
);
106+
assert_eq!(
107+
::std::mem::align_of::<StructWithAllowlistedFwdDecl>(),
108+
4usize,
109+
concat!("Alignment of ", stringify!(StructWithAllowlistedFwdDecl))
110+
);
111+
assert_eq!(
112+
unsafe {
113+
&(*(::std::ptr::null::<StructWithAllowlistedFwdDecl>())).b
114+
as *const _ as usize
115+
},
116+
0usize,
117+
concat!(
118+
"Offset of field: ",
119+
stringify!(StructWithAllowlistedFwdDecl),
120+
"::",
121+
stringify!(b)
122+
)
123+
);
124+
}
125+
#[repr(C)]
126+
#[derive(Debug, Default, Copy, Clone)]
127+
pub struct AllowlistMe {
128+
pub foo: ::std::os::raw::c_int,
129+
}
130+
#[test]
131+
fn bindgen_test_layout_AllowlistMe() {
132+
assert_eq!(
133+
::std::mem::size_of::<AllowlistMe>(),
134+
4usize,
135+
concat!("Size of: ", stringify!(AllowlistMe))
136+
);
137+
assert_eq!(
138+
::std::mem::align_of::<AllowlistMe>(),
139+
4usize,
140+
concat!("Alignment of ", stringify!(AllowlistMe))
141+
);
142+
assert_eq!(
143+
unsafe {
144+
&(*(::std::ptr::null::<AllowlistMe>())).foo as *const _ as usize
145+
},
146+
0usize,
147+
concat!(
148+
"Offset of field: ",
149+
stringify!(AllowlistMe),
150+
"::",
151+
stringify!(foo)
152+
)
153+
);
154+
}

tests/headers/allowlist-file.hpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// bindgen-flags: --allowlist-file ".*/allowlisted/file.*" --allowlist-type AllowlistMe -- -Itests/headers
2+
3+
4+
// Forward declaration of struct that's defined in an allowlisted file.
5+
struct StructWithAllowlistedDefinition;
6+
7+
#include "allowlisted/file.hpp"
8+
9+
// Actual definition of struct that has a forward declaration in an allowlisted file.
10+
struct StructWithAllowlistedFwdDecl {
11+
int b;
12+
};
13+
14+
class Ignored {
15+
char c;
16+
};
17+
18+
// Also have an explicitly allowlisted type
19+
class AllowlistMe {
20+
int foo;
21+
};

tests/headers/allowlisted/file.hpp

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
void SomeFunction();
2+
extern int someVar;
3+
#define SOME_DEFUN 123
4+
5+
class someClass {
6+
void somePrivateMethod();
7+
public:
8+
void somePublicMethod(int foo);
9+
};
10+
11+
extern "C" void ExternFunction();
12+
13+
namespace foo {
14+
void NamespacedFunction();
15+
}
16+
17+
18+
struct StructWithAllowlistedFwdDecl;
19+
20+
struct StructWithAllowlistedDefinition {
21+
StructWithAllowlistedFwdDecl* other;
22+
};

0 commit comments

Comments
 (0)