aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Maurer <mmaurer@google.com>2023-06-28 21:15:44 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-06-28 21:15:44 +0000
commitdff14bfb1eb52af0bc812483a760e2be896ccaf7 (patch)
treec6735723e0c4e0a71c5472143c03b23e5330993f
parentf0884fc0c4a525619e0d0ca0a697d7555b49de6b (diff)
parenta15fc56dc17e5bf7af8c3414dbeaad91b3d40a2b (diff)
downloadbindgen-dff14bfb1eb52af0bc812483a760e2be896ccaf7.tar.gz
Update to 0.65.1 am: 0c91f92a37 am: a12b261650 am: a15fc56dc1
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/bindgen/+/2624796 Change-Id: I551bf31d4918b4175313b6b33895f2273ee17e6b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp9
-rw-r--r--Cargo.toml19
-rw-r--r--Cargo.toml.orig13
-rw-r--r--METADATA8
-rw-r--r--callbacks.rs17
-rw-r--r--cargo2android.json2
-rw-r--r--clang.rs326
-rw-r--r--codegen/dyngen.rs6
-rw-r--r--codegen/error.rs4
-rw-r--r--codegen/helpers.rs59
-rw-r--r--codegen/impl_debug.rs4
-rw-r--r--codegen/impl_partialeq.rs4
-rw-r--r--codegen/mod.rs482
-rw-r--r--codegen/postprocessing/merge_extern_blocks.rs100
-rw-r--r--codegen/postprocessing/mod.rs27
-rw-r--r--codegen/postprocessing/sort_semantically.rs55
-rw-r--r--codegen/serialize.rs68
-rw-r--r--codegen/struct_layout.rs28
-rw-r--r--diagnostics.rs189
-rw-r--r--features.rs10
-rw-r--r--ir/analysis/derive.rs10
-rw-r--r--ir/analysis/has_destructor.rs2
-rw-r--r--ir/analysis/has_float.rs2
-rw-r--r--ir/analysis/has_type_param_in_array.rs2
-rw-r--r--ir/analysis/has_vtable.rs8
-rw-r--r--ir/analysis/mod.rs27
-rw-r--r--ir/analysis/sizedness.rs12
-rw-r--r--ir/analysis/template_params.rs8
-rw-r--r--ir/annotations.rs93
-rw-r--r--ir/comment.rs2
-rw-r--r--ir/comp.rs133
-rw-r--r--ir/context.rs298
-rw-r--r--ir/derive.rs18
-rw-r--r--ir/dot.rs4
-rw-r--r--ir/enum_ty.rs31
-rw-r--r--ir/function.rs104
-rw-r--r--ir/int.rs8
-rw-r--r--ir/item.rs159
-rw-r--r--ir/item_kind.rs38
-rw-r--r--ir/layout.rs39
-rw-r--r--ir/mod.rs39
-rw-r--r--ir/module.rs14
-rw-r--r--ir/objc.rs43
-rw-r--r--ir/template.rs46
-rw-r--r--ir/traversal.rs31
-rw-r--r--ir/ty.rs93
-rw-r--r--ir/var.rs87
-rw-r--r--lib.rs2279
-rw-r--r--options/as_args.rs52
-rw-r--r--options/helpers.rs43
-rw-r--r--options/mod.rs2008
-rw-r--r--parse.rs7
-rw-r--r--regex_set.rs117
54 files changed, 4162 insertions, 3127 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 32c33e6..820d6ff 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "ae6817256ac557981906e93a1f866349db85053e"
+ "sha1": "7d243056d335fdc4537f7bca73c06d01aae24ddc"
},
"path_in_vcs": "bindgen"
} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 86a6c71..0f0d867 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,26 +42,29 @@ rust_library_host {
name: "libbindgen",
crate_name: "bindgen",
cargo_env_compat: true,
- cargo_pkg_version: "0.64.0",
+ cargo_pkg_version: "0.65.1",
srcs: [
"lib.rs",
":copy_bindgen_build_out",
],
edition: "2018",
features: [
- "cli",
+ "__cli",
+ "annotate-snippets",
"experimental",
"runtime",
"which",
"which-rustfmt",
],
rustlibs: [
- "libbitflags-1.3.2",
+ "libannotate_snippets",
+ "libbitflags",
"libcexpr",
"libclang_sys",
"liblazy_static",
"liblazycell",
"libpeeking_take_while",
+ "libprettyplease",
"libproc_macro2",
"libquote",
"libregex",
diff --git a/Cargo.toml b/Cargo.toml
index a0119c4..facd25a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.60.0"
name = "bindgen"
-version = "0.64.0"
+version = "0.65.1"
authors = [
"Jyun-Yan You <jyyou.tw@gmail.com>",
"Emilio Cobos Álvarez <emilio@crisal.io>",
@@ -39,7 +39,12 @@ repository = "https://github.com/rust-lang/rust-bindgen"
[lib]
name = "bindgen"
-path = "./lib.rs"
+path = "lib.rs"
+
+[dependencies.annotate-snippets]
+version = "0.9.1"
+features = ["color"]
+optional = true
[dependencies.bitflags]
version = "1.0.3"
@@ -64,6 +69,9 @@ optional = true
[dependencies.peeking_take_while]
version = "0.1.2"
+[dependencies.prettyplease]
+version = "0.2.0"
+
[dependencies.proc-macro2]
version = "1"
default-features = false
@@ -87,7 +95,7 @@ version = "1.0.1"
version = "1"
[dependencies.syn]
-version = "2"
+version = "2.0"
features = [
"full",
"extra-traits",
@@ -100,17 +108,16 @@ optional = true
default-features = false
[features]
-cli = []
+__cli = []
default = [
"logging",
"runtime",
"which-rustfmt",
]
-experimental = []
+experimental = ["annotate-snippets"]
logging = ["log"]
runtime = ["clang-sys/runtime"]
static = ["clang-sys/static"]
-testing_only_docs = []
testing_only_extra_assertions = []
testing_only_libclang_5 = []
testing_only_libclang_9 = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index bc53be5..838524f 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -14,7 +14,7 @@ readme = "../README.md"
repository = "https://github.com/rust-lang/rust-bindgen"
documentation = "https://docs.rs/bindgen"
homepage = "https://rust-lang.github.io/rust-bindgen/"
-version = "0.64.0"
+version = "0.65.1"
edition = "2018"
build = "build.rs"
# If you change this, also update README.md and msrv in .github/workflows/bindgen.yml
@@ -22,7 +22,7 @@ rust-version = "1.60.0"
[lib]
name = "bindgen"
-path = "./lib.rs"
+path = "lib.rs"
[dependencies]
bitflags = "1.0.3"
@@ -32,9 +32,11 @@ lazycell = "1"
lazy_static = "1"
peeking_take_while = "0.1.2"
quote = { version = "1", default-features = false }
-syn = { version = "1.0.99", features = ["full", "extra-traits", "visit-mut"]}
+syn = { version = "2.0", features = ["full", "extra-traits", "visit-mut"]}
regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
which = { version = "4.2.1", optional = true, default-features = false }
+prettyplease = { version = "0.2.0" }
+annotate-snippets = { version = "0.9.1", features = ["color"], optional = true }
shlex = "1"
rustc-hash = "1.0.1"
proc-macro2 = { version = "1", default-features = false }
@@ -47,12 +49,11 @@ static = ["clang-sys/static"]
runtime = ["clang-sys/runtime"]
# Dynamically discover a `rustfmt` binary using the `which` crate
which-rustfmt = ["which"]
-cli = []
-experimental = []
+__cli = []
+experimental = ["annotate-snippets"]
# These features only exist for CI testing -- don't use them if you're not hacking
# on bindgen!
-testing_only_docs = []
testing_only_extra_assertions = []
testing_only_libclang_9 = []
testing_only_libclang_5 = []
diff --git a/METADATA b/METADATA
index c038164..3a8c1e8 100644
--- a/METADATA
+++ b/METADATA
@@ -11,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/bindgen/bindgen-0.64.0.crate"
+ value: "https://static.crates.io/crates/bindgen/bindgen-0.65.1.crate"
}
- version: "0.64.0"
+ version: "0.65.1"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 2
- day: 16
+ month: 6
+ day: 9
}
}
diff --git a/callbacks.rs b/callbacks.rs
index dc20e25..5824466 100644
--- a/callbacks.rs
+++ b/callbacks.rs
@@ -25,7 +25,7 @@ impl Default for MacroParsingBehavior {
/// A trait to allow configuring different kinds of types in different
/// situations.
pub trait ParseCallbacks: fmt::Debug {
- #[cfg(feature = "cli")]
+ #[cfg(feature = "__cli")]
#[doc(hidden)]
fn cli_args(&self) -> Vec<String> {
vec![]
@@ -45,6 +45,15 @@ pub trait ParseCallbacks: fmt::Debug {
None
}
+ /// This function will run for every extern variable and function. The returned value determines
+ /// the link name in the bindings.
+ fn generated_link_name_override(
+ &self,
+ _item_info: ItemInfo<'_>,
+ ) -> Option<String> {
+ None
+ }
+
/// The integer kind an integer macro should have, given a name and the
/// value of that macro, or `None` if you want the default to be chosen.
fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> {
@@ -93,6 +102,10 @@ pub trait ParseCallbacks: fmt::Debug {
/// This will be called on every file inclusion, with the full path of the included file.
fn include_file(&self, _filename: &str) {}
+ /// This will be called every time `bindgen` reads an environment variable whether it has any
+ /// content or not.
+ fn read_env_var(&self, _key: &str) {}
+
/// This will be called to determine whether a particular blocklisted type
/// implements a trait or not. This will be used to implement traits on
/// other types containing the blocklisted type.
@@ -146,7 +159,7 @@ pub enum TypeKind {
Union,
}
-/// An struct providing information about the item being passed to `ParseCallbacks::generated_name_override`.
+/// A struct providing information about the item being passed to [`ParseCallbacks::generated_name_override`].
#[non_exhaustive]
pub struct ItemInfo<'a> {
/// The name of the item
diff --git a/cargo2android.json b/cargo2android.json
index fd62b50..ea1fdc2 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,6 +1,6 @@
{
"copy-out": true,
- "features": "cli,experimental,runtime,which-rustfmt",
+ "features": "__cli,experimental,runtime,which-rustfmt",
"host-first-multilib": true,
"run": true
}
diff --git a/clang.rs b/clang.rs
index 32a2544..0060213 100644
--- a/clang.rs
+++ b/clang.rs
@@ -2,6 +2,7 @@
//! `clang_sys` module.
#![allow(non_upper_case_globals, dead_code)]
+#![deny(clippy::missing_docs_in_private_items)]
use crate::ir::context::BindgenContext;
use clang_sys::*;
@@ -16,7 +17,7 @@ use std::{mem, ptr, slice};
///
/// Values of this type can be used to check for different attributes using the `has_attrs`
/// function.
-pub struct Attribute {
+pub(crate) struct Attribute {
name: &'static [u8],
kind: Option<CXCursorKind>,
token_kind: CXTokenKind,
@@ -24,7 +25,7 @@ pub struct Attribute {
impl Attribute {
/// A `warn_unused_result` attribute.
- pub const MUST_USE: Self = Self {
+ pub(crate) const MUST_USE: Self = Self {
name: b"warn_unused_result",
// FIXME(emilio): clang-sys doesn't expose `CXCursor_WarnUnusedResultAttr` (from clang 9).
kind: Some(440),
@@ -32,14 +33,14 @@ impl Attribute {
};
/// A `_Noreturn` attribute.
- pub const NO_RETURN: Self = Self {
+ pub(crate) const NO_RETURN: Self = Self {
name: b"_Noreturn",
kind: None,
token_kind: CXToken_Keyword,
};
/// A `[[noreturn]]` attribute.
- pub const NO_RETURN_CPP: Self = Self {
+ pub(crate) const NO_RETURN_CPP: Self = Self {
name: b"noreturn",
kind: None,
token_kind: CXToken_Identifier,
@@ -50,7 +51,7 @@ impl Attribute {
///
/// We call the AST node pointed to by the cursor the cursor's "referent".
#[derive(Copy, Clone)]
-pub struct Cursor {
+pub(crate) struct Cursor {
x: CXCursor,
}
@@ -72,7 +73,7 @@ impl Cursor {
/// available.
///
/// The USR can be used to compare entities across translation units.
- pub fn usr(&self) -> Option<String> {
+ pub(crate) fn usr(&self) -> Option<String> {
let s = unsafe { cxstring_into_string(clang_getCursorUSR(self.x)) };
if s.is_empty() {
None
@@ -82,17 +83,17 @@ impl Cursor {
}
/// Is this cursor's referent a declaration?
- pub fn is_declaration(&self) -> bool {
+ pub(crate) fn is_declaration(&self) -> bool {
unsafe { clang_isDeclaration(self.kind()) != 0 }
}
/// Is this cursor's referent an anonymous record or so?
- pub fn is_anonymous(&self) -> bool {
+ pub(crate) fn is_anonymous(&self) -> bool {
unsafe { clang_Cursor_isAnonymous(self.x) != 0 }
}
/// Get this cursor's referent's spelling.
- pub fn spelling(&self) -> String {
+ pub(crate) fn spelling(&self) -> String {
unsafe { cxstring_into_string(clang_getCursorSpelling(self.x)) }
}
@@ -100,18 +101,18 @@ impl Cursor {
///
/// This is not necessarily a valid identifier. It includes extra
/// information, such as parameters for a function, etc.
- pub fn display_name(&self) -> String {
+ pub(crate) fn display_name(&self) -> String {
unsafe { cxstring_into_string(clang_getCursorDisplayName(self.x)) }
}
/// Get the mangled name of this cursor's referent.
- pub fn mangling(&self) -> String {
+ pub(crate) fn mangling(&self) -> String {
unsafe { cxstring_into_string(clang_Cursor_getMangling(self.x)) }
}
/// Gets the C++ manglings for this cursor, or an error if the manglings
/// are not available.
- pub fn cxx_manglings(&self) -> Result<Vec<String>, ()> {
+ pub(crate) fn cxx_manglings(&self) -> Result<Vec<String>, ()> {
use clang_sys::*;
unsafe {
let manglings = clang_Cursor_getCXXManglings(self.x);
@@ -131,7 +132,7 @@ impl Cursor {
}
/// Returns whether the cursor refers to a built-in definition.
- pub fn is_builtin(&self) -> bool {
+ pub(crate) fn is_builtin(&self) -> bool {
let (file, _, _, _) = self.location().location();
file.name().is_none()
}
@@ -153,7 +154,7 @@ impl Cursor {
///
/// void Foo::method() { /* ... */ }
/// ```
- pub fn lexical_parent(&self) -> Cursor {
+ pub(crate) fn lexical_parent(&self) -> Cursor {
unsafe {
Cursor {
x: clang_getCursorLexicalParent(self.x),
@@ -165,7 +166,7 @@ impl Cursor {
///
/// See documentation for `lexical_parent` for details on semantic vs
/// lexical parents.
- pub fn fallible_semantic_parent(&self) -> Option<Cursor> {
+ pub(crate) fn fallible_semantic_parent(&self) -> Option<Cursor> {
let sp = unsafe {
Cursor {
x: clang_getCursorSemanticParent(self.x),
@@ -181,7 +182,7 @@ impl Cursor {
///
/// See documentation for `lexical_parent` for details on semantic vs
/// lexical parents.
- pub fn semantic_parent(&self) -> Cursor {
+ pub(crate) fn semantic_parent(&self) -> Cursor {
self.fallible_semantic_parent().unwrap()
}
@@ -191,7 +192,7 @@ impl Cursor {
///
/// NOTE: This may not return `Some` for partial template specializations,
/// see #193 and #194.
- pub fn num_template_args(&self) -> Option<u32> {
+ pub(crate) fn num_template_args(&self) -> Option<u32> {
// XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while
// `clang_Cursor_getNumTemplateArguments` is totally unreliable.
// Therefore, try former first, and only fallback to the latter if we
@@ -225,7 +226,7 @@ impl Cursor {
/// bindgen assumes there will only be one of them alive at a time, and
/// disposes it on drop. That can change if this would be required, but I
/// think we can survive fine without it.
- pub fn translation_unit(&self) -> Cursor {
+ pub(crate) fn translation_unit(&self) -> Cursor {
assert!(self.is_valid());
unsafe {
let tu = clang_Cursor_getTranslationUnit(self.x);
@@ -238,7 +239,7 @@ impl Cursor {
}
/// Is the referent a top level construct?
- pub fn is_toplevel(&self) -> bool {
+ pub(crate) fn is_toplevel(&self) -> bool {
let mut semantic_parent = self.fallible_semantic_parent();
while semantic_parent.is_some() &&
@@ -259,7 +260,7 @@ impl Cursor {
/// There are a few kinds of types that we need to treat specially, mainly
/// not tracking the type declaration but the location of the cursor, given
/// clang doesn't expose a proper declaration for these types.
- pub fn is_template_like(&self) -> bool {
+ pub(crate) fn is_template_like(&self) -> bool {
matches!(
self.kind(),
CXCursor_ClassTemplate |
@@ -269,28 +270,28 @@ impl Cursor {
}
/// Is this Cursor pointing to a function-like macro definition?
- pub fn is_macro_function_like(&self) -> bool {
+ pub(crate) fn is_macro_function_like(&self) -> bool {
unsafe { clang_Cursor_isMacroFunctionLike(self.x) != 0 }
}
/// Get the kind of referent this cursor is pointing to.
- pub fn kind(&self) -> CXCursorKind {
+ pub(crate) fn kind(&self) -> CXCursorKind {
self.x.kind
}
/// Returns true if the cursor is a definition
- pub fn is_definition(&self) -> bool {
+ pub(crate) fn is_definition(&self) -> bool {
unsafe { clang_isCursorDefinition(self.x) != 0 }
}
/// Is the referent a template specialization?
- pub fn is_template_specialization(&self) -> bool {
+ pub(crate) fn is_template_specialization(&self) -> bool {
self.specialized().is_some()
}
/// Is the referent a fully specialized template specialization without any
/// remaining free template arguments?
- pub fn is_fully_specialized_template(&self) -> bool {
+ pub(crate) fn is_fully_specialized_template(&self) -> bool {
self.is_template_specialization() &&
self.kind() != CXCursor_ClassTemplatePartialSpecialization &&
self.num_template_args().unwrap_or(0) > 0
@@ -298,7 +299,7 @@ impl Cursor {
/// Is the referent a template specialization that still has remaining free
/// template arguments?
- pub fn is_in_non_fully_specialized_template(&self) -> bool {
+ pub(crate) fn is_in_non_fully_specialized_template(&self) -> bool {
if self.is_toplevel() {
return false;
}
@@ -316,7 +317,7 @@ impl Cursor {
}
/// Is the referent any kind of template parameter?
- pub fn is_template_parameter(&self) -> bool {
+ pub(crate) fn is_template_parameter(&self) -> bool {
matches!(
self.kind(),
CXCursor_TemplateTemplateParameter |
@@ -326,7 +327,7 @@ impl Cursor {
}
/// Does the referent's type or value depend on a template parameter?
- pub fn is_dependent_on_template_parameter(&self) -> bool {
+ pub(crate) fn is_dependent_on_template_parameter(&self) -> bool {
fn visitor(
found_template_parameter: &mut bool,
cur: Cursor,
@@ -366,12 +367,12 @@ impl Cursor {
}
/// Is this cursor pointing a valid referent?
- pub fn is_valid(&self) -> bool {
+ pub(crate) fn is_valid(&self) -> bool {
unsafe { clang_isInvalid(self.kind()) == 0 }
}
/// Get the source location for the referent.
- pub fn location(&self) -> SourceLocation {
+ pub(crate) fn location(&self) -> SourceLocation {
unsafe {
SourceLocation {
x: clang_getCursorLocation(self.x),
@@ -380,12 +381,12 @@ impl Cursor {
}
/// Get the source location range for the referent.
- pub fn extent(&self) -> CXSourceRange {
+ pub(crate) fn extent(&self) -> CXSourceRange {
unsafe { clang_getCursorExtent(self.x) }
}
/// Get the raw declaration comment for this referent, if one exists.
- pub fn raw_comment(&self) -> Option<String> {
+ pub(crate) fn raw_comment(&self) -> Option<String> {
let s = unsafe {
cxstring_into_string(clang_Cursor_getRawCommentText(self.x))
};
@@ -397,7 +398,7 @@ impl Cursor {
}
/// Get the referent's parsed comment.
- pub fn comment(&self) -> Comment {
+ pub(crate) fn comment(&self) -> Comment {
unsafe {
Comment {
x: clang_Cursor_getParsedComment(self.x),
@@ -406,7 +407,7 @@ impl Cursor {
}
/// Get the referent's type.
- pub fn cur_type(&self) -> Type {
+ pub(crate) fn cur_type(&self) -> Type {
unsafe {
Type {
x: clang_getCursorType(self.x),
@@ -417,7 +418,7 @@ impl Cursor {
/// Given that this cursor's referent is a reference to another type, or is
/// a declaration, get the cursor pointing to the referenced type or type of
/// the declared thing.
- pub fn definition(&self) -> Option<Cursor> {
+ pub(crate) fn definition(&self) -> Option<Cursor> {
unsafe {
let ret = Cursor {
x: clang_getCursorDefinition(self.x),
@@ -433,7 +434,7 @@ impl Cursor {
/// Given that this cursor's referent is reference type, get the cursor
/// pointing to the referenced type.
- pub fn referenced(&self) -> Option<Cursor> {
+ pub(crate) fn referenced(&self) -> Option<Cursor> {
unsafe {
let ret = Cursor {
x: clang_getCursorReferenced(self.x),
@@ -452,7 +453,7 @@ impl Cursor {
/// Many types can be declared multiple times before finally being properly
/// defined. This method allows us to get the canonical cursor for the
/// referent type.
- pub fn canonical(&self) -> Cursor {
+ pub(crate) fn canonical(&self) -> Cursor {
unsafe {
Cursor {
x: clang_getCanonicalCursor(self.x),
@@ -463,7 +464,7 @@ impl Cursor {
/// Given that this cursor points to either a template specialization or a
/// template instantiation, get a cursor pointing to the template definition
/// that is being specialized.
- pub fn specialized(&self) -> Option<Cursor> {
+ pub(crate) fn specialized(&self) -> Option<Cursor> {
unsafe {
let ret = Cursor {
x: clang_getSpecializedCursorTemplate(self.x),
@@ -478,14 +479,14 @@ impl Cursor {
/// Assuming that this cursor's referent is a template declaration, get the
/// kind of cursor that would be generated for its specializations.
- pub fn template_kind(&self) -> CXCursorKind {
+ pub(crate) fn template_kind(&self) -> CXCursorKind {
unsafe { clang_getTemplateCursorKind(self.x) }
}
/// Traverse this cursor's referent and its children.
///
/// Call the given function on each AST node traversed.
- pub fn visit<Visitor>(&self, mut visitor: Visitor)
+ pub(crate) fn visit<Visitor>(&self, mut visitor: Visitor)
where
Visitor: FnMut(Cursor) -> CXChildVisitResult,
{
@@ -496,7 +497,7 @@ impl Cursor {
}
/// Collect all of this cursor's children into a vec and return them.
- pub fn collect_children(&self) -> Vec<Cursor> {
+ pub(crate) fn collect_children(&self) -> Vec<Cursor> {
let mut children = vec![];
self.visit(|c| {
children.push(c);
@@ -506,7 +507,7 @@ impl Cursor {
}
/// Does this cursor have any children?
- pub fn has_children(&self) -> bool {
+ pub(crate) fn has_children(&self) -> bool {
let mut has_children = false;
self.visit(|_| {
has_children = true;
@@ -516,7 +517,7 @@ impl Cursor {
}
/// Does this cursor have at least `n` children?
- pub fn has_at_least_num_children(&self, n: usize) -> bool {
+ pub(crate) fn has_at_least_num_children(&self, n: usize) -> bool {
assert!(n > 0);
let mut num_left = n;
self.visit(|_| {
@@ -533,7 +534,7 @@ impl Cursor {
/// Returns whether the given location contains a cursor with the given
/// kind in the first level of nesting underneath (doesn't look
/// recursively).
- pub fn contains_cursor(&self, kind: CXCursorKind) -> bool {
+ pub(crate) fn contains_cursor(&self, kind: CXCursorKind) -> bool {
let mut found = false;
self.visit(|c| {
@@ -549,17 +550,17 @@ impl Cursor {
}
/// Is the referent an inlined function?
- pub fn is_inlined_function(&self) -> bool {
+ pub(crate) fn is_inlined_function(&self) -> bool {
unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 }
}
/// Is the referent a defaulted function?
- pub fn is_defaulted_function(&self) -> bool {
+ pub(crate) fn is_defaulted_function(&self) -> bool {
unsafe { clang_CXXMethod_isDefaulted(self.x) != 0 }
}
/// Is the referent a deleted function?
- pub fn is_deleted_function(&self) -> bool {
+ pub(crate) fn is_deleted_function(&self) -> bool {
// Unfortunately, libclang doesn't yet have an API for checking if a
// member function is deleted, but the following should be a good
// enough approximation.
@@ -575,13 +576,13 @@ impl Cursor {
}
/// Is the referent a bit field declaration?
- pub fn is_bit_field(&self) -> bool {
+ pub(crate) fn is_bit_field(&self) -> bool {
unsafe { clang_Cursor_isBitField(self.x) != 0 }
}
/// Get a cursor to the bit field's width expression, or `None` if it's not
/// a bit field.
- pub fn bit_width_expr(&self) -> Option<Cursor> {
+ pub(crate) fn bit_width_expr(&self) -> Option<Cursor> {
if !self.is_bit_field() {
return None;
}
@@ -605,7 +606,7 @@ impl Cursor {
/// Get the width of this cursor's referent bit field, or `None` if the
/// referent is not a bit field or if the width could not be evaluated.
- pub fn bit_width(&self) -> Option<u32> {
+ pub(crate) fn bit_width(&self) -> Option<u32> {
// It is not safe to check the bit width without ensuring it doesn't
// depend on a template parameter. See
// https://github.com/rust-lang/rust-bindgen/issues/2239
@@ -625,7 +626,7 @@ impl Cursor {
/// Get the integer representation type used to hold this cursor's referent
/// enum type.
- pub fn enum_type(&self) -> Option<Type> {
+ pub(crate) fn enum_type(&self) -> Option<Type> {
unsafe {
let t = Type {
x: clang_getEnumDeclIntegerType(self.x),
@@ -641,7 +642,7 @@ impl Cursor {
/// Get the boolean constant value for this cursor's enum variant referent.
///
/// Returns None if the cursor's referent is not an enum variant.
- pub fn enum_val_boolean(&self) -> Option<bool> {
+ pub(crate) fn enum_val_boolean(&self) -> Option<bool> {
unsafe {
if self.kind() == CXCursor_EnumConstantDecl {
Some(clang_getEnumConstantDeclValue(self.x) != 0)
@@ -654,7 +655,7 @@ impl Cursor {
/// Get the signed constant value for this cursor's enum variant referent.
///
/// Returns None if the cursor's referent is not an enum variant.
- pub fn enum_val_signed(&self) -> Option<i64> {
+ pub(crate) fn enum_val_signed(&self) -> Option<i64> {
unsafe {
if self.kind() == CXCursor_EnumConstantDecl {
#[allow(clippy::unnecessary_cast)]
@@ -668,7 +669,7 @@ impl Cursor {
/// Get the unsigned constant value for this cursor's enum variant referent.
///
/// Returns None if the cursor's referent is not an enum variant.
- pub fn enum_val_unsigned(&self) -> Option<u64> {
+ pub(crate) fn enum_val_unsigned(&self) -> Option<u64> {
unsafe {
if self.kind() == CXCursor_EnumConstantDecl {
#[allow(clippy::unnecessary_cast)]
@@ -680,7 +681,7 @@ impl Cursor {
}
/// Does this cursor have the given attributes?
- pub fn has_attrs<const N: usize>(
+ pub(crate) fn has_attrs<const N: usize>(
&self,
attrs: &[Attribute; N],
) -> [bool; N] {
@@ -718,7 +719,7 @@ impl Cursor {
/// Given that this cursor's referent is a `typedef`, get the `Type` that is
/// being aliased.
- pub fn typedef_type(&self) -> Option<Type> {
+ pub(crate) fn typedef_type(&self) -> Option<Type> {
let inner = Type {
x: unsafe { clang_getTypedefDeclUnderlyingType(self.x) },
};
@@ -733,12 +734,12 @@ impl Cursor {
/// Get the linkage kind for this cursor's referent.
///
/// This only applies to functions and variables.
- pub fn linkage(&self) -> CXLinkageKind {
+ pub(crate) fn linkage(&self) -> CXLinkageKind {
unsafe { clang_getCursorLinkage(self.x) }
}
/// Get the visibility of this cursor's referent.
- pub fn visibility(&self) -> CXVisibilityKind {
+ pub(crate) fn visibility(&self) -> CXVisibilityKind {
unsafe { clang_getCursorVisibility(self.x) }
}
@@ -747,7 +748,7 @@ impl Cursor {
///
/// Returns None if the cursor's referent is not a function/method call or
/// declaration.
- pub fn args(&self) -> Option<Vec<Cursor>> {
+ pub(crate) fn args(&self) -> Option<Vec<Cursor>> {
// match self.kind() {
// CXCursor_FunctionDecl |
// CXCursor_CXXMethod => {
@@ -765,7 +766,7 @@ impl Cursor {
///
/// Returns Err if the cursor's referent is not a function/method call or
/// declaration.
- pub fn num_args(&self) -> Result<u32, ()> {
+ pub(crate) fn num_args(&self) -> Result<u32, ()> {
unsafe {
let w = clang_Cursor_getNumArguments(self.x);
if w == -1 {
@@ -777,7 +778,7 @@ impl Cursor {
}
/// Get the access specifier for this cursor's referent.
- pub fn access_specifier(&self) -> CX_CXXAccessSpecifier {
+ pub(crate) fn access_specifier(&self) -> CX_CXXAccessSpecifier {
unsafe { clang_getCXXAccessSpecifier(self.x) }
}
@@ -785,19 +786,19 @@ impl Cursor {
///
/// Returns true if self.access_specifier() is `CX_CXXPublic` or
/// `CX_CXXInvalidAccessSpecifier`.
- pub fn public_accessible(&self) -> bool {
+ pub(crate) fn public_accessible(&self) -> bool {
let access = self.access_specifier();
access == CX_CXXPublic || access == CX_CXXInvalidAccessSpecifier
}
/// Is this cursor's referent a field declaration that is marked as
/// `mutable`?
- pub fn is_mutable_field(&self) -> bool {
+ pub(crate) fn is_mutable_field(&self) -> bool {
unsafe { clang_CXXField_isMutable(self.x) != 0 }
}
/// Get the offset of the field represented by the Cursor.
- pub fn offset_of_field(&self) -> Result<usize, LayoutError> {
+ pub(crate) fn offset_of_field(&self) -> Result<usize, LayoutError> {
let offset = unsafe { clang_Cursor_getOffsetOfField(self.x) };
if offset < 0 {
@@ -808,37 +809,37 @@ impl Cursor {
}
/// Is this cursor's referent a member function that is declared `static`?
- pub fn method_is_static(&self) -> bool {
+ pub(crate) fn method_is_static(&self) -> bool {
unsafe { clang_CXXMethod_isStatic(self.x) != 0 }
}
/// Is this cursor's referent a member function that is declared `const`?
- pub fn method_is_const(&self) -> bool {
+ pub(crate) fn method_is_const(&self) -> bool {
unsafe { clang_CXXMethod_isConst(self.x) != 0 }
}
/// Is this cursor's referent a member function that is virtual?
- pub fn method_is_virtual(&self) -> bool {
+ pub(crate) fn method_is_virtual(&self) -> bool {
unsafe { clang_CXXMethod_isVirtual(self.x) != 0 }
}
/// Is this cursor's referent a member function that is pure virtual?
- pub fn method_is_pure_virtual(&self) -> bool {
+ pub(crate) fn method_is_pure_virtual(&self) -> bool {
unsafe { clang_CXXMethod_isPureVirtual(self.x) != 0 }
}
/// Is this cursor's referent a struct or class with virtual members?
- pub fn is_virtual_base(&self) -> bool {
+ pub(crate) fn is_virtual_base(&self) -> bool {
unsafe { clang_isVirtualBase(self.x) != 0 }
}
/// Try to evaluate this cursor.
- pub fn evaluate(&self) -> Option<EvalResult> {
+ pub(crate) fn evaluate(&self) -> Option<EvalResult> {
EvalResult::new(*self)
}
/// Return the result type for this cursor
- pub fn ret_type(&self) -> Option<Type> {
+ pub(crate) fn ret_type(&self) -> Option<Type> {
let rt = Type {
x: unsafe { clang_getCursorResultType(self.x) },
};
@@ -850,12 +851,12 @@ impl Cursor {
}
/// Gets the tokens that correspond to that cursor.
- pub fn tokens(&self) -> RawTokens {
+ pub(crate) fn tokens(&self) -> RawTokens {
RawTokens::new(self)
}
/// Gets the tokens that correspond to that cursor as `cexpr` tokens.
- pub fn cexpr_tokens(self) -> Vec<cexpr::token::Token> {
+ pub(crate) fn cexpr_tokens(self) -> Vec<cexpr::token::Token> {
self.tokens()
.iter()
.filter_map(|token| token.as_cexpr_token())
@@ -865,7 +866,7 @@ impl Cursor {
/// Obtain the real path name of a cursor of InclusionDirective kind.
///
/// Returns None if the cursor does not include a file, otherwise the file's full name
- pub fn get_included_file_name(&self) -> Option<String> {
+ pub(crate) fn get_included_file_name(&self) -> Option<String> {
let file = unsafe { clang_sys::clang_getIncludedFile(self.x) };
if file.is_null() {
None
@@ -878,7 +879,7 @@ impl Cursor {
}
/// A struct that owns the tokenizer result from a given cursor.
-pub struct RawTokens<'a> {
+pub(crate) struct RawTokens<'a> {
cursor: &'a Cursor,
tu: CXTranslationUnit,
tokens: *mut CXToken,
@@ -908,7 +909,7 @@ impl<'a> RawTokens<'a> {
}
/// Get an iterator over these tokens.
- pub fn iter(&self) -> ClangTokenIterator {
+ pub(crate) fn iter(&self) -> ClangTokenIterator {
ClangTokenIterator {
tu: self.tu,
raw: self.as_slice().iter(),
@@ -934,19 +935,19 @@ impl<'a> Drop for RawTokens<'a> {
/// slightly more convenient version of `CXToken` which owns the spelling
/// string and extent.
#[derive(Debug)]
-pub struct ClangToken {
+pub(crate) struct ClangToken {
spelling: CXString,
/// The extent of the token. This is the same as the relevant member from
/// `CXToken`.
- pub extent: CXSourceRange,
+ pub(crate) extent: CXSourceRange,
/// The kind of the token. This is the same as the relevant member from
/// `CXToken`.
- pub kind: CXTokenKind,
+ pub(crate) kind: CXTokenKind,
}
impl ClangToken {
/// Get the token spelling, without being converted to utf-8.
- pub fn spelling(&self) -> &[u8] {
+ pub(crate) fn spelling(&self) -> &[u8] {
let c_str = unsafe {
CStr::from_ptr(clang_getCString(self.spelling) as *const _)
};
@@ -954,7 +955,7 @@ impl ClangToken {
}
/// Converts a ClangToken to a `cexpr` token if possible.
- pub fn as_cexpr_token(&self) -> Option<cexpr::token::Token> {
+ pub(crate) fn as_cexpr_token(&self) -> Option<cexpr::token::Token> {
use cexpr::token;
let kind = match self.kind {
@@ -985,7 +986,7 @@ impl Drop for ClangToken {
}
/// An iterator over a set of Tokens.
-pub struct ClangTokenIterator<'a> {
+pub(crate) struct ClangTokenIterator<'a> {
tu: CXTranslationUnit,
raw: slice::Iter<'a, CXToken>,
}
@@ -1010,7 +1011,7 @@ impl<'a> Iterator for ClangTokenIterator<'a> {
/// Checks whether the name looks like an identifier, i.e. is alphanumeric
/// (including '_') and does not start with a digit.
-pub fn is_valid_identifier(name: &str) -> bool {
+pub(crate) fn is_valid_identifier(name: &str) -> bool {
let mut chars = name.chars();
let first_valid = chars
.next()
@@ -1050,7 +1051,7 @@ impl Hash for Cursor {
/// The type of a node in clang's AST.
#[derive(Clone, Copy)]
-pub struct Type {
+pub(crate) struct Type {
x: CXType,
}
@@ -1078,7 +1079,7 @@ impl fmt::Debug for Type {
/// An error about the layout of a struct, class, or type.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum LayoutError {
+pub(crate) enum LayoutError {
/// Asked for the layout of an invalid type.
Invalid,
/// Asked for the layout of an incomplete type.
@@ -1111,12 +1112,12 @@ impl ::std::convert::From<i32> for LayoutError {
impl Type {
/// Get this type's kind.
- pub fn kind(&self) -> CXTypeKind {
+ pub(crate) fn kind(&self) -> CXTypeKind {
self.x.kind
}
/// Get a cursor pointing to this type's declaration.
- pub fn declaration(&self) -> Cursor {
+ pub(crate) fn declaration(&self) -> Cursor {
unsafe {
Cursor {
x: clang_getTypeDeclaration(self.x),
@@ -1125,7 +1126,7 @@ impl Type {
}
/// Get the canonical declaration of this type, if it is available.
- pub fn canonical_declaration(
+ pub(crate) fn canonical_declaration(
&self,
location: Option<&Cursor>,
) -> Option<CanonicalTypeDeclaration> {
@@ -1151,7 +1152,7 @@ impl Type {
}
/// Get a raw display name for this type.
- pub fn spelling(&self) -> String {
+ pub(crate) fn spelling(&self) -> String {
let s = unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) };
// Clang 5.0 introduced changes in the spelling API so it returned the
// full qualified name. Let's undo that here.
@@ -1165,7 +1166,7 @@ impl Type {
}
/// Is this type const qualified?
- pub fn is_const(&self) -> bool {
+ pub(crate) fn is_const(&self) -> bool {
unsafe { clang_isConstQualifiedType(self.x) != 0 }
}
@@ -1203,7 +1204,7 @@ impl Type {
/// What is the size of this type? Paper over invalid types by returning `0`
/// for them.
- pub fn size(&self, ctx: &BindgenContext) -> usize {
+ pub(crate) fn size(&self, ctx: &BindgenContext) -> usize {
let val = self.clang_size_of(ctx);
if val < 0 {
0
@@ -1213,7 +1214,7 @@ impl Type {
}
/// What is the size of this type?
- pub fn fallible_size(
+ pub(crate) fn fallible_size(
&self,
ctx: &BindgenContext,
) -> Result<usize, LayoutError> {
@@ -1227,7 +1228,7 @@ impl Type {
/// What is the alignment of this type? Paper over invalid types by
/// returning `0`.
- pub fn align(&self, ctx: &BindgenContext) -> usize {
+ pub(crate) fn align(&self, ctx: &BindgenContext) -> usize {
let val = self.clang_align_of(ctx);
if val < 0 {
0
@@ -1237,7 +1238,7 @@ impl Type {
}
/// What is the alignment of this type?
- pub fn fallible_align(
+ pub(crate) fn fallible_align(
&self,
ctx: &BindgenContext,
) -> Result<usize, LayoutError> {
@@ -1251,7 +1252,7 @@ impl Type {
/// Get the layout for this type, or an error describing why it does not
/// have a valid layout.
- pub fn fallible_layout(
+ pub(crate) fn fallible_layout(
&self,
ctx: &BindgenContext,
) -> Result<crate::ir::layout::Layout, LayoutError> {
@@ -1263,7 +1264,7 @@ impl Type {
/// Get the number of template arguments this type has, or `None` if it is
/// not some kind of template.
- pub fn num_template_args(&self) -> Option<u32> {
+ pub(crate) fn num_template_args(&self) -> Option<u32> {
let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
if n >= 0 {
Some(n as u32)
@@ -1275,7 +1276,7 @@ impl Type {
/// If this type is a class template specialization, return its
/// template arguments. Otherwise, return None.
- pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
+ pub(crate) fn template_args(&self) -> Option<TypeTemplateArgIterator> {
self.num_template_args().map(|n| TypeTemplateArgIterator {
x: self.x,
length: n,
@@ -1286,7 +1287,7 @@ impl Type {
/// Given that this type is a function prototype, return the types of its parameters.
///
/// Returns None if the type is not a function prototype.
- pub fn args(&self) -> Option<Vec<Type>> {
+ pub(crate) fn args(&self) -> Option<Vec<Type>> {
self.num_args().ok().map(|num| {
(0..num)
.map(|i| Type {
@@ -1299,7 +1300,7 @@ impl Type {
/// Given that this type is a function prototype, return the number of arguments it takes.
///
/// Returns Err if the type is not a function prototype.
- pub fn num_args(&self) -> Result<u32, ()> {
+ pub(crate) fn num_args(&self) -> Result<u32, ()> {
unsafe {
let w = clang_getNumArgTypes(self.x);
if w == -1 {
@@ -1312,7 +1313,7 @@ impl Type {
/// Given that this type is a pointer type, return the type that it points
/// to.
- pub fn pointee_type(&self) -> Option<Type> {
+ pub(crate) fn pointee_type(&self) -> Option<Type> {
match self.kind() {
CXType_Pointer |
CXType_RValueReference |
@@ -1332,7 +1333,7 @@ impl Type {
/// Given that this type is an array, vector, or complex type, return the
/// type of its elements.
- pub fn elem_type(&self) -> Option<Type> {
+ pub(crate) fn elem_type(&self) -> Option<Type> {
let current_type = Type {
x: unsafe { clang_getElementType(self.x) },
};
@@ -1345,7 +1346,7 @@ impl Type {
/// Given that this type is an array or vector type, return its number of
/// elements.
- pub fn num_elements(&self) -> Option<usize> {
+ pub(crate) fn num_elements(&self) -> Option<usize> {
let num_elements_returned = unsafe { clang_getNumElements(self.x) };
if num_elements_returned != -1 {
Some(num_elements_returned as usize)
@@ -1356,7 +1357,7 @@ impl Type {
/// Get the canonical version of this type. This sees through `typedef`s and
/// aliases to get the underlying, canonical type.
- pub fn canonical_type(&self) -> Type {
+ pub(crate) fn canonical_type(&self) -> Type {
unsafe {
Type {
x: clang_getCanonicalType(self.x),
@@ -1365,13 +1366,13 @@ impl Type {
}
/// Is this type a variadic function type?
- pub fn is_variadic(&self) -> bool {
+ pub(crate) fn is_variadic(&self) -> bool {
unsafe { clang_isFunctionTypeVariadic(self.x) != 0 }
}
/// Given that this type is a function type, get the type of its return
/// value.
- pub fn ret_type(&self) -> Option<Type> {
+ pub(crate) fn ret_type(&self) -> Option<Type> {
let rt = Type {
x: unsafe { clang_getResultType(self.x) },
};
@@ -1384,13 +1385,13 @@ impl Type {
/// Given that this type is a function type, get its calling convention. If
/// this is not a function type, `CXCallingConv_Invalid` is returned.
- pub fn call_conv(&self) -> CXCallingConv {
+ pub(crate) fn call_conv(&self) -> CXCallingConv {
unsafe { clang_getFunctionTypeCallingConv(self.x) }
}
/// For elaborated types (types which use `class`, `struct`, or `union` to
/// disambiguate types from local bindings), get the underlying type.
- pub fn named(&self) -> Type {
+ pub(crate) fn named(&self) -> Type {
unsafe {
Type {
x: clang_Type_getNamedType(self.x),
@@ -1399,17 +1400,17 @@ impl Type {
}
/// Is this a valid type?
- pub fn is_valid(&self) -> bool {
+ pub(crate) fn is_valid(&self) -> bool {
self.kind() != CXType_Invalid
}
/// Is this a valid and exposed type?
- pub fn is_valid_and_exposed(&self) -> bool {
+ pub(crate) fn is_valid_and_exposed(&self) -> bool {
self.is_valid() && self.kind() != CXType_Unexposed
}
/// Is this type a fully instantiated template?
- pub fn is_fully_instantiated_template(&self) -> bool {
+ pub(crate) fn is_fully_instantiated_template(&self) -> bool {
// Yep, the spelling of this containing type-parameter is extremely
// nasty... But can happen in <type_traits>. Unfortunately I couldn't
// reduce it enough :(
@@ -1431,7 +1432,7 @@ impl Type {
/// typename T::Associated member;
/// };
/// ```
- pub fn is_associated_type(&self) -> bool {
+ pub(crate) fn is_associated_type(&self) -> bool {
// This is terrible :(
fn hacky_parse_associated_type<S: AsRef<str>>(spelling: S) -> bool {
lazy_static! {
@@ -1457,22 +1458,22 @@ impl Type {
/// cursor match up in a canonical declaration relationship, and it simply
/// cannot be otherwise.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct CanonicalTypeDeclaration(Type, Cursor);
+pub(crate) struct CanonicalTypeDeclaration(Type, Cursor);
impl CanonicalTypeDeclaration {
/// Get the type.
- pub fn ty(&self) -> &Type {
+ pub(crate) fn ty(&self) -> &Type {
&self.0
}
/// Get the type's canonical declaration cursor.
- pub fn cursor(&self) -> &Cursor {
+ pub(crate) fn cursor(&self) -> &Cursor {
&self.1
}
}
/// An iterator for a type's template arguments.
-pub struct TypeTemplateArgIterator {
+pub(crate) struct TypeTemplateArgIterator {
x: CXType,
length: u32,
index: u32,
@@ -1502,14 +1503,14 @@ impl ExactSizeIterator for TypeTemplateArgIterator {
/// A `SourceLocation` is a file, line, column, and byte offset location for
/// some source text.
-pub struct SourceLocation {
+pub(crate) struct SourceLocation {
x: CXSourceLocation,
}
impl SourceLocation {
/// Get the (file, line, column, byte offset) tuple for this source
/// location.
- pub fn location(&self) -> (File, usize, usize, usize) {
+ pub(crate) fn location(&self) -> (File, usize, usize, usize) {
unsafe {
let mut file = mem::zeroed();
let mut line = 0;
@@ -1543,18 +1544,18 @@ impl fmt::Debug for SourceLocation {
/// A comment in the source text.
///
/// Comments are sort of parsed by Clang, and have a tree structure.
-pub struct Comment {
+pub(crate) struct Comment {
x: CXComment,
}
impl Comment {
/// What kind of comment is this?
- pub fn kind(&self) -> CXCommentKind {
+ pub(crate) fn kind(&self) -> CXCommentKind {
unsafe { clang_Comment_getKind(self.x) }
}
/// Get this comment's children comment
- pub fn get_children(&self) -> CommentChildrenIterator {
+ pub(crate) fn get_children(&self) -> CommentChildrenIterator {
CommentChildrenIterator {
parent: self.x,
length: unsafe { clang_Comment_getNumChildren(self.x) },
@@ -1564,12 +1565,12 @@ impl Comment {
/// Given that this comment is the start or end of an HTML tag, get its tag
/// name.
- pub fn get_tag_name(&self) -> String {
+ pub(crate) fn get_tag_name(&self) -> String {
unsafe { cxstring_into_string(clang_HTMLTagComment_getTagName(self.x)) }
}
/// Given that this comment is an HTML start tag, get its attributes.
- pub fn get_tag_attrs(&self) -> CommentAttributesIterator {
+ pub(crate) fn get_tag_attrs(&self) -> CommentAttributesIterator {
CommentAttributesIterator {
x: self.x,
length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) },
@@ -1579,7 +1580,7 @@ impl Comment {
}
/// An iterator for a comment's children
-pub struct CommentChildrenIterator {
+pub(crate) struct CommentChildrenIterator {
parent: CXComment,
length: c_uint,
index: c_uint,
@@ -1601,15 +1602,15 @@ impl Iterator for CommentChildrenIterator {
}
/// An HTML start tag comment attribute
-pub struct CommentAttribute {
+pub(crate) struct CommentAttribute {
/// HTML start tag attribute name
- pub name: String,
+ pub(crate) name: String,
/// HTML start tag attribute value
- pub value: String,
+ pub(crate) value: String,
}
/// An iterator for a comment's attributes
-pub struct CommentAttributesIterator {
+pub(crate) struct CommentAttributesIterator {
x: CXComment,
length: c_uint,
index: c_uint,
@@ -1640,13 +1641,13 @@ impl Iterator for CommentAttributesIterator {
}
/// A source file.
-pub struct File {
+pub(crate) struct File {
x: CXFile,
}
impl File {
/// Get the name of this source file.
- pub fn name(&self) -> Option<String> {
+ pub(crate) fn name(&self) -> Option<String> {
if self.x.is_null() {
return None;
}
@@ -1670,7 +1671,7 @@ fn cxstring_into_string(s: CXString) -> String {
/// An `Index` is an environment for a set of translation units that will
/// typically end up linked together in one final binary.
-pub struct Index {
+pub(crate) struct Index {
x: CXIndex,
}
@@ -1681,7 +1682,7 @@ impl Index {
/// headers are included when enumerating a translation unit's "locals".
///
/// The `diag` parameter controls whether debugging diagnostics are enabled.
- pub fn new(pch: bool, diag: bool) -> Index {
+ pub(crate) fn new(pch: bool, diag: bool) -> Index {
unsafe {
Index {
x: clang_createIndex(pch as c_int, diag as c_int),
@@ -1705,7 +1706,7 @@ impl Drop for Index {
}
/// A translation unit (or "compilation unit").
-pub struct TranslationUnit {
+pub(crate) struct TranslationUnit {
x: CXTranslationUnit,
}
@@ -1717,7 +1718,7 @@ impl fmt::Debug for TranslationUnit {
impl TranslationUnit {
/// Parse a source file into a translation unit.
- pub fn parse(
+ pub(crate) fn parse(
ix: &Index,
file: &str,
cmd_args: &[String],
@@ -1753,7 +1754,7 @@ impl TranslationUnit {
/// Get the Clang diagnostic information associated with this translation
/// unit.
- pub fn diags(&self) -> Vec<Diagnostic> {
+ pub(crate) fn diags(&self) -> Vec<Diagnostic> {
unsafe {
let num = clang_getNumDiagnostics(self.x) as usize;
let mut diags = vec![];
@@ -1767,7 +1768,7 @@ impl TranslationUnit {
}
/// Get a cursor pointing to the root of this translation unit's AST.
- pub fn cursor(&self) -> Cursor {
+ pub(crate) fn cursor(&self) -> Cursor {
unsafe {
Cursor {
x: clang_getTranslationUnitCursor(self.x),
@@ -1776,7 +1777,7 @@ impl TranslationUnit {
}
/// Is this the null translation unit?
- pub fn is_null(&self) -> bool {
+ pub(crate) fn is_null(&self) -> bool {
self.x.is_null()
}
}
@@ -1790,14 +1791,14 @@ impl Drop for TranslationUnit {
}
/// A diagnostic message generated while parsing a translation unit.
-pub struct Diagnostic {
+pub(crate) struct Diagnostic {
x: CXDiagnostic,
}
impl Diagnostic {
/// Format this diagnostic message as a string, using the given option bit
/// flags.
- pub fn format(&self) -> String {
+ pub(crate) fn format(&self) -> String {
unsafe {
let opts = clang_defaultDiagnosticDisplayOptions();
cxstring_into_string(clang_formatDiagnostic(self.x, opts))
@@ -1805,7 +1806,7 @@ impl Diagnostic {
}
/// What is the severity of this diagnostic message?
- pub fn severity(&self) -> CXDiagnosticSeverity {
+ pub(crate) fn severity(&self) -> CXDiagnosticSeverity {
unsafe { clang_getDiagnosticSeverity(self.x) }
}
}
@@ -1820,17 +1821,17 @@ impl Drop for Diagnostic {
}
/// A file which has not been saved to disk.
-pub struct UnsavedFile {
+pub(crate) struct UnsavedFile {
x: CXUnsavedFile,
/// The name of the unsaved file. Kept here to avoid leaving dangling pointers in
/// `CXUnsavedFile`.
- pub name: CString,
+ pub(crate) name: CString,
contents: CString,
}
impl UnsavedFile {
/// Construct a new unsaved file with the given `name` and `contents`.
- pub fn new(name: String, contents: String) -> UnsavedFile {
+ pub(crate) fn new(name: String, contents: String) -> UnsavedFile {
let name = CString::new(name).unwrap();
let contents = CString::new(contents).unwrap();
let x = CXUnsavedFile {
@@ -1853,17 +1854,17 @@ impl fmt::Debug for UnsavedFile {
}
/// Convert a cursor kind into a static string.
-pub fn kind_to_str(x: CXCursorKind) -> String {
+pub(crate) fn kind_to_str(x: CXCursorKind) -> String {
unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }
}
/// Convert a type kind to a static string.
-pub fn type_to_str(x: CXTypeKind) -> String {
+pub(crate) fn type_to_str(x: CXTypeKind) -> String {
unsafe { cxstring_into_string(clang_getTypeKindSpelling(x)) }
}
/// Dump the Clang AST to stdout for debugging purposes.
-pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
+pub(crate) fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
fn print_indent<S: AsRef<str>>(depth: isize, s: S) {
for _ in 0..depth {
print!(" ");
@@ -2095,19 +2096,20 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
}
/// Try to extract the clang version to a string
-pub fn extract_clang_version() -> String {
+pub(crate) fn extract_clang_version() -> String {
unsafe { cxstring_into_string(clang_getClangVersion()) }
}
/// A wrapper for the result of evaluating an expression.
#[derive(Debug)]
-pub struct EvalResult {
+pub(crate) struct EvalResult {
x: CXEvalResult,
+ ty: Type,
}
impl EvalResult {
/// Evaluate `cursor` and return the result.
- pub fn new(cursor: Cursor) -> Option<Self> {
+ pub(crate) fn new(cursor: Cursor) -> Option<Self> {
// Work around https://bugs.llvm.org/show_bug.cgi?id=42532, see:
// * https://github.com/rust-lang/rust-bindgen/issues/283
// * https://github.com/rust-lang/rust-bindgen/issues/1590
@@ -2130,6 +2132,7 @@ impl EvalResult {
}
Some(EvalResult {
x: unsafe { clang_Cursor_Evaluate(cursor.x) },
+ ty: cursor.cur_type().canonical_type(),
})
}
@@ -2138,7 +2141,7 @@ impl EvalResult {
}
/// Try to get back the result as a double.
- pub fn as_double(&self) -> Option<f64> {
+ pub(crate) fn as_double(&self) -> Option<f64> {
match self.kind() {
CXEval_Float => {
Some(unsafe { clang_EvalResult_getAsDouble(self.x) })
@@ -2148,7 +2151,7 @@ impl EvalResult {
}
/// Try to get back the result as an integer.
- pub fn as_int(&self) -> Option<i64> {
+ pub(crate) fn as_int(&self) -> Option<i64> {
if self.kind() != CXEval_Int {
return None;
}
@@ -2175,14 +2178,23 @@ impl EvalResult {
/// Evaluates the expression as a literal string, that may or may not be
/// valid utf-8.
- pub fn as_literal_string(&self) -> Option<Vec<u8>> {
- match self.kind() {
- CXEval_StrLiteral => {
+ pub(crate) fn as_literal_string(&self) -> Option<Vec<u8>> {
+ if self.kind() != CXEval_StrLiteral {
+ return None;
+ }
+
+ let char_ty = self.ty.pointee_type().or_else(|| self.ty.elem_type())?;
+ match char_ty.kind() {
+ CXType_Char_S | CXType_SChar | CXType_Char_U | CXType_UChar => {
let ret = unsafe {
CStr::from_ptr(clang_EvalResult_getAsStr(self.x))
};
Some(ret.to_bytes().to_vec())
}
+ // FIXME: Support generating these.
+ CXType_Char16 => None,
+ CXType_Char32 => None,
+ CXType_WChar => None,
_ => None,
}
}
@@ -2196,16 +2208,16 @@ impl Drop for EvalResult {
/// Target information obtained from libclang.
#[derive(Debug)]
-pub struct TargetInfo {
+pub(crate) struct TargetInfo {
/// The target triple.
- pub triple: String,
+ pub(crate) triple: String,
/// The width of the pointer _in bits_.
- pub pointer_width: usize,
+ pub(crate) pointer_width: usize,
}
impl TargetInfo {
/// Tries to obtain target information from libclang.
- pub fn new(tu: &TranslationUnit) -> Self {
+ pub(crate) fn new(tu: &TranslationUnit) -> Self {
let triple;
let pointer_width;
unsafe {
diff --git a/codegen/dyngen.rs b/codegen/dyngen.rs
index d8ea811..c067fad 100644
--- a/codegen/dyngen.rs
+++ b/codegen/dyngen.rs
@@ -5,7 +5,7 @@ use proc_macro2::Ident;
/// Used to build the output tokens for dynamic bindings.
#[derive(Default)]
-pub struct DynamicItems {
+pub(crate) struct DynamicItems {
/// Tracks the tokens that will appears inside the library struct -- e.g.:
/// ```ignore
/// struct Lib {
@@ -69,11 +69,11 @@ pub struct DynamicItems {
}
impl DynamicItems {
- pub fn new() -> Self {
+ pub(crate) fn new() -> Self {
Self::default()
}
- pub fn get_tokens(
+ pub(crate) fn get_tokens(
&self,
lib_ident: Ident,
ctx: &BindgenContext,
diff --git a/codegen/error.rs b/codegen/error.rs
index c1bcf4e..ead3496 100644
--- a/codegen/error.rs
+++ b/codegen/error.rs
@@ -3,7 +3,7 @@ use std::fmt;
/// Errors that can occur during code generation.
#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum Error {
+pub(crate) enum Error {
/// Tried to generate an opaque blob for a type that did not have a layout.
NoLayoutForOpaqueBlob,
@@ -30,4 +30,4 @@ impl fmt::Display for Error {
impl error::Error for Error {}
/// A `Result` of `T` or an error of `bindgen::codegen::error::Error`.
-pub type Result<T> = ::std::result::Result<T, Error>;
+pub(crate) type Result<T> = ::std::result::Result<T, Error>;
diff --git a/codegen/helpers.rs b/codegen/helpers.rs
index 088c7f9..726fe75 100644
--- a/codegen/helpers.rs
+++ b/codegen/helpers.rs
@@ -5,18 +5,18 @@ use crate::ir::layout::Layout;
use proc_macro2::{Ident, Span, TokenStream};
use quote::TokenStreamExt;
-pub mod attributes {
+pub(crate) mod attributes {
use proc_macro2::{Ident, Span, TokenStream};
- use std::str::FromStr;
+ use std::{borrow::Cow, str::FromStr};
- pub fn repr(which: &str) -> TokenStream {
+ pub(crate) fn repr(which: &str) -> TokenStream {
let which = Ident::new(which, Span::call_site());
quote! {
#[repr( #which )]
}
}
- pub fn repr_list(which_ones: &[&str]) -> TokenStream {
+ pub(crate) fn repr_list(which_ones: &[&str]) -> TokenStream {
let which_ones = which_ones
.iter()
.cloned()
@@ -26,7 +26,7 @@ pub mod attributes {
}
}
- pub fn derives(which_ones: &[&str]) -> TokenStream {
+ pub(crate) fn derives(which_ones: &[&str]) -> TokenStream {
let which_ones = which_ones
.iter()
.cloned()
@@ -36,25 +36,25 @@ pub mod attributes {
}
}
- pub fn inline() -> TokenStream {
+ pub(crate) fn inline() -> TokenStream {
quote! {
#[inline]
}
}
- pub fn must_use() -> TokenStream {
+ pub(crate) fn must_use() -> TokenStream {
quote! {
#[must_use]
}
}
- pub fn non_exhaustive() -> TokenStream {
+ pub(crate) fn non_exhaustive() -> TokenStream {
quote! {
#[non_exhaustive]
}
}
- pub fn doc(comment: String) -> TokenStream {
+ pub(crate) fn doc(comment: String) -> TokenStream {
if comment.is_empty() {
quote!()
} else {
@@ -62,10 +62,15 @@ pub mod attributes {
}
}
- pub fn link_name(name: &str) -> TokenStream {
+ pub(crate) fn link_name<const MANGLE: bool>(name: &str) -> TokenStream {
// LLVM mangles the name by default but it's already mangled.
// Prefixing the name with \u{1} should tell LLVM to not mangle it.
- let name = format!("\u{1}{}", name);
+ let name: Cow<'_, str> = if MANGLE {
+ name.into()
+ } else {
+ format!("\u{1}{}", name).into()
+ };
+
quote! {
#[link_name = #name]
}
@@ -74,7 +79,7 @@ pub mod attributes {
/// Generates a proper type for a field or type with a given `Layout`, that is,
/// a type with the correct size and alignment restrictions.
-pub fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream {
+pub(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream {
let opaque = layout.opaque();
// FIXME(emilio, #412): We fall back to byte alignment, but there are
@@ -105,7 +110,7 @@ pub fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream {
}
/// Integer type of the same size as the given `Layout`.
-pub fn integer_type(
+pub(crate) fn integer_type(
ctx: &BindgenContext,
layout: Layout,
) -> Option<TokenStream> {
@@ -115,7 +120,10 @@ pub fn integer_type(
}
/// Generates a bitfield allocation unit type for a type with the given `Layout`.
-pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> TokenStream {
+pub(crate) fn bitfield_unit(
+ ctx: &BindgenContext,
+ layout: Layout,
+) -> TokenStream {
let mut tokens = quote! {};
if ctx.options().enable_cxx_namespaces {
@@ -130,7 +138,7 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> TokenStream {
tokens
}
-pub mod ast_ty {
+pub(crate) mod ast_ty {
use crate::ir::context::BindgenContext;
use crate::ir::function::FunctionSig;
use crate::ir::layout::Layout;
@@ -138,7 +146,7 @@ pub mod ast_ty {
use proc_macro2::{self, TokenStream};
use std::str::FromStr;
- pub fn c_void(ctx: &BindgenContext) -> TokenStream {
+ pub(crate) fn c_void(ctx: &BindgenContext) -> TokenStream {
// ctypes_prefix takes precedence
match ctx.options().ctypes_prefix {
Some(ref prefix) => {
@@ -159,7 +167,7 @@ pub mod ast_ty {
}
}
- pub fn raw_type(ctx: &BindgenContext, name: &str) -> TokenStream {
+ pub(crate) fn raw_type(ctx: &BindgenContext, name: &str) -> TokenStream {
let ident = ctx.rust_ident_raw(name);
match ctx.options().ctypes_prefix {
Some(ref prefix) => {
@@ -184,7 +192,7 @@ pub mod ast_ty {
}
}
- pub fn float_kind_rust_type(
+ pub(crate) fn float_kind_rust_type(
ctx: &BindgenContext,
fk: FloatKind,
layout: Option<Layout>,
@@ -229,25 +237,25 @@ pub mod ast_ty {
}
}
- pub fn int_expr(val: i64) -> TokenStream {
+ pub(crate) fn int_expr(val: i64) -> TokenStream {
// Don't use quote! { #val } because that adds the type suffix.
let val = proc_macro2::Literal::i64_unsuffixed(val);
quote!(#val)
}
- pub fn uint_expr(val: u64) -> TokenStream {
+ pub(crate) fn uint_expr(val: u64) -> TokenStream {
// Don't use quote! { #val } because that adds the type suffix.
let val = proc_macro2::Literal::u64_unsuffixed(val);
quote!(#val)
}
- pub fn byte_array_expr(bytes: &[u8]) -> TokenStream {
+ pub(crate) fn byte_array_expr(bytes: &[u8]) -> TokenStream {
let mut bytes: Vec<_> = bytes.to_vec();
bytes.push(0);
quote! { [ #(#bytes),* ] }
}
- pub fn cstr_expr(mut string: String) -> TokenStream {
+ pub(crate) fn cstr_expr(mut string: String) -> TokenStream {
string.push('\0');
let b = proc_macro2::Literal::byte_string(string.as_bytes());
quote! {
@@ -255,7 +263,10 @@ pub mod ast_ty {
}
}
- pub fn float_expr(ctx: &BindgenContext, f: f64) -> Result<TokenStream, ()> {
+ pub(crate) fn float_expr(
+ ctx: &BindgenContext,
+ f: f64,
+ ) -> Result<TokenStream, ()> {
if f.is_finite() {
let val = proc_macro2::Literal::f64_unsuffixed(f);
@@ -286,7 +297,7 @@ pub mod ast_ty {
Err(())
}
- pub fn arguments_from_signature(
+ pub(crate) fn arguments_from_signature(
signature: &FunctionSig,
ctx: &BindgenContext,
) -> Vec<TokenStream> {
diff --git a/codegen/impl_debug.rs b/codegen/impl_debug.rs
index 0e2cd33..67ec214 100644
--- a/codegen/impl_debug.rs
+++ b/codegen/impl_debug.rs
@@ -3,7 +3,7 @@ use crate::ir::context::BindgenContext;
use crate::ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName};
use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
-pub fn gen_debug_impl(
+pub(crate) fn gen_debug_impl(
ctx: &BindgenContext,
fields: &[Field],
item: &Item,
@@ -51,7 +51,7 @@ pub fn gen_debug_impl(
/// A trait for the things which we can codegen tokens that contribute towards a
/// generated `impl Debug`.
-pub trait ImplDebug<'a> {
+pub(crate) trait ImplDebug<'a> {
/// Any extra parameter required by this a particular `ImplDebug` implementation.
type Extra;
diff --git a/codegen/impl_partialeq.rs b/codegen/impl_partialeq.rs
index 960306f..42fabf6 100644
--- a/codegen/impl_partialeq.rs
+++ b/codegen/impl_partialeq.rs
@@ -5,7 +5,7 @@ use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
/// Generate a manual implementation of `PartialEq` trait for the
/// specified compound type.
-pub fn gen_partialeq_impl(
+pub(crate) fn gen_partialeq_impl(
ctx: &BindgenContext,
comp_info: &CompInfo,
item: &Item,
@@ -18,7 +18,7 @@ pub fn gen_partialeq_impl(
&self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
});
} else if comp_info.kind() == CompKind::Union {
- assert!(!ctx.options().rust_features().untagged_union);
+ assert!(!ctx.options().untagged_union);
tokens.push(quote! {
&self.bindgen_union_field[..] == &other.bindgen_union_field[..]
});
diff --git a/codegen/mod.rs b/codegen/mod.rs
index b6fb70e..0dd3228 100644
--- a/codegen/mod.rs
+++ b/codegen/mod.rs
@@ -5,7 +5,7 @@ mod impl_debug;
mod impl_partialeq;
mod postprocessing;
mod serialize;
-pub mod struct_layout;
+pub(crate) mod struct_layout;
#[cfg(test)]
#[allow(warnings)]
@@ -21,7 +21,9 @@ use super::BindgenOptions;
use crate::callbacks::{DeriveInfo, TypeKind as DeriveTypeKind};
use crate::ir::analysis::{HasVtable, Sizedness};
-use crate::ir::annotations::FieldAccessorKind;
+use crate::ir::annotations::{
+ Annotations, FieldAccessorKind, FieldVisibilityKind,
+};
use crate::ir::comp::{
Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData, FieldMethods,
Method, MethodKind,
@@ -55,8 +57,7 @@ use crate::{Entry, HashMap, HashSet};
use std::borrow::Cow;
use std::cell::Cell;
use std::collections::VecDeque;
-use std::fmt::Write;
-use std::iter;
+use std::fmt::{self, Write};
use std::ops;
use std::str::FromStr;
@@ -72,19 +73,19 @@ impl From<std::io::Error> for CodegenError {
}
}
-impl std::fmt::Display for CodegenError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+impl fmt::Display for CodegenError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- CodegenError::Serialize { msg, loc } => {
+ Self::Serialize { msg, loc } => {
write!(f, "serialization error at {}: {}", loc, msg)
}
- CodegenError::Io(err) => err.fmt(f),
+ Self::Io(err) => err.fmt(f),
}
}
}
// Name of type defined in constified enum module
-pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type";
+pub(crate) static CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type";
fn top_level_path(
ctx: &BindgenContext,
@@ -124,6 +125,7 @@ fn root_import(
}
bitflags! {
+ #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct DerivableTraits: u16 {
const DEBUG = 1 << 0;
const DEFAULT = 1 << 1;
@@ -222,7 +224,7 @@ struct CodegenResult<'a> {
items: Vec<proc_macro2::TokenStream>,
dynamic_items: DynamicItems,
- /// A monotonic counter used to add stable unique id's to stuff that doesn't
+ /// A monotonic counter used to add stable unique ID's to stuff that doesn't
/// need to be referenced by anything.
codegen_id: &'a Cell<usize>,
@@ -694,7 +696,7 @@ impl CodeGenerator for Var {
// Account the trailing zero.
//
// TODO: Here we ignore the type we just made up, probably
- // we should refactor how the variable type and ty id work.
+ // we should refactor how the variable type and ty ID work.
let len = bytes.len() + 1;
let ty = quote! {
[u8; #len]
@@ -745,13 +747,18 @@ impl CodeGenerator for Var {
}
} else {
// If necessary, apply a `#[link_name]` attribute
- let link_name = self.mangled_name().unwrap_or_else(|| self.name());
- if !utils::names_will_be_identical_after_mangling(
- &canonical_name,
- link_name,
- None,
- ) {
- attrs.push(attributes::link_name(link_name));
+ if let Some(link_name) = self.link_name() {
+ attrs.push(attributes::link_name::<false>(link_name));
+ } else {
+ let link_name =
+ self.mangled_name().unwrap_or_else(|| self.name());
+ if !utils::names_will_be_identical_after_mangling(
+ &canonical_name,
+ link_name,
+ None,
+ ) {
+ attrs.push(attributes::link_name::<false>(link_name));
+ }
}
let maybe_mut = if self.is_const() {
@@ -1034,13 +1041,15 @@ impl CodeGenerator for Type {
});
}
+ let access_spec =
+ access_specifier(ctx.options().default_visibility);
tokens.append_all(match alias_style {
AliasVariation::TypeAlias => quote! {
= #inner_rust_type ;
},
AliasVariation::NewType | AliasVariation::NewTypeDeref => {
quote! {
- (pub #inner_rust_type) ;
+ (#access_spec #inner_rust_type) ;
}
}
});
@@ -1271,7 +1280,7 @@ trait FieldCodegen<'a> {
fn codegen<F, M>(
&self,
ctx: &BindgenContext,
- fields_should_be_private: bool,
+ visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
result: &mut CodegenResult,
@@ -1290,7 +1299,7 @@ impl<'a> FieldCodegen<'a> for Field {
fn codegen<F, M>(
&self,
ctx: &BindgenContext,
- fields_should_be_private: bool,
+ visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
result: &mut CodegenResult,
@@ -1306,7 +1315,7 @@ impl<'a> FieldCodegen<'a> for Field {
Field::DataMember(ref data) => {
data.codegen(
ctx,
- fields_should_be_private,
+ visibility_kind,
accessor_kind,
parent,
result,
@@ -1319,7 +1328,7 @@ impl<'a> FieldCodegen<'a> for Field {
Field::Bitfields(ref unit) => {
unit.codegen(
ctx,
- fields_should_be_private,
+ visibility_kind,
accessor_kind,
parent,
result,
@@ -1368,7 +1377,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
fn codegen<F, M>(
&self,
ctx: &BindgenContext,
- fields_should_be_private: bool,
+ parent_visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
result: &mut CodegenResult,
@@ -1431,23 +1440,31 @@ impl<'a> FieldCodegen<'a> for FieldData {
fields.extend(Some(padding_field));
}
- let is_private = (!self.is_public() &&
- ctx.options().respect_cxx_access_specs) ||
- self.annotations()
- .private_fields()
- .unwrap_or(fields_should_be_private);
-
+ let visibility = compute_visibility(
+ ctx,
+ self.is_public(),
+ Some(self.annotations()),
+ parent_visibility_kind,
+ );
let accessor_kind =
self.annotations().accessor_kind().unwrap_or(accessor_kind);
- if is_private {
- field.append_all(quote! {
- #field_ident : #ty ,
- });
- } else {
- field.append_all(quote! {
- pub #field_ident : #ty ,
- });
+ match visibility {
+ FieldVisibilityKind::Private => {
+ field.append_all(quote! {
+ #field_ident : #ty ,
+ });
+ }
+ FieldVisibilityKind::PublicCrate => {
+ field.append_all(quote! {
+ pub(crate) #field_ident : #ty ,
+ });
+ }
+ FieldVisibilityKind::Public => {
+ field.append_all(quote! {
+ pub #field_ident : #ty ,
+ });
+ }
}
fields.extend(Some(field));
@@ -1557,13 +1574,48 @@ impl Bitfield {
}
fn access_specifier(
- ctx: &BindgenContext,
- is_pub: bool,
+ visibility: FieldVisibilityKind,
) -> proc_macro2::TokenStream {
- if is_pub || !ctx.options().respect_cxx_access_specs {
- quote! { pub }
- } else {
- quote! {}
+ match visibility {
+ FieldVisibilityKind::Private => quote! {},
+ FieldVisibilityKind::PublicCrate => quote! { pub(crate) },
+ FieldVisibilityKind::Public => quote! { pub },
+ }
+}
+
+/// Compute a fields or structs visibility based on multiple conditions.
+/// 1. If the element was declared public, and we respect such CXX accesses specs
+/// (context option) => By default Public, but this can be overruled by an `annotation`.
+///
+/// 2. If the element was declared private, and we respect such CXX accesses specs
+/// (context option) => By default Private, but this can be overruled by an `annotation`.
+///
+/// 3. If we do not respect visibility modifiers, the result depends on the `annotation`,
+/// if any, or the passed `default_kind`.
+///
+fn compute_visibility(
+ ctx: &BindgenContext,
+ is_declared_public: bool,
+ annotations: Option<&Annotations>,
+ default_kind: FieldVisibilityKind,
+) -> FieldVisibilityKind {
+ match (
+ is_declared_public,
+ ctx.options().respect_cxx_access_specs,
+ annotations.and_then(|e| e.visibility_kind()),
+ ) {
+ (true, true, annotated_visibility) => {
+ // declared as public, cxx specs are respected
+ annotated_visibility.unwrap_or(FieldVisibilityKind::Public)
+ }
+ (false, true, annotated_visibility) => {
+ // declared as private, cxx specs are respected
+ annotated_visibility.unwrap_or(FieldVisibilityKind::Private)
+ }
+ (_, false, annotated_visibility) => {
+ // cxx specs are not respected, declaration does not matter.
+ annotated_visibility.unwrap_or(default_kind)
+ }
}
}
@@ -1573,7 +1625,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
fn codegen<F, M>(
&self,
ctx: &BindgenContext,
- fields_should_be_private: bool,
+ visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
result: &mut CodegenResult,
@@ -1591,15 +1643,18 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
let layout = self.layout();
let unit_field_ty = helpers::bitfield_unit(ctx, layout);
- let field_ty = if parent.is_union() {
- wrap_union_field_if_needed(
- ctx,
- struct_layout,
- unit_field_ty.clone(),
- result,
- )
- } else {
- unit_field_ty.clone()
+ let field_ty = {
+ let unit_field_ty = unit_field_ty.clone();
+ if parent.is_union() {
+ wrap_union_field_if_needed(
+ ctx,
+ struct_layout,
+ unit_field_ty,
+ result,
+ )
+ } else {
+ unit_field_ty
+ }
};
{
@@ -1611,8 +1666,9 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
2 => quote! { u16 },
_ => quote! { u8 },
};
+ let access_spec = access_specifier(visibility_kind);
let align_field = quote! {
- pub #align_field_ident: [#align_ty; 0],
+ #access_spec #align_field_ident: [#align_ty; 0],
};
fields.extend(Some(align_field));
}
@@ -1631,7 +1687,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
// the 32 items limitation.
let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT;
- let mut access_spec = !fields_should_be_private;
+ let mut all_fields_declared_as_public = true;
for bf in self.bitfields() {
// Codegen not allowed for anonymous bitfields
if bf.name().is_none() {
@@ -1644,12 +1700,11 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
continue;
}
- access_spec &= bf.is_public();
+ all_fields_declared_as_public &= bf.is_public();
let mut bitfield_representable_as_int = true;
-
bf.codegen(
ctx,
- fields_should_be_private,
+ visibility_kind,
accessor_kind,
parent,
result,
@@ -1677,7 +1732,13 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
ctor_impl = bf.extend_ctor_impl(ctx, param_name, ctor_impl);
}
- let access_spec = access_specifier(ctx, access_spec);
+ let visibility_kind = compute_visibility(
+ ctx,
+ all_fields_declared_as_public,
+ None,
+ visibility_kind,
+ );
+ let access_spec = access_specifier(visibility_kind);
let field = quote! {
#access_spec #unit_field_ident : #field_ty ,
@@ -1723,7 +1784,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
fn codegen<F, M>(
&self,
ctx: &BindgenContext,
- fields_should_be_private: bool,
+ visibility_kind: FieldVisibilityKind,
_accessor_kind: FieldAccessorKind,
parent: &CompInfo,
_result: &mut CodegenResult,
@@ -1763,10 +1824,14 @@ impl<'a> FieldCodegen<'a> for Bitfield {
let offset = self.offset_into_unit();
let width = self.width() as u8;
- let access_spec = access_specifier(
+
+ let visibility_kind = compute_visibility(
ctx,
- self.is_public() && !fields_should_be_private,
+ self.is_public(),
+ Some(self.annotations()),
+ visibility_kind,
);
+ let access_spec = access_specifier(visibility_kind);
if parent.is_union() && !struct_layout.is_rust_union() {
methods.extend(Some(quote! {
@@ -1892,7 +1957,16 @@ impl CodeGenerator for CompInfo {
struct_layout.saw_base(inner_item.expect_type());
- let access_spec = access_specifier(ctx, base.is_public());
+ let visibility = match (
+ base.is_public(),
+ ctx.options().respect_cxx_access_specs,
+ ) {
+ (true, true) => FieldVisibilityKind::Public,
+ (false, true) => FieldVisibilityKind::Private,
+ _ => ctx.options().default_visibility,
+ };
+
+ let access_spec = access_specifier(visibility);
fields.push(quote! {
#access_spec #field_name: #inner,
});
@@ -1901,8 +1975,10 @@ impl CodeGenerator for CompInfo {
let mut methods = vec![];
if !is_opaque {
- let fields_should_be_private =
- item.annotations().private_fields().unwrap_or(false);
+ let visibility = item
+ .annotations()
+ .visibility_kind()
+ .unwrap_or(ctx.options().default_visibility);
let struct_accessor_kind = item
.annotations()
.accessor_kind()
@@ -1910,7 +1986,7 @@ impl CodeGenerator for CompInfo {
for field in self.fields() {
field.codegen(
ctx,
- fields_should_be_private,
+ visibility,
struct_accessor_kind,
self,
result,
@@ -2491,6 +2567,9 @@ impl Method {
ClangAbi::Known(Abi::CUnwind) => {
ctx.options().rust_features().c_unwind_abi
}
+ ClangAbi::Known(Abi::EfiApi) => {
+ ctx.options().rust_features().abi_efiapi
+ }
_ => true,
};
@@ -2661,6 +2740,35 @@ impl Default for EnumVariation {
}
}
+impl fmt::Display for EnumVariation {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let s = match self {
+ Self::Rust {
+ non_exhaustive: false,
+ } => "rust",
+ Self::Rust {
+ non_exhaustive: true,
+ } => "rust_non_exhaustive",
+ Self::NewType {
+ is_bitfield: true, ..
+ } => "bitfield",
+ Self::NewType {
+ is_bitfield: false,
+ is_global,
+ } => {
+ if *is_global {
+ "newtype_global"
+ } else {
+ "newtype"
+ }
+ }
+ Self::Consts => "consts",
+ Self::ModuleConsts => "moduleconsts",
+ };
+ s.fmt(f)
+ }
+}
+
impl std::str::FromStr for EnumVariation {
type Err = std::io::Error;
@@ -3347,13 +3455,13 @@ pub enum MacroTypeVariation {
Unsigned,
}
-impl MacroTypeVariation {
- /// Convert a `MacroTypeVariation` to its str representation.
- pub fn as_str(&self) -> &str {
- match self {
- MacroTypeVariation::Signed => "signed",
- MacroTypeVariation::Unsigned => "unsigned",
- }
+impl fmt::Display for MacroTypeVariation {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let s = match self {
+ Self::Signed => "signed",
+ Self::Unsigned => "unsigned",
+ };
+ s.fmt(f)
}
}
@@ -3393,14 +3501,15 @@ pub enum AliasVariation {
NewTypeDeref,
}
-impl AliasVariation {
- /// Convert an `AliasVariation` to its str representation.
- pub fn as_str(&self) -> &str {
- match self {
- AliasVariation::TypeAlias => "type_alias",
- AliasVariation::NewType => "new_type",
- AliasVariation::NewTypeDeref => "new_type_deref",
- }
+impl fmt::Display for AliasVariation {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let s = match self {
+ Self::TypeAlias => "type_alias",
+ Self::NewType => "new_type",
+ Self::NewTypeDeref => "new_type_deref",
+ };
+
+ s.fmt(f)
}
}
@@ -3430,10 +3539,10 @@ impl std::str::FromStr for AliasVariation {
}
}
-/// Enum for how non-Copy unions should be translated.
+/// Enum for how non-`Copy` `union`s should be translated.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum NonCopyUnionStyle {
- /// Wrap members in a type generated by bindgen.
+ /// Wrap members in a type generated by `bindgen`.
BindgenWrapper,
/// Wrap members in [`::core::mem::ManuallyDrop`].
///
@@ -3442,13 +3551,14 @@ pub enum NonCopyUnionStyle {
ManuallyDrop,
}
-impl NonCopyUnionStyle {
- /// Convert an `NonCopyUnionStyle` to its str representation.
- pub fn as_str(&self) -> &'static str {
- match self {
+impl fmt::Display for NonCopyUnionStyle {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let s = match self {
Self::BindgenWrapper => "bindgen_wrapper",
Self::ManuallyDrop => "manually_drop",
- }
+ };
+
+ s.fmt(f)
}
}
@@ -3983,9 +4093,8 @@ impl TryToRustTy for FunctionSig {
// TODO: we might want to consider ignoring the reference return value.
let ret = utils::fnsig_return_ty(ctx, self);
let arguments = utils::fnsig_arguments(ctx, self);
- let abi = self.abi(ctx, None);
- match abi {
+ match self.abi(ctx, None) {
ClangAbi::Known(Abi::ThisCall)
if !ctx.options().rust_features().thiscall_abi =>
{
@@ -4004,7 +4113,13 @@ impl TryToRustTy for FunctionSig {
warn!("Skipping function with C-unwind ABI that isn't supported by the configured Rust target");
Ok(proc_macro2::TokenStream::new())
}
- _ => Ok(quote! {
+ ClangAbi::Known(Abi::EfiApi)
+ if !ctx.options().rust_features().abi_efiapi =>
+ {
+ warn!("Skipping function with efiapi ABI that isn't supported by the configured Rust target");
+ Ok(proc_macro2::TokenStream::new())
+ }
+ abi => Ok(quote! {
unsafe extern #abi fn ( #( #arguments ),* ) #ret
}),
}
@@ -4029,14 +4144,10 @@ impl CodeGenerator for Function {
let is_internal = matches!(self.linkage(), Linkage::Internal);
- if is_internal {
- if ctx.options().wrap_static_fns {
- result.items_to_serialize.push(item.id());
- } else {
- // We can't do anything with Internal functions if we are not wrapping them so just
- // avoid generating anything for them.
- return None;
- }
+ if is_internal && !ctx.options().wrap_static_fns {
+ // We can't do anything with Internal functions if we are not wrapping them so just
+ // avoid generating anything for them.
+ return None;
}
// Pure virtual methods have no actual symbol, so we can't generate
@@ -4111,23 +4222,54 @@ impl CodeGenerator for Function {
ClangAbi::Known(Abi::ThisCall)
if !ctx.options().rust_features().thiscall_abi =>
{
- warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
+ unsupported_abi_diagnostic::<false>(
+ name,
+ item.location(),
+ "thiscall",
+ ctx,
+ );
return None;
}
ClangAbi::Known(Abi::Vectorcall)
if !ctx.options().rust_features().vectorcall_abi =>
{
- warn!("Skipping function with vectorcall ABI that isn't supported by the configured Rust target");
+ unsupported_abi_diagnostic::<false>(
+ name,
+ item.location(),
+ "vectorcall",
+ ctx,
+ );
return None;
}
ClangAbi::Known(Abi::CUnwind)
if !ctx.options().rust_features().c_unwind_abi =>
{
- warn!("Skipping function with C-unwind ABI that isn't supported by the configured Rust target");
+ unsupported_abi_diagnostic::<false>(
+ name,
+ item.location(),
+ "C-unwind",
+ ctx,
+ );
+ return None;
+ }
+ ClangAbi::Known(Abi::EfiApi)
+ if !ctx.options().rust_features().abi_efiapi =>
+ {
+ unsupported_abi_diagnostic::<true>(
+ name,
+ item.location(),
+ "efiapi",
+ ctx,
+ );
return None;
}
ClangAbi::Known(Abi::Win64) if signature.is_variadic() => {
- warn!("Skipping variadic function with Win64 ABI that isn't supported");
+ unsupported_abi_diagnostic::<true>(
+ name,
+ item.location(),
+ "Win64",
+ ctx,
+ );
return None;
}
ClangAbi::Unknown(unknown_abi) => {
@@ -4139,6 +4281,10 @@ impl CodeGenerator for Function {
abi => abi,
};
+ if is_internal && ctx.options().wrap_static_fns {
+ result.items_to_serialize.push(item.id());
+ }
+
// Handle overloaded functions by giving each overload its own unique
// suffix.
let times_seen = result.overload_number(&canonical_name);
@@ -4147,16 +4293,21 @@ impl CodeGenerator for Function {
}
let mut has_link_name_attr = false;
- let link_name = mangled_name.unwrap_or(name);
- if !is_dynamic_function &&
- !utils::names_will_be_identical_after_mangling(
- &canonical_name,
- link_name,
- Some(abi),
- )
- {
- attributes.push(attributes::link_name(link_name));
+ if let Some(link_name) = self.link_name() {
+ attributes.push(attributes::link_name::<false>(link_name));
has_link_name_attr = true;
+ } else {
+ let link_name = mangled_name.unwrap_or(name);
+ if !is_dynamic_function &&
+ !utils::names_will_be_identical_after_mangling(
+ &canonical_name,
+ link_name,
+ Some(abi),
+ )
+ {
+ attributes.push(attributes::link_name::<false>(link_name));
+ has_link_name_attr = true;
+ }
}
// Unfortunately this can't piggyback on the `attributes` list because
@@ -4169,7 +4320,7 @@ impl CodeGenerator for Function {
if is_internal && ctx.options().wrap_static_fns && !has_link_name_attr {
let name = canonical_name.clone() + ctx.wrap_static_fns_suffix();
- attributes.push(attributes::link_name(&name));
+ attributes.push(attributes::link_name::<true>(&name));
}
let ident = ctx.rust_ident(canonical_name);
@@ -4205,6 +4356,51 @@ impl CodeGenerator for Function {
}
}
+fn unsupported_abi_diagnostic<const VARIADIC: bool>(
+ fn_name: &str,
+ _location: Option<&crate::clang::SourceLocation>,
+ abi: &str,
+ _ctx: &BindgenContext,
+) {
+ warn!(
+ "Skipping {}function `{}` with the {} ABI that isn't supported by the configured Rust target",
+ if VARIADIC { "variadic " } else { "" },
+ fn_name,
+ abi
+ );
+
+ #[cfg(feature = "experimental")]
+ if _ctx.options().emit_diagnostics {
+ use crate::diagnostics::{get_line, Diagnostic, Level, Slice};
+
+ let mut diag = Diagnostic::default();
+ diag
+ .with_title(format!(
+ "The `{}` {}function uses the {} ABI which is not supported by the configured Rust target.",
+ fn_name,
+ if VARIADIC { "variadic " } else { "" },
+ abi), Level::Warn)
+ .add_annotation("No code will be generated for this function.", Level::Warn)
+ .add_annotation(format!("The configured Rust version is {}.", String::from(_ctx.options().rust_target)), Level::Note);
+
+ if let Some(loc) = _location {
+ let (file, line, col, _) = loc.location();
+
+ if let Some(filename) = file.name() {
+ if let Ok(Some(source)) = get_line(&filename, line) {
+ let mut slice = Slice::default();
+ slice
+ .with_source(source)
+ .with_location(filename, line, col);
+ diag.add_slice(slice);
+ }
+ }
+ }
+
+ diag.display()
+ }
+}
+
fn objc_method_codegen(
ctx: &BindgenContext,
method: &ObjCMethod,
@@ -4226,13 +4422,12 @@ fn objc_method_codegen(
let fn_ret = utils::fnsig_return_ty(ctx, signature);
let sig = if method.is_class_method() {
- let fn_args = fn_args.clone();
quote! {
( #( #fn_args ),* ) #fn_ret
}
} else {
- let fn_args = fn_args.clone();
- let args = iter::once(quote! { &self }).chain(fn_args.into_iter());
+ let self_arr = [quote! { &self }];
+ let args = self_arr.iter().chain(fn_args.iter());
quote! {
( #( #args ),* ) #fn_ret
}
@@ -4476,8 +4671,7 @@ impl CodeGenerator for ObjCInterface {
pub(crate) fn codegen(
context: BindgenContext,
-) -> Result<(proc_macro2::TokenStream, BindgenOptions, Vec<String>), CodegenError>
-{
+) -> Result<(proc_macro2::TokenStream, BindgenOptions), CodegenError> {
context.gen(|context| {
let _t = context.timer("codegen");
let counter = Cell::new(0);
@@ -4536,7 +4730,7 @@ pub(crate) fn codegen(
})
}
-pub mod utils {
+pub(crate) mod utils {
use super::serialize::CSerialize;
use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque};
use crate::ir::context::BindgenContext;
@@ -4544,8 +4738,8 @@ pub mod utils {
use crate::ir::item::{Item, ItemCanonicalPath};
use crate::ir::ty::TypeKind;
use crate::{args_are_cpp, file_is_cpp};
- use proc_macro2;
use std::borrow::Cow;
+ use std::io::Write;
use std::mem;
use std::path::PathBuf;
use std::str::FromStr;
@@ -4570,7 +4764,7 @@ pub mod utils {
let dir = path.parent().unwrap();
if !dir.exists() {
- std::fs::create_dir_all(&dir)?;
+ std::fs::create_dir_all(dir)?;
}
let is_cpp = args_are_cpp(&context.options().clang_args) ||
@@ -4584,6 +4778,24 @@ pub mod utils {
let mut code = Vec::new();
+ if !context.options().input_headers.is_empty() {
+ for header in &context.options().input_headers {
+ writeln!(code, "#include \"{}\"", header)?;
+ }
+
+ writeln!(code)?;
+ }
+
+ if !context.options().input_header_contents.is_empty() {
+ for (name, contents) in &context.options().input_header_contents {
+ writeln!(code, "// {}\n{}", name, contents)?;
+ }
+
+ writeln!(code)?;
+ }
+
+ writeln!(code, "// Static wrappers\n")?;
+
for &id in &result.items_to_serialize {
let item = context.resolve_item(id);
item.serialize(context, (), &mut vec![], &mut code)?;
@@ -4594,7 +4806,7 @@ pub mod utils {
Ok(())
}
- pub fn prepend_bitfield_unit_type(
+ pub(crate) fn prepend_bitfield_unit_type(
ctx: &BindgenContext,
result: &mut Vec<proc_macro2::TokenStream>,
) {
@@ -4613,7 +4825,7 @@ pub mod utils {
result.extend(old_items);
}
- pub fn prepend_objc_header(
+ pub(crate) fn prepend_objc_header(
ctx: &BindgenContext,
result: &mut Vec<proc_macro2::TokenStream>,
) {
@@ -4638,7 +4850,7 @@ pub mod utils {
result.extend(old_items.into_iter());
}
- pub fn prepend_block_header(
+ pub(crate) fn prepend_block_header(
ctx: &BindgenContext,
result: &mut Vec<proc_macro2::TokenStream>,
) {
@@ -4657,7 +4869,7 @@ pub mod utils {
result.extend(old_items.into_iter());
}
- pub fn prepend_union_types(
+ pub(crate) fn prepend_union_types(
ctx: &BindgenContext,
result: &mut Vec<proc_macro2::TokenStream>,
) {
@@ -4769,7 +4981,7 @@ pub mod utils {
result.extend(old_items.into_iter());
}
- pub fn prepend_incomplete_array_types(
+ pub(crate) fn prepend_incomplete_array_types(
ctx: &BindgenContext,
result: &mut Vec<proc_macro2::TokenStream>,
) {
@@ -4845,7 +5057,9 @@ pub mod utils {
result.extend(old_items.into_iter());
}
- pub fn prepend_complex_type(result: &mut Vec<proc_macro2::TokenStream>) {
+ pub(crate) fn prepend_complex_type(
+ result: &mut Vec<proc_macro2::TokenStream>,
+ ) {
let complex_type = quote! {
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
#[repr(C)]
@@ -4860,7 +5074,7 @@ pub mod utils {
result.extend(old_items.into_iter());
}
- pub fn build_path(
+ pub(crate) fn build_path(
item: &Item,
ctx: &BindgenContext,
) -> error::Result<proc_macro2::TokenStream> {
@@ -4881,7 +5095,7 @@ pub mod utils {
}
}
- pub fn type_from_named(
+ pub(crate) fn type_from_named(
ctx: &BindgenContext,
name: &str,
) -> Option<proc_macro2::TokenStream> {
@@ -4949,14 +5163,14 @@ pub mod utils {
}
}
- pub fn fnsig_return_ty(
+ pub(crate) fn fnsig_return_ty(
ctx: &BindgenContext,
sig: &FunctionSig,
) -> proc_macro2::TokenStream {
fnsig_return_ty_internal(ctx, sig, /* include_arrow = */ true)
}
- pub fn fnsig_arguments(
+ pub(crate) fn fnsig_arguments(
ctx: &BindgenContext,
sig: &FunctionSig,
) -> Vec<proc_macro2::TokenStream> {
@@ -5029,7 +5243,7 @@ pub mod utils {
args
}
- pub fn fnsig_argument_identifiers(
+ pub(crate) fn fnsig_argument_identifiers(
ctx: &BindgenContext,
sig: &FunctionSig,
) -> Vec<proc_macro2::TokenStream> {
@@ -5058,7 +5272,7 @@ pub mod utils {
args
}
- pub fn fnsig_block(
+ pub(crate) fn fnsig_block(
ctx: &BindgenContext,
sig: &FunctionSig,
) -> proc_macro2::TokenStream {
diff --git a/codegen/postprocessing/merge_extern_blocks.rs b/codegen/postprocessing/merge_extern_blocks.rs
index 8dacedf..10fa0ec 100644
--- a/codegen/postprocessing/merge_extern_blocks.rs
+++ b/codegen/postprocessing/merge_extern_blocks.rs
@@ -1,68 +1,72 @@
use syn::{
- visit_mut::{visit_item_mod_mut, VisitMut},
- Item, ItemForeignMod, ItemMod,
+ visit_mut::{visit_file_mut, visit_item_mod_mut, VisitMut},
+ File, Item, ItemForeignMod, ItemMod,
};
-pub(super) fn merge_extern_blocks(item_mod: &mut ItemMod) {
- Visitor.visit_item_mod_mut(item_mod)
+pub(super) fn merge_extern_blocks(file: &mut File) {
+ Visitor.visit_file_mut(file)
}
struct Visitor;
impl VisitMut for Visitor {
+ fn visit_file_mut(&mut self, file: &mut File) {
+ visit_items(&mut file.items);
+ visit_file_mut(self, file)
+ }
+
fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
if let Some((_, ref mut items)) = item_mod.content {
- // Keep all the extern blocks in a different `Vec` for faster search.
- let mut extern_blocks = Vec::<ItemForeignMod>::new();
+ visit_items(items);
+ }
+ visit_item_mod_mut(self, item_mod)
+ }
+}
- for item in std::mem::take(items) {
- if let Item::ForeignMod(ItemForeignMod {
+fn visit_items(items: &mut Vec<Item>) {
+ // Keep all the extern blocks in a different `Vec` for faster search.
+ let mut extern_blocks = Vec::<ItemForeignMod>::new();
+
+ for item in std::mem::take(items) {
+ if let Item::ForeignMod(ItemForeignMod {
+ attrs,
+ abi,
+ brace_token,
+ unsafety,
+ items: extern_block_items,
+ }) = item
+ {
+ let mut exists = false;
+ for extern_block in &mut extern_blocks {
+ // Check if there is a extern block with the same ABI and
+ // attributes.
+ if extern_block.attrs == attrs && extern_block.abi == abi {
+ // Merge the items of the two blocks.
+ extern_block.items.extend_from_slice(&extern_block_items);
+ exists = true;
+ break;
+ }
+ }
+ // If no existing extern block had the same ABI and attributes, store
+ // it.
+ if !exists {
+ extern_blocks.push(ItemForeignMod {
attrs,
abi,
brace_token,
- items: extern_block_items,
unsafety,
- }) = item
- {
- let mut exists = false;
- for extern_block in &mut extern_blocks {
- // Check if there is a extern block with the same ABI and
- // attributes.
- if extern_block.attrs == attrs &&
- extern_block.abi == abi
- {
- // Merge the items of the two blocks.
- extern_block
- .items
- .extend_from_slice(&extern_block_items);
- exists = true;
- break;
- }
- }
- // If no existing extern block had the same ABI and attributes, store
- // it.
- if !exists {
- extern_blocks.push(ItemForeignMod {
- attrs,
- abi,
- brace_token,
- items: extern_block_items,
- unsafety,
- });
- }
- } else {
- // If the item is not an extern block, we don't have to do anything and just
- // push it back.
- items.push(item);
- }
- }
-
- // Move all the extern blocks alongside the rest of the items.
- for extern_block in extern_blocks {
- items.push(Item::ForeignMod(extern_block));
+ items: extern_block_items,
+ });
}
+ } else {
+ // If the item is not an extern block, we don't have to do anything and just
+ // push it back.
+ items.push(item);
}
+ }
- visit_item_mod_mut(self, item_mod)
+ // Move all the extern blocks alongside the rest of the items.
+ for extern_block in extern_blocks {
+ items.push(Item::ForeignMod(extern_block));
}
}
diff --git a/codegen/postprocessing/mod.rs b/codegen/postprocessing/mod.rs
index 1d5a498..9641698 100644
--- a/codegen/postprocessing/mod.rs
+++ b/codegen/postprocessing/mod.rs
@@ -1,6 +1,6 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
-use syn::{parse2, ItemMod};
+use syn::{parse2, File};
use crate::BindgenOptions;
@@ -12,7 +12,7 @@ use sort_semantically::sort_semantically;
struct PostProcessingPass {
should_run: fn(&BindgenOptions) -> bool,
- run: fn(&mut ItemMod),
+ run: fn(&mut File),
}
// TODO: This can be a const fn when mutable references are allowed in const
@@ -21,7 +21,7 @@ macro_rules! pass {
($pass:ident) => {
PostProcessingPass {
should_run: |options| options.$pass,
- run: |item_mod| $pass(item_mod),
+ run: |file| $pass(file),
}
};
}
@@ -33,34 +33,25 @@ pub(crate) fn postprocessing(
items: Vec<TokenStream>,
options: &BindgenOptions,
) -> TokenStream {
+ let items = items.into_iter().collect();
let require_syn = PASSES.iter().any(|pass| (pass.should_run)(options));
+
if !require_syn {
- return items.into_iter().collect();
+ return items;
}
- let module_wrapped_tokens =
- quote!(mod wrapper_for_postprocessing_hack { #( #items )* });
// This syn business is a hack, for now. This means that we are re-parsing already
// generated code using `syn` (as opposed to `quote`) because `syn` provides us more
// control over the elements.
- // One caveat is that some of the items coming from `quote`d output might have
- // multiple items within them. Hence, we have to wrap the incoming in a `mod`.
// The `unwrap` here is deliberate because bindgen should generate valid rust items at all
// times.
- let mut item_mod = parse2::<ItemMod>(module_wrapped_tokens).unwrap();
+ let mut file = parse2::<File>(items).unwrap();
for pass in PASSES {
if (pass.should_run)(options) {
- (pass.run)(&mut item_mod);
+ (pass.run)(&mut file);
}
}
- let synful_items = item_mod
- .content
- .map(|(_, items)| items)
- .unwrap_or_default()
- .into_iter()
- .map(|item| item.into_token_stream());
-
- quote! { #( #synful_items )* }
+ file.into_token_stream()
}
diff --git a/codegen/postprocessing/sort_semantically.rs b/codegen/postprocessing/sort_semantically.rs
index 71fb75c..be94ce6 100644
--- a/codegen/postprocessing/sort_semantically.rs
+++ b/codegen/postprocessing/sort_semantically.rs
@@ -1,37 +1,46 @@
use syn::{
- visit_mut::{visit_item_mod_mut, VisitMut},
- Item, ItemMod,
+ visit_mut::{visit_file_mut, visit_item_mod_mut, VisitMut},
+ File, Item, ItemMod,
};
-pub(super) fn sort_semantically(item_mod: &mut ItemMod) {
- Visitor.visit_item_mod_mut(item_mod)
+pub(super) fn sort_semantically(file: &mut File) {
+ Visitor.visit_file_mut(file)
}
struct Visitor;
impl VisitMut for Visitor {
+ fn visit_file_mut(&mut self, file: &mut File) {
+ visit_items(&mut file.items);
+ visit_file_mut(self, file)
+ }
+
fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
if let Some((_, ref mut items)) = item_mod.content {
- items.sort_by_key(|item| match item {
- Item::Type(_) => 0,
- Item::Struct(_) => 1,
- Item::Const(_) => 2,
- Item::Fn(_) => 3,
- Item::Enum(_) => 4,
- Item::Union(_) => 5,
- Item::Static(_) => 6,
- Item::Trait(_) => 7,
- Item::TraitAlias(_) => 8,
- Item::Impl(_) => 9,
- Item::Mod(_) => 10,
- Item::Use(_) => 11,
- Item::Verbatim(_) => 12,
- Item::ExternCrate(_) => 13,
- Item::ForeignMod(_) => 14,
- Item::Macro(_) => 15,
- _ => 18,
- });
+ visit_items(items);
}
visit_item_mod_mut(self, item_mod)
}
}
+
+fn visit_items(items: &mut [Item]) {
+ items.sort_by_key(|item| match item {
+ Item::Type(_) => 0,
+ Item::Struct(_) => 1,
+ Item::Const(_) => 2,
+ Item::Fn(_) => 3,
+ Item::Enum(_) => 4,
+ Item::Union(_) => 5,
+ Item::Static(_) => 6,
+ Item::Trait(_) => 7,
+ Item::TraitAlias(_) => 8,
+ Item::Impl(_) => 9,
+ Item::Mod(_) => 10,
+ Item::Use(_) => 11,
+ Item::Verbatim(_) => 12,
+ Item::ExternCrate(_) => 13,
+ Item::ForeignMod(_) => 14,
+ Item::Macro(_) => 15,
+ _ => 18,
+ });
+}
diff --git a/codegen/serialize.rs b/codegen/serialize.rs
index 217098e..ac62023 100644
--- a/codegen/serialize.rs
+++ b/codegen/serialize.rs
@@ -44,12 +44,10 @@ impl<'a> CSerialize<'a> for Item {
ItemKind::Function(func) => {
func.serialize(ctx, self, stack, writer)
}
- kind => {
- return Err(CodegenError::Serialize {
- msg: format!("Cannot serialize item kind {:?}", kind),
- loc: get_loc(self),
- });
- }
+ kind => Err(CodegenError::Serialize {
+ msg: format!("Cannot serialize item kind {:?}", kind),
+ loc: get_loc(self),
+ }),
}
}
}
@@ -107,36 +105,10 @@ impl<'a> CSerialize<'a> for Function {
// The function's return type
let ret_ty = signature.return_type();
- // Write `ret_ty wrap_name(args) asm("wrap_name");`
- ret_ty.serialize(ctx, (), stack, writer)?;
- write!(writer, " {}(", wrap_name)?;
- if args.is_empty() {
- write!(writer, "void")?;
- } else {
- serialize_sep(
- ", ",
- args.iter(),
- ctx,
- writer,
- |(name, type_id), ctx, buf| {
- type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
- },
- )?;
- }
- writeln!(writer, ") asm(\"{}\");", wrap_name)?;
-
// Write `ret_ty wrap_name(args) { return name(arg_names)' }`
ret_ty.serialize(ctx, (), stack, writer)?;
write!(writer, " {}(", wrap_name)?;
- serialize_sep(
- ", ",
- args.iter(),
- ctx,
- writer,
- |(name, type_id), _, buf| {
- type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
- },
- )?;
+ serialize_args(&args, ctx, writer)?;
write!(writer, ") {{ return {}(", name)?;
serialize_sep(", ", args.iter(), ctx, writer, |(name, _), _, buf| {
write!(buf, "{}", name).map_err(From::from)
@@ -313,6 +285,14 @@ impl<'a> CSerialize<'a> for Type {
CompKind::Union => write!(writer, "union {}", name)?,
};
}
+ TypeKind::Enum(_enum_ty) => {
+ if self.is_const() {
+ write!(writer, "const ")?;
+ }
+
+ let name = item.canonical_name(ctx);
+ write!(writer, "enum {}", name)?;
+ }
ty => {
return Err(CodegenError::Serialize {
msg: format!("Cannot serialize type kind {:?}", ty),
@@ -332,6 +312,28 @@ impl<'a> CSerialize<'a> for Type {
}
}
+fn serialize_args<W: Write>(
+ args: &[(String, TypeId)],
+ ctx: &BindgenContext,
+ writer: &mut W,
+) -> Result<(), CodegenError> {
+ if args.is_empty() {
+ write!(writer, "void")?;
+ } else {
+ serialize_sep(
+ ", ",
+ args.iter(),
+ ctx,
+ writer,
+ |(name, type_id), ctx, buf| {
+ type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
+ },
+ )?;
+ }
+
+ Ok(())
+}
+
fn serialize_sep<
W: Write,
F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
diff --git a/codegen/struct_layout.rs b/codegen/struct_layout.rs
index ddac1b0..cca4a59 100644
--- a/codegen/struct_layout.rs
+++ b/codegen/struct_layout.rs
@@ -13,7 +13,7 @@ const MAX_GUARANTEED_ALIGN: usize = 8;
/// Trace the layout of struct.
#[derive(Debug)]
-pub struct StructLayoutTracker<'a> {
+pub(crate) struct StructLayoutTracker<'a> {
name: &'a str,
ctx: &'a BindgenContext,
comp: &'a CompInfo,
@@ -29,7 +29,7 @@ pub struct StructLayoutTracker<'a> {
}
/// Returns a size aligned to a given value.
-pub fn align_to(size: usize, align: usize) -> usize {
+pub(crate) fn align_to(size: usize, align: usize) -> usize {
if align == 0 {
return size;
}
@@ -43,7 +43,7 @@ pub fn align_to(size: usize, align: usize) -> usize {
}
/// Returns the lower power of two byte count that can hold at most n bits.
-pub fn bytes_from_bits_pow2(mut n: usize) -> usize {
+pub(crate) fn bytes_from_bits_pow2(mut n: usize) -> usize {
if n == 0 {
return 0;
}
@@ -83,7 +83,7 @@ fn test_bytes_from_bits_pow2() {
}
impl<'a> StructLayoutTracker<'a> {
- pub fn new(
+ pub(crate) fn new(
ctx: &'a BindgenContext,
comp: &'a CompInfo,
ty: &'a Type,
@@ -109,15 +109,15 @@ impl<'a> StructLayoutTracker<'a> {
}
}
- pub fn can_copy_union_fields(&self) -> bool {
+ pub(crate) fn can_copy_union_fields(&self) -> bool {
self.can_copy_union_fields
}
- pub fn is_rust_union(&self) -> bool {
+ pub(crate) fn is_rust_union(&self) -> bool {
self.is_rust_union
}
- pub fn saw_vtable(&mut self) {
+ pub(crate) fn saw_vtable(&mut self) {
debug!("saw vtable for {}", self.name);
let ptr_size = self.ctx.target_pointer_size();
@@ -126,7 +126,7 @@ impl<'a> StructLayoutTracker<'a> {
self.max_field_align = ptr_size;
}
- pub fn saw_base(&mut self, base_ty: &Type) {
+ pub(crate) fn saw_base(&mut self, base_ty: &Type) {
debug!("saw base for {}", self.name);
if let Some(layout) = base_ty.layout(self.ctx) {
self.align_to_latest_field(layout);
@@ -137,7 +137,7 @@ impl<'a> StructLayoutTracker<'a> {
}
}
- pub fn saw_bitfield_unit(&mut self, layout: Layout) {
+ pub(crate) fn saw_bitfield_unit(&mut self, layout: Layout) {
debug!("saw bitfield unit for {}: {:?}", self.name, layout);
self.align_to_latest_field(layout);
@@ -159,7 +159,7 @@ impl<'a> StructLayoutTracker<'a> {
/// Returns a padding field if necessary for a given new field _before_
/// adding that field.
- pub fn saw_field(
+ pub(crate) fn saw_field(
&mut self,
field_name: &str,
field_ty: &Type,
@@ -189,7 +189,7 @@ impl<'a> StructLayoutTracker<'a> {
self.saw_field_with_layout(field_name, field_layout, field_offset)
}
- pub fn saw_field_with_layout(
+ pub(crate) fn saw_field_with_layout(
&mut self,
field_name: &str,
field_layout: Layout,
@@ -274,7 +274,7 @@ impl<'a> StructLayoutTracker<'a> {
padding_layout.map(|layout| self.padding_field(layout))
}
- pub fn add_tail_padding(
+ pub(crate) fn add_tail_padding(
&mut self,
comp_name: &str,
comp_layout: Layout,
@@ -305,7 +305,7 @@ impl<'a> StructLayoutTracker<'a> {
Some(self.padding_field(Layout::new(size, 0)))
}
- pub fn pad_struct(
+ pub(crate) fn pad_struct(
&mut self,
layout: Layout,
) -> Option<proc_macro2::TokenStream> {
@@ -360,7 +360,7 @@ impl<'a> StructLayoutTracker<'a> {
}
}
- pub fn requires_explicit_align(&self, layout: Layout) -> bool {
+ pub(crate) fn requires_explicit_align(&self, layout: Layout) -> bool {
let repr_align = self.ctx.options().rust_features().repr_align;
// Always force explicit repr(align) for stuff more than 16-byte aligned
diff --git a/diagnostics.rs b/diagnostics.rs
new file mode 100644
index 0000000..f765afe
--- /dev/null
+++ b/diagnostics.rs
@@ -0,0 +1,189 @@
+//! Types and function used to emit pretty diagnostics for `bindgen`.
+//!
+//! The entry point of this module is the [`Diagnostic`] type.
+
+use std::fmt::Write;
+use std::io::{self, BufRead, BufReader};
+use std::{borrow::Cow, fs::File};
+
+use annotate_snippets::{
+ display_list::{DisplayList, FormatOptions},
+ snippet::{Annotation, Slice as ExtSlice, Snippet},
+};
+
+use annotate_snippets::snippet::AnnotationType;
+
+#[derive(Clone, Copy, Debug)]
+pub(crate) enum Level {
+ Error,
+ Warn,
+ Info,
+ Note,
+ Help,
+}
+
+impl From<Level> for AnnotationType {
+ fn from(level: Level) -> Self {
+ match level {
+ Level::Error => Self::Error,
+ Level::Warn => Self::Warning,
+ Level::Info => Self::Info,
+ Level::Note => Self::Note,
+ Level::Help => Self::Help,
+ }
+ }
+}
+
+/// A `bindgen` diagnostic.
+#[derive(Default)]
+pub(crate) struct Diagnostic<'a> {
+ title: Option<(Cow<'a, str>, Level)>,
+ slices: Vec<Slice<'a>>,
+ footer: Vec<(Cow<'a, str>, Level)>,
+}
+
+impl<'a> Diagnostic<'a> {
+ /// Add a title to the diagnostic and set its type.
+ pub(crate) fn with_title(
+ &mut self,
+ title: impl Into<Cow<'a, str>>,
+ level: Level,
+ ) -> &mut Self {
+ self.title = Some((title.into(), level));
+ self
+ }
+
+ /// Add a slice of source code to the diagnostic.
+ pub(crate) fn add_slice(&mut self, slice: Slice<'a>) -> &mut Self {
+ self.slices.push(slice);
+ self
+ }
+
+ /// Add a footer annotation to the diagnostic. This annotation will have its own type.
+ pub(crate) fn add_annotation(
+ &mut self,
+ msg: impl Into<Cow<'a, str>>,
+ level: Level,
+ ) -> &mut Self {
+ self.footer.push((msg.into(), level));
+ self
+ }
+
+ /// Print this diagnostic.
+ ///
+ /// The diagnostic is printed using `cargo:warning` if `bindgen` is being invoked by a build
+ /// script or using `eprintln` otherwise.
+ pub(crate) fn display(&self) {
+ std::thread_local! {
+ static INVOKED_BY_BUILD_SCRIPT: bool = std::env::var_os("CARGO_CFG_TARGET_ARCH").is_some();
+ }
+
+ let mut title = None;
+ let mut footer = vec![];
+ let mut slices = vec![];
+ if let Some((msg, level)) = &self.title {
+ title = Some(Annotation {
+ id: Some("bindgen"),
+ label: Some(msg.as_ref()),
+ annotation_type: (*level).into(),
+ })
+ }
+
+ for (msg, level) in &self.footer {
+ footer.push(Annotation {
+ id: None,
+ label: Some(msg.as_ref()),
+ annotation_type: (*level).into(),
+ });
+ }
+
+ // add additional info that this is generated by bindgen
+ // so as to not confuse with rustc warnings
+ footer.push(Annotation {
+ id: None,
+ label: Some("This diagnostic was generated by bindgen."),
+ annotation_type: AnnotationType::Info,
+ });
+
+ for slice in &self.slices {
+ if let Some(source) = &slice.source {
+ slices.push(ExtSlice {
+ source: source.as_ref(),
+ line_start: slice.line.unwrap_or_default(),
+ origin: slice.filename.as_deref(),
+ annotations: vec![],
+ fold: false,
+ })
+ }
+ }
+
+ let snippet = Snippet {
+ title,
+ footer,
+ slices,
+ opt: FormatOptions {
+ color: true,
+ ..Default::default()
+ },
+ };
+ let dl = DisplayList::from(snippet);
+
+ if INVOKED_BY_BUILD_SCRIPT.with(Clone::clone) {
+ // This is just a hack which hides the `warning:` added by cargo at the beginning of
+ // every line. This should be fine as our diagnostics already have a colorful title.
+ // FIXME (pvdrz): Could it be that this doesn't work in other languages?
+ let hide_warning = "\r \r";
+ let string = dl.to_string();
+ for line in string.lines() {
+ println!("cargo:warning={}{}", hide_warning, line);
+ }
+ } else {
+ eprintln!("{}\n", dl);
+ }
+ }
+}
+
+/// A slice of source code.
+#[derive(Default)]
+pub(crate) struct Slice<'a> {
+ source: Option<Cow<'a, str>>,
+ filename: Option<String>,
+ line: Option<usize>,
+}
+
+impl<'a> Slice<'a> {
+ /// Set the source code.
+ pub(crate) fn with_source(
+ &mut self,
+ source: impl Into<Cow<'a, str>>,
+ ) -> &mut Self {
+ self.source = Some(source.into());
+ self
+ }
+
+ /// Set the file, line and column.
+ pub(crate) fn with_location(
+ &mut self,
+ mut name: String,
+ line: usize,
+ col: usize,
+ ) -> &mut Self {
+ write!(name, ":{}:{}", line, col)
+ .expect("Writing to a string cannot fail");
+ self.filename = Some(name);
+ self.line = Some(line);
+ self
+ }
+}
+
+pub(crate) fn get_line(
+ filename: &str,
+ line: usize,
+) -> io::Result<Option<String>> {
+ let file = BufReader::new(File::open(filename)?);
+ if let Some(line) = file.lines().nth(line.wrapping_sub(1)) {
+ return line.map(Some);
+ }
+
+ Ok(None)
+}
diff --git a/features.rs b/features.rs
index 4fee5d6..fe6f415 100644
--- a/features.rs
+++ b/features.rs
@@ -1,7 +1,7 @@
//! Contains code for selecting features
-#![deny(missing_docs)]
#![deny(unused_extern_crates)]
+#![deny(clippy::missing_docs_in_private_items)]
#![allow(deprecated)]
use std::io;
@@ -131,6 +131,9 @@ macro_rules! rust_target_base {
/// Rust stable 1.64
/// * `core_ffi_c` ([Tracking issue](https://github.com/rust-lang/rust/issues/94501))
=> Stable_1_64 => 1.64;
+ /// Rust stable 1.68
+ /// * `abi_efiapi` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/65815))
+ => Stable_1_68 => 1.68;
/// Nightly rust
/// * `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
/// * `vectorcall` calling convention (no tracking issue)
@@ -144,7 +147,7 @@ rust_target_base!(rust_target_def);
rust_target_base!(rust_target_values_def);
/// Latest stable release of Rust
-pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_64;
+pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_68;
/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules! rust_feature_def {
@@ -241,6 +244,9 @@ rust_feature_def!(
Stable_1_64 {
=> core_ffi_c;
}
+ Stable_1_68 {
+ => abi_efiapi;
+ }
Nightly {
=> thiscall_abi;
=> vectorcall_abi;
diff --git a/ir/analysis/derive.rs b/ir/analysis/derive.rs
index d888cd5..d8d29ed 100644
--- a/ir/analysis/derive.rs
+++ b/ir/analysis/derive.rs
@@ -61,7 +61,7 @@ pub enum DeriveTrait {
/// * For all other (simple) types, compiler and standard library limitations
/// dictate whether the trait is implemented.
#[derive(Debug, Clone)]
-pub struct CannotDerive<'ctx> {
+pub(crate) struct CannotDerive<'ctx> {
ctx: &'ctx BindgenContext,
derive_trait: DeriveTrait,
@@ -172,7 +172,7 @@ impl<'ctx> CannotDerive<'ctx> {
if item.is_opaque(self.ctx, &()) {
if !self.derive_trait.can_derive_union() &&
ty.is_union() &&
- self.ctx.options().rust_features().untagged_union
+ self.ctx.options().untagged_union
{
trace!(
" cannot derive {} for Rust unions",
@@ -322,7 +322,7 @@ impl<'ctx> CannotDerive<'ctx> {
if info.kind() == CompKind::Union {
if self.derive_trait.can_derive_union() {
- if self.ctx.options().rust_features().untagged_union &&
+ if self.ctx.options().untagged_union &&
// https://github.com/rust-lang/rust/issues/36640
(!info.self_template_params(self.ctx).is_empty() ||
!item.all_template_params(self.ctx).is_empty())
@@ -334,7 +334,7 @@ impl<'ctx> CannotDerive<'ctx> {
}
// fall through to be same as non-union handling
} else {
- if self.ctx.options().rust_features().untagged_union {
+ if self.ctx.options().untagged_union {
trace!(
" cannot derive {} for Rust unions",
self.derive_trait
@@ -722,7 +722,7 @@ impl<'ctx> From<CannotDerive<'ctx>> for HashMap<ItemId, CanDerive> {
///
/// Elements that are not `CanDerive::Yes` are kept in the set, so that it
/// represents all items that cannot derive.
-pub fn as_cannot_derive_set(
+pub(crate) fn as_cannot_derive_set(
can_derive: HashMap<ItemId, CanDerive>,
) -> HashSet<ItemId> {
can_derive
diff --git a/ir/analysis/has_destructor.rs b/ir/analysis/has_destructor.rs
index 74fd73d..cbcbe55 100644
--- a/ir/analysis/has_destructor.rs
+++ b/ir/analysis/has_destructor.rs
@@ -22,7 +22,7 @@ use crate::{HashMap, HashSet};
/// * If T is the type of a field, that field has a destructor if it's not a bitfield,
/// and if T has a destructor.
#[derive(Debug, Clone)]
-pub struct HasDestructorAnalysis<'ctx> {
+pub(crate) struct HasDestructorAnalysis<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation. Everything in this
diff --git a/ir/analysis/has_float.rs b/ir/analysis/has_float.rs
index bbf2126..219c5a5 100644
--- a/ir/analysis/has_float.rs
+++ b/ir/analysis/has_float.rs
@@ -22,7 +22,7 @@ use crate::{HashMap, HashSet};
/// float if any of the template arguments or template definition
/// has.
#[derive(Debug, Clone)]
-pub struct HasFloat<'ctx> {
+pub(crate) struct HasFloat<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation. Everything in this
diff --git a/ir/analysis/has_type_param_in_array.rs b/ir/analysis/has_type_param_in_array.rs
index aa52304..088c08f 100644
--- a/ir/analysis/has_type_param_in_array.rs
+++ b/ir/analysis/has_type_param_in_array.rs
@@ -22,7 +22,7 @@ use crate::{HashMap, HashSet};
/// type parameter in array if any of the template arguments or template definition
/// has.
#[derive(Debug, Clone)]
-pub struct HasTypeParameterInArray<'ctx> {
+pub(crate) struct HasTypeParameterInArray<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation. Everything in this
diff --git a/ir/analysis/has_vtable.rs b/ir/analysis/has_vtable.rs
index 8ac47a6..980a551 100644
--- a/ir/analysis/has_vtable.rs
+++ b/ir/analysis/has_vtable.rs
@@ -10,7 +10,7 @@ use std::ops;
/// The result of the `HasVtableAnalysis` for an individual item.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub enum HasVtableResult {
+pub(crate) enum HasVtableResult {
/// The item does not have a vtable pointer.
No,
@@ -30,7 +30,7 @@ impl Default for HasVtableResult {
impl HasVtableResult {
/// Take the least upper bound of `self` and `rhs`.
- pub fn join(self, rhs: Self) -> Self {
+ pub(crate) fn join(self, rhs: Self) -> Self {
cmp::max(self, rhs)
}
}
@@ -60,7 +60,7 @@ impl ops::BitOrAssign for HasVtableResult {
/// * If T is an instantiation of an abstract template definition, T has
/// vtable if template definition has vtable
#[derive(Debug, Clone)]
-pub struct HasVtableAnalysis<'ctx> {
+pub(crate) struct HasVtableAnalysis<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation. Everything in this
@@ -230,7 +230,7 @@ impl<'ctx> From<HasVtableAnalysis<'ctx>> for HashMap<ItemId, HasVtableResult> {
/// This is not for _computing_ whether the thing has a vtable, it is for
/// looking up the results of the HasVtableAnalysis's computations for a
/// specific thing.
-pub trait HasVtable {
+pub(crate) trait HasVtable {
/// Return `true` if this thing has vtable, `false` otherwise.
fn has_vtable(&self, ctx: &BindgenContext) -> bool;
diff --git a/ir/analysis/mod.rs b/ir/analysis/mod.rs
index 40dfc6d..0263088 100644
--- a/ir/analysis/mod.rs
+++ b/ir/analysis/mod.rs
@@ -39,19 +39,24 @@
// Re-export individual analyses.
mod template_params;
-pub use self::template_params::UsedTemplateParameters;
+pub(crate) use self::template_params::UsedTemplateParameters;
mod derive;
-pub use self::derive::{as_cannot_derive_set, CannotDerive, DeriveTrait};
+pub use self::derive::DeriveTrait;
+pub(crate) use self::derive::{as_cannot_derive_set, CannotDerive};
mod has_vtable;
-pub use self::has_vtable::{HasVtable, HasVtableAnalysis, HasVtableResult};
+pub(crate) use self::has_vtable::{
+ HasVtable, HasVtableAnalysis, HasVtableResult,
+};
mod has_destructor;
-pub use self::has_destructor::HasDestructorAnalysis;
+pub(crate) use self::has_destructor::HasDestructorAnalysis;
mod has_type_param_in_array;
-pub use self::has_type_param_in_array::HasTypeParameterInArray;
+pub(crate) use self::has_type_param_in_array::HasTypeParameterInArray;
mod has_float;
-pub use self::has_float::HasFloat;
+pub(crate) use self::has_float::HasFloat;
mod sizedness;
-pub use self::sizedness::{Sizedness, SizednessAnalysis, SizednessResult};
+pub(crate) use self::sizedness::{
+ Sizedness, SizednessAnalysis, SizednessResult,
+};
use crate::ir::context::{BindgenContext, ItemId};
@@ -73,7 +78,7 @@ use std::ops;
///
/// For a simple example analysis, see the `ReachableFrom` type in the `tests`
/// module below.
-pub trait MonotoneFramework: Sized + fmt::Debug {
+pub(crate) trait MonotoneFramework: Sized + fmt::Debug {
/// The type of node in our dependency graph.
///
/// This is just generic (and not `ItemId`) so that we can easily unit test
@@ -121,7 +126,7 @@ pub trait MonotoneFramework: Sized + fmt::Debug {
/// Whether an analysis's `constrain` function modified the incremental results
/// or not.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum ConstrainResult {
+pub(crate) enum ConstrainResult {
/// The incremental results were updated, and the fix-point computation
/// should continue.
Changed,
@@ -155,7 +160,7 @@ impl ops::BitOrAssign for ConstrainResult {
}
/// Run an analysis in the monotone framework.
-pub fn analyze<Analysis>(extra: Analysis::Extra) -> Analysis::Output
+pub(crate) fn analyze<Analysis>(extra: Analysis::Extra) -> Analysis::Output
where
Analysis: MonotoneFramework,
{
@@ -174,7 +179,7 @@ where
}
/// Generate the dependency map for analysis
-pub fn generate_dependencies<F>(
+pub(crate) fn generate_dependencies<F>(
ctx: &BindgenContext,
consider_edge: F,
) -> HashMap<ItemId, Vec<ItemId>>
diff --git a/ir/analysis/sizedness.rs b/ir/analysis/sizedness.rs
index 251c374..995d700 100644
--- a/ir/analysis/sizedness.rs
+++ b/ir/analysis/sizedness.rs
@@ -25,7 +25,7 @@ use std::{cmp, ops};
/// We initially assume that all types are `ZeroSized` and then update our
/// understanding as we learn more about each type.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub enum SizednessResult {
+pub(crate) enum SizednessResult {
/// The type is zero-sized.
///
/// This means that if it is a C++ type, and is not being used as a base
@@ -52,7 +52,7 @@ pub enum SizednessResult {
/// have an `_address` byte inserted.
///
/// We don't properly handle this situation correctly right now:
- /// https://github.com/rust-lang/rust-bindgen/issues/586
+ /// <https://github.com/rust-lang/rust-bindgen/issues/586>
DependsOnTypeParam,
/// Has some size that is known to be greater than zero. That doesn't mean
@@ -70,7 +70,7 @@ impl Default for SizednessResult {
impl SizednessResult {
/// Take the least upper bound of `self` and `rhs`.
- pub fn join(self, rhs: Self) -> Self {
+ pub(crate) fn join(self, rhs: Self) -> Self {
cmp::max(self, rhs)
}
}
@@ -102,7 +102,7 @@ impl ops::BitOrAssign for SizednessResult {
///
/// * For type parameters, `DependsOnTypeParam` is assigned.
#[derive(Debug)]
-pub struct SizednessAnalysis<'ctx> {
+pub(crate) struct SizednessAnalysis<'ctx> {
ctx: &'ctx BindgenContext,
dependencies: HashMap<TypeId, Vec<TypeId>>,
// Incremental results of the analysis. Missing entries are implicitly
@@ -346,11 +346,11 @@ impl<'ctx> From<SizednessAnalysis<'ctx>> for HashMap<TypeId, SizednessResult> {
}
}
-/// A convenience trait for querying whether some type or id is sized.
+/// A convenience trait for querying whether some type or ID is sized.
///
/// This is not for _computing_ whether the thing is sized, it is for looking up
/// the results of the `Sizedness` analysis's computations for a specific thing.
-pub trait Sizedness {
+pub(crate) trait Sizedness {
/// Get the sizedness of this type.
fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult;
diff --git a/ir/analysis/template_params.rs b/ir/analysis/template_params.rs
index f4f0c59..3e6cd5e 100644
--- a/ir/analysis/template_params.rs
+++ b/ir/analysis/template_params.rs
@@ -14,7 +14,7 @@
//! If we generate the naive Rust code for this alias, we get:
//!
//! ```ignore
-//! pub type Fml<T> = ::std::os::raw::int;
+//! pub(crate) type Fml<T> = ::std::os::raw::int;
//! ```
//!
//! And this is rejected by `rustc` due to the unused type parameter.
@@ -146,7 +146,7 @@ use crate::{HashMap, HashSet};
/// specially; see `constrain_instantiation_of_blocklisted_template` and its
/// documentation for details.
#[derive(Debug, Clone)]
-pub struct UsedTemplateParameters<'ctx> {
+pub(crate) struct UsedTemplateParameters<'ctx> {
ctx: &'ctx BindgenContext,
// The Option is only there for temporary moves out of the hash map. See the
@@ -329,7 +329,7 @@ impl<'ctx> UsedTemplateParameters<'ctx> {
}
}
- /// The join operation on our lattice: the set union of all of this id's
+ /// The join operation on our lattice: the set union of all of this ID's
/// successors.
fn constrain_join(&self, used_by_this_id: &mut ItemSet, item: &Item) {
trace!(" other item: join with successors' usage");
@@ -518,7 +518,7 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> {
// exiting this method.
extra_assert!(self.used.values().all(|v| v.is_some()));
- // Take the set for this id out of the hash map while we mutate it based
+ // Take the set for this ID out of the hash map while we mutate it based
// on other hash map entries. We *must* put it back into the hash map at
// the end of this method. This allows us to side-step HashMap's lack of
// an analog to slice::split_at_mut.
diff --git a/ir/annotations.rs b/ir/annotations.rs
index 288c11e..423f6c4 100644
--- a/ir/annotations.rs
+++ b/ir/annotations.rs
@@ -4,11 +4,55 @@
//! replace other types with, mark as opaque, etc. This module deals with all of
//! that stuff.
+use std::str::FromStr;
+
use crate::clang;
+/// What kind of visibility modifer should be used for a struct or field?
+#[derive(Copy, PartialEq, Eq, Clone, Debug)]
+pub enum FieldVisibilityKind {
+ /// Fields are marked as private, i.e., struct Foo {bar: bool}
+ Private,
+ /// Fields are marked as crate public, i.e., struct Foo {pub(crate) bar: bool}
+ PublicCrate,
+ /// Fields are marked as public, i.e., struct Foo {pub bar: bool}
+ Public,
+}
+
+impl FromStr for FieldVisibilityKind {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "private" => Ok(Self::Private),
+ "crate" => Ok(Self::PublicCrate),
+ "public" => Ok(Self::Public),
+ _ => Err(format!("Invalid visibility kind: `{}`", s)),
+ }
+ }
+}
+
+impl std::fmt::Display for FieldVisibilityKind {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let s = match self {
+ FieldVisibilityKind::Private => "private",
+ FieldVisibilityKind::PublicCrate => "crate",
+ FieldVisibilityKind::Public => "public",
+ };
+
+ s.fmt(f)
+ }
+}
+
+impl Default for FieldVisibilityKind {
+ fn default() -> Self {
+ FieldVisibilityKind::Public
+ }
+}
+
/// What kind of accessor should we provide for a field?
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
-pub enum FieldAccessorKind {
+pub(crate) enum FieldAccessorKind {
/// No accessor.
None,
/// Plain accessor.
@@ -21,12 +65,9 @@ pub enum FieldAccessorKind {
/// Annotations for a given item, or a field.
///
-/// You can see the kind of comments that are accepted in the Doxygen
-/// documentation:
-///
-/// http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
+/// You can see the kind of comments that are accepted in the [Doxygen documentation](https://www.doxygen.nl/manual/docblocks.html).
#[derive(Default, Clone, PartialEq, Eq, Debug)]
-pub struct Annotations {
+pub(crate) struct Annotations {
/// Whether this item is marked as opaque. Only applies to types.
opaque: bool,
/// Whether this item should be hidden from the output. Only applies to
@@ -42,11 +83,11 @@ pub struct Annotations {
disallow_debug: bool,
/// Manually disable deriving/implement default on this type.
disallow_default: bool,
- /// Whether to add a #[must_use] annotation to this type.
+ /// Whether to add a `#[must_use]` annotation to this type.
must_use_type: bool,
- /// Whether fields should be marked as private or not. You can set this on
+ /// Visibility of struct fields. You can set this on
/// structs (it will apply to all the fields), or individual fields.
- private_fields: Option<bool>,
+ visibility_kind: Option<FieldVisibilityKind>,
/// The kind of accessor this field will have. Also can be applied to
/// structs so all the fields inside share it by default.
accessor_kind: Option<FieldAccessorKind>,
@@ -80,7 +121,7 @@ fn parse_accessor(s: &str) -> FieldAccessorKind {
impl Annotations {
/// Construct new annotations for the given cursor and its bindgen comments
/// (if any).
- pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
+ pub(crate) fn new(cursor: &clang::Cursor) -> Option<Annotations> {
let mut anno = Annotations::default();
let mut matched_one = false;
anno.parse(&cursor.comment(), &mut matched_one);
@@ -93,12 +134,12 @@ impl Annotations {
}
/// Should this type be hidden?
- pub fn hide(&self) -> bool {
+ pub(crate) fn hide(&self) -> bool {
self.hide
}
/// Should this type be opaque?
- pub fn opaque(&self) -> bool {
+ pub(crate) fn opaque(&self) -> bool {
self.opaque
}
@@ -124,42 +165,42 @@ impl Annotations {
/// ```
///
/// That is, code for `Foo` is used to generate `Bar`.
- pub fn use_instead_of(&self) -> Option<&[String]> {
+ pub(crate) fn use_instead_of(&self) -> Option<&[String]> {
self.use_instead_of.as_deref()
}
/// The list of derives that have been specified in this annotation.
- pub fn derives(&self) -> &[String] {
+ pub(crate) fn derives(&self) -> &[String] {
&self.derives
}
/// Should we avoid implementing the `Copy` trait?
- pub fn disallow_copy(&self) -> bool {
+ pub(crate) fn disallow_copy(&self) -> bool {
self.disallow_copy
}
/// Should we avoid implementing the `Debug` trait?
- pub fn disallow_debug(&self) -> bool {
+ pub(crate) fn disallow_debug(&self) -> bool {
self.disallow_debug
}
/// Should we avoid implementing the `Default` trait?
- pub fn disallow_default(&self) -> bool {
+ pub(crate) fn disallow_default(&self) -> bool {
self.disallow_default
}
/// Should this type get a `#[must_use]` annotation?
- pub fn must_use_type(&self) -> bool {
+ pub(crate) fn must_use_type(&self) -> bool {
self.must_use_type
}
- /// Should the fields be private?
- pub fn private_fields(&self) -> Option<bool> {
- self.private_fields
+ /// What kind of accessors should we provide for this type's fields?
+ pub(crate) fn visibility_kind(&self) -> Option<FieldVisibilityKind> {
+ self.visibility_kind
}
/// What kind of accessors should we provide for this type's fields?
- pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
+ pub(crate) fn accessor_kind(&self) -> Option<FieldAccessorKind> {
self.accessor_kind
}
@@ -188,7 +229,11 @@ impl Annotations {
}
"derive" => self.derives.push(attr.value),
"private" => {
- self.private_fields = Some(attr.value != "false")
+ self.visibility_kind = if attr.value != "false" {
+ Some(FieldVisibilityKind::Private)
+ } else {
+ Some(FieldVisibilityKind::Public)
+ };
}
"accessor" => {
self.accessor_kind = Some(parse_accessor(&attr.value))
@@ -205,7 +250,7 @@ impl Annotations {
}
/// Returns whether we've parsed a "constant" attribute.
- pub fn constify_enum_variant(&self) -> bool {
+ pub(crate) fn constify_enum_variant(&self) -> bool {
self.constify_enum_variant
}
}
diff --git a/ir/comment.rs b/ir/comment.rs
index 3eb17aa..7b6f105 100644
--- a/ir/comment.rs
+++ b/ir/comment.rs
@@ -12,7 +12,7 @@ enum Kind {
}
/// Preprocesses a C/C++ comment so that it is a valid Rust comment.
-pub fn preprocess(comment: &str) -> String {
+pub(crate) fn preprocess(comment: &str) -> String {
match self::kind(comment) {
Some(Kind::SingleLines) => preprocess_single_lines(comment),
Some(Kind::MultiLine) => preprocess_multi_line(comment),
diff --git a/ir/comp.rs b/ir/comp.rs
index 18a4291..89e77e1 100644
--- a/ir/comp.rs
+++ b/ir/comp.rs
@@ -22,7 +22,7 @@ use std::mem;
/// The kind of compound type.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum CompKind {
+pub(crate) enum CompKind {
/// A struct.
Struct,
/// A union.
@@ -31,7 +31,7 @@ pub enum CompKind {
/// The kind of C++ method.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum MethodKind {
+pub(crate) enum MethodKind {
/// A constructor. We represent it as method for convenience, to avoid code
/// duplication.
Constructor,
@@ -55,7 +55,7 @@ pub enum MethodKind {
impl MethodKind {
/// Is this a destructor method?
- pub fn is_destructor(&self) -> bool {
+ pub(crate) fn is_destructor(&self) -> bool {
matches!(
*self,
MethodKind::Destructor | MethodKind::VirtualDestructor { .. }
@@ -63,7 +63,7 @@ impl MethodKind {
}
/// Is this a pure virtual method?
- pub fn is_pure_virtual(&self) -> bool {
+ pub(crate) fn is_pure_virtual(&self) -> bool {
match *self {
MethodKind::Virtual { pure_virtual } |
MethodKind::VirtualDestructor { pure_virtual } => pure_virtual,
@@ -74,7 +74,7 @@ impl MethodKind {
/// A struct representing a C++ method, either static, normal, or virtual.
#[derive(Debug)]
-pub struct Method {
+pub(crate) struct Method {
kind: MethodKind,
/// The signature of the method. Take into account this is not a `Type`
/// item, but a `Function` one.
@@ -86,7 +86,7 @@ pub struct Method {
impl Method {
/// Construct a new `Method`.
- pub fn new(
+ pub(crate) fn new(
kind: MethodKind,
signature: FunctionId,
is_const: bool,
@@ -99,17 +99,17 @@ impl Method {
}
/// What kind of method is this?
- pub fn kind(&self) -> MethodKind {
+ pub(crate) fn kind(&self) -> MethodKind {
self.kind
}
/// Is this a constructor?
- pub fn is_constructor(&self) -> bool {
+ pub(crate) fn is_constructor(&self) -> bool {
self.kind == MethodKind::Constructor
}
/// Is this a virtual method?
- pub fn is_virtual(&self) -> bool {
+ pub(crate) fn is_virtual(&self) -> bool {
matches!(
self.kind,
MethodKind::Virtual { .. } | MethodKind::VirtualDestructor { .. }
@@ -117,23 +117,23 @@ impl Method {
}
/// Is this a static method?
- pub fn is_static(&self) -> bool {
+ pub(crate) fn is_static(&self) -> bool {
self.kind == MethodKind::Static
}
- /// Get the id for the `Function` signature for this method.
- pub fn signature(&self) -> FunctionId {
+ /// Get the ID for the `Function` signature for this method.
+ pub(crate) fn signature(&self) -> FunctionId {
self.signature
}
/// Is this a const qualified method?
- pub fn is_const(&self) -> bool {
+ pub(crate) fn is_const(&self) -> bool {
self.is_const
}
}
/// Methods common to the various field types.
-pub trait FieldMethods {
+pub(crate) trait FieldMethods {
/// Get the name of this field.
fn name(&self) -> Option<&str>;
@@ -161,7 +161,7 @@ pub trait FieldMethods {
/// 2.4.II.1 in the Itanium C++
/// ABI](http://itanium-cxx-abi.github.io/cxx-abi/abi.html#class-types).
#[derive(Debug)]
-pub struct BitfieldUnit {
+pub(crate) struct BitfieldUnit {
nth: usize,
layout: Layout,
bitfields: Vec<Bitfield>,
@@ -171,24 +171,24 @@ impl BitfieldUnit {
/// Get the 1-based index of this bitfield unit within its containing
/// struct. Useful for generating a Rust struct's field name for this unit
/// of bitfields.
- pub fn nth(&self) -> usize {
+ pub(crate) fn nth(&self) -> usize {
self.nth
}
/// Get the layout within which these bitfields reside.
- pub fn layout(&self) -> Layout {
+ pub(crate) fn layout(&self) -> Layout {
self.layout
}
/// Get the bitfields within this unit.
- pub fn bitfields(&self) -> &[Bitfield] {
+ pub(crate) fn bitfields(&self) -> &[Bitfield] {
&self.bitfields
}
}
/// A struct representing a C++ field.
#[derive(Debug)]
-pub enum Field {
+pub(crate) enum Field {
/// A normal data member.
DataMember(FieldData),
@@ -198,7 +198,7 @@ pub enum Field {
impl Field {
/// Get this field's layout.
- pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
+ pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
match *self {
Field::Bitfields(BitfieldUnit { layout, .. }) => Some(layout),
Field::DataMember(ref data) => {
@@ -307,7 +307,7 @@ impl DotAttributes for Bitfield {
/// A logical bitfield within some physical bitfield allocation unit.
#[derive(Debug)]
-pub struct Bitfield {
+pub(crate) struct Bitfield {
/// Index of the bit within this bitfield's allocation unit where this
/// bitfield's bits begin.
offset_into_unit: usize,
@@ -341,27 +341,12 @@ impl Bitfield {
/// Get the index of the bit within this bitfield's allocation unit where
/// this bitfield begins.
- pub fn offset_into_unit(&self) -> usize {
+ pub(crate) fn offset_into_unit(&self) -> usize {
self.offset_into_unit
}
- /// Get the mask value that when &'ed with this bitfield's allocation unit
- /// produces this bitfield's value.
- pub fn mask(&self) -> u64 {
- use std::u64;
-
- let unoffseted_mask =
- if self.width() as u64 == mem::size_of::<u64>() as u64 * 8 {
- u64::MAX
- } else {
- (1u64 << self.width()) - 1u64
- };
-
- unoffseted_mask << self.offset_into_unit()
- }
-
/// Get the bit width of this bitfield.
- pub fn width(&self) -> u32 {
+ pub(crate) fn width(&self) -> u32 {
self.data.bitfield_width().unwrap()
}
@@ -369,7 +354,7 @@ impl Bitfield {
///
/// Panics if called before assigning bitfield accessor names or if
/// this bitfield have no name.
- pub fn getter_name(&self) -> &str {
+ pub(crate) fn getter_name(&self) -> &str {
assert!(
self.name().is_some(),
"`Bitfield::getter_name` called on anonymous field"
@@ -384,7 +369,7 @@ impl Bitfield {
///
/// Panics if called before assigning bitfield accessor names or if
/// this bitfield have no name.
- pub fn setter_name(&self) -> &str {
+ pub(crate) fn setter_name(&self) -> &str {
assert!(
self.name().is_some(),
"`Bitfield::setter_name` called on anonymous field"
@@ -866,7 +851,7 @@ impl Trace for CompFields {
/// Common data shared across different field types.
#[derive(Clone, Debug)]
-pub struct FieldData {
+pub(crate) struct FieldData {
/// The name of the field, empty if it's an unnamed bitfield width.
name: Option<String>,
@@ -921,7 +906,7 @@ impl FieldMethods for FieldData {
/// The kind of inheritance a base class is using.
#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum BaseKind {
+pub(crate) enum BaseKind {
/// Normal inheritance, like:
///
/// ```cpp
@@ -938,25 +923,25 @@ pub enum BaseKind {
/// A base class.
#[derive(Clone, Debug)]
-pub struct Base {
+pub(crate) struct Base {
/// The type of this base class.
- pub ty: TypeId,
+ pub(crate) ty: TypeId,
/// The kind of inheritance we're doing.
- pub kind: BaseKind,
+ pub(crate) kind: BaseKind,
/// Name of the field in which this base should be stored.
- pub field_name: String,
+ pub(crate) field_name: String,
/// Whether this base is inherited from publically.
- pub is_pub: bool,
+ pub(crate) is_pub: bool,
}
impl Base {
/// Whether this base class is inheriting virtually.
- pub fn is_virtual(&self) -> bool {
+ pub(crate) fn is_virtual(&self) -> bool {
self.kind == BaseKind::Virtual
}
/// Whether this base class should have it's own field for storage.
- pub fn requires_storage(&self, ctx: &BindgenContext) -> bool {
+ pub(crate) fn requires_storage(&self, ctx: &BindgenContext) -> bool {
// Virtual bases are already taken into account by the vtable
// pointer.
//
@@ -976,7 +961,7 @@ impl Base {
}
/// Whether this base is inherited from publically.
- pub fn is_public(&self) -> bool {
+ pub(crate) fn is_public(&self) -> bool {
self.is_pub
}
}
@@ -987,7 +972,7 @@ impl Base {
/// of fields which also are associated with their own (potentially compound)
/// type.
#[derive(Debug)]
-pub struct CompInfo {
+pub(crate) struct CompInfo {
/// Whether this is a struct or a union.
kind: CompKind,
@@ -1067,7 +1052,7 @@ pub struct CompInfo {
impl CompInfo {
/// Construct a new compound type.
- pub fn new(kind: CompKind) -> Self {
+ pub(crate) fn new(kind: CompKind) -> Self {
CompInfo {
kind,
fields: CompFields::default(),
@@ -1097,7 +1082,7 @@ impl CompInfo {
/// If we're a union without known layout, we try to compute it from our
/// members. This is not ideal, but clang fails to report the size for these
/// kind of unions, see test/headers/template_union.hpp
- pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
+ pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
// We can't do better than clang here, sorry.
if self.kind == CompKind::Struct {
return None;
@@ -1126,7 +1111,7 @@ impl CompInfo {
}
/// Get this type's set of fields.
- pub fn fields(&self) -> &[Field] {
+ pub(crate) fn fields(&self) -> &[Field] {
match self.fields {
CompFields::Error => &[],
CompFields::After { ref fields, .. } => fields,
@@ -1184,7 +1169,7 @@ impl CompInfo {
/// Returns whether we have a too large bitfield unit, in which case we may
/// not be able to derive some of the things we should be able to normally
/// derive.
- pub fn has_too_large_bitfield_unit(&self) -> bool {
+ pub(crate) fn has_too_large_bitfield_unit(&self) -> bool {
if !self.has_bitfields() {
return false;
}
@@ -1198,53 +1183,53 @@ impl CompInfo {
/// Does this type have any template parameters that aren't types
/// (e.g. int)?
- pub fn has_non_type_template_params(&self) -> bool {
+ pub(crate) fn has_non_type_template_params(&self) -> bool {
self.has_non_type_template_params
}
/// Do we see a virtual function during parsing?
/// Get the has_own_virtual_method boolean.
- pub fn has_own_virtual_method(&self) -> bool {
+ pub(crate) fn has_own_virtual_method(&self) -> bool {
self.has_own_virtual_method
}
/// Did we see a destructor when parsing this type?
- pub fn has_own_destructor(&self) -> bool {
+ pub(crate) fn has_own_destructor(&self) -> bool {
self.has_destructor
}
/// Get this type's set of methods.
- pub fn methods(&self) -> &[Method] {
+ pub(crate) fn methods(&self) -> &[Method] {
&self.methods
}
/// Get this type's set of constructors.
- pub fn constructors(&self) -> &[FunctionId] {
+ pub(crate) fn constructors(&self) -> &[FunctionId] {
&self.constructors
}
/// Get this type's destructor.
- pub fn destructor(&self) -> Option<(MethodKind, FunctionId)> {
+ pub(crate) fn destructor(&self) -> Option<(MethodKind, FunctionId)> {
self.destructor
}
/// What kind of compound type is this?
- pub fn kind(&self) -> CompKind {
+ pub(crate) fn kind(&self) -> CompKind {
self.kind
}
/// Is this a union?
- pub fn is_union(&self) -> bool {
+ pub(crate) fn is_union(&self) -> bool {
self.kind() == CompKind::Union
}
/// The set of types that this one inherits from.
- pub fn base_members(&self) -> &[Base] {
+ pub(crate) fn base_members(&self) -> &[Base] {
&self.base_members
}
/// Construct a new compound type from a Clang type.
- pub fn from_ty(
+ pub(crate) fn from_ty(
potential_id: ItemId,
ty: &clang::Type,
location: Option<clang::Cursor>,
@@ -1611,23 +1596,23 @@ impl CompInfo {
/// Get the set of types that were declared within this compound type
/// (e.g. nested class definitions).
- pub fn inner_types(&self) -> &[TypeId] {
+ pub(crate) fn inner_types(&self) -> &[TypeId] {
&self.inner_types
}
/// Get the set of static variables declared within this compound type.
- pub fn inner_vars(&self) -> &[VarId] {
+ pub(crate) fn inner_vars(&self) -> &[VarId] {
&self.inner_vars
}
/// Have we found a field with an opaque type that could potentially mess up
/// the layout of this compound type?
- pub fn found_unknown_attr(&self) -> bool {
+ pub(crate) fn found_unknown_attr(&self) -> bool {
self.found_unknown_attr
}
/// Is this compound type packed?
- pub fn is_packed(
+ pub(crate) fn is_packed(
&self,
ctx: &BindgenContext,
layout: Option<&Layout>,
@@ -1657,12 +1642,12 @@ impl CompInfo {
}
/// Returns true if compound type has been forward declared
- pub fn is_forward_declaration(&self) -> bool {
+ pub(crate) fn is_forward_declaration(&self) -> bool {
self.is_forward_declaration
}
/// Compute this compound structure's bitfield allocation units.
- pub fn compute_bitfield_units(
+ pub(crate) fn compute_bitfield_units(
&mut self,
ctx: &BindgenContext,
layout: Option<&Layout>,
@@ -1672,7 +1657,7 @@ impl CompInfo {
}
/// Assign for each anonymous field a generated name.
- pub fn deanonymize_fields(&mut self, ctx: &BindgenContext) {
+ pub(crate) fn deanonymize_fields(&mut self, ctx: &BindgenContext) {
self.fields.deanonymize_fields(ctx, &self.methods);
}
@@ -1685,7 +1670,7 @@ impl CompInfo {
///
/// Second boolean returns whether all fields can be copied (and thus
/// ManuallyDrop is not needed).
- pub fn is_rust_union(
+ pub(crate) fn is_rust_union(
&self,
ctx: &BindgenContext,
layout: Option<&Layout>,
@@ -1695,7 +1680,7 @@ impl CompInfo {
return (false, false);
}
- if !ctx.options().rust_features().untagged_union {
+ if !ctx.options().untagged_union {
return (false, false);
}
diff --git a/ir/context.rs b/ir/context.rs
index b693a70..a5c14a8 100644
--- a/ir/context.rs
+++ b/ir/context.rs
@@ -23,8 +23,7 @@ use crate::clang::{self, Cursor};
use crate::codegen::CodegenError;
use crate::BindgenOptions;
use crate::{Entry, HashMap, HashSet};
-use cexpr;
-use clang_sys;
+
use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;
use std::borrow::Cow;
@@ -35,12 +34,13 @@ use std::mem;
/// An identifier for some kind of IR item.
#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
-pub struct ItemId(usize);
+pub(crate) struct ItemId(usize);
+/// Declare a newtype around `ItemId` with convesion methods.
macro_rules! item_id_newtype {
(
$( #[$attr:meta] )*
- pub struct $name:ident(ItemId)
+ pub(crate) struct $name:ident(ItemId)
where
$( #[$checked_attr:meta] )*
checked = $checked:ident with $check_method:ident,
@@ -51,11 +51,12 @@ macro_rules! item_id_newtype {
) => {
$( #[$attr] )*
#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
- pub struct $name(ItemId);
+ pub(crate) struct $name(ItemId);
impl $name {
- /// Create an `ItemResolver` from this id.
- pub fn into_resolver(self) -> ItemResolver {
+ /// Create an `ItemResolver` from this ID.
+ #[allow(dead_code)]
+ pub(crate) fn into_resolver(self) -> ItemResolver {
let id: ItemId = self.into();
id.into()
}
@@ -83,9 +84,10 @@ macro_rules! item_id_newtype {
}
}
+ #[allow(dead_code)]
impl ItemId {
$( #[$checked_attr] )*
- pub fn $checked(&self, ctx: &BindgenContext) -> Option<$name> {
+ pub(crate) fn $checked(&self, ctx: &BindgenContext) -> Option<$name> {
if ctx.resolve_item(*self).kind().$check_method() {
Some($name(*self))
} else {
@@ -94,7 +96,7 @@ macro_rules! item_id_newtype {
}
$( #[$expected_attr] )*
- pub fn $expected(&self, ctx: &BindgenContext) -> $name {
+ pub(crate) fn $expected(&self, ctx: &BindgenContext) -> $name {
self.$checked(ctx)
.expect(concat!(
stringify!($expected),
@@ -103,7 +105,7 @@ macro_rules! item_id_newtype {
}
$( #[$unchecked_attr] )*
- pub fn $unchecked(&self) -> $name {
+ pub(crate) fn $unchecked(&self) -> $name {
$name(*self)
}
}
@@ -113,7 +115,7 @@ macro_rules! item_id_newtype {
item_id_newtype! {
/// An identifier for an `Item` whose `ItemKind` is known to be
/// `ItemKind::Type`.
- pub struct TypeId(ItemId)
+ pub(crate) struct TypeId(ItemId)
where
/// Convert this `ItemId` into a `TypeId` if its associated item is a type,
/// otherwise return `None`.
@@ -125,14 +127,14 @@ item_id_newtype! {
expected = expect_type_id,
/// Convert this `ItemId` into a `TypeId` without actually checking whether
- /// this id actually points to a `Type`.
+ /// this ID actually points to a `Type`.
unchecked = as_type_id_unchecked;
}
item_id_newtype! {
/// An identifier for an `Item` whose `ItemKind` is known to be
/// `ItemKind::Module`.
- pub struct ModuleId(ItemId)
+ pub(crate) struct ModuleId(ItemId)
where
/// Convert this `ItemId` into a `ModuleId` if its associated item is a
/// module, otherwise return `None`.
@@ -144,14 +146,14 @@ item_id_newtype! {
expected = expect_module_id,
/// Convert this `ItemId` into a `ModuleId` without actually checking
- /// whether this id actually points to a `Module`.
+ /// whether this ID actually points to a `Module`.
unchecked = as_module_id_unchecked;
}
item_id_newtype! {
/// An identifier for an `Item` whose `ItemKind` is known to be
/// `ItemKind::Var`.
- pub struct VarId(ItemId)
+ pub(crate) struct VarId(ItemId)
where
/// Convert this `ItemId` into a `VarId` if its associated item is a var,
/// otherwise return `None`.
@@ -163,14 +165,14 @@ item_id_newtype! {
expected = expect_var_id,
/// Convert this `ItemId` into a `VarId` without actually checking whether
- /// this id actually points to a `Var`.
+ /// this ID actually points to a `Var`.
unchecked = as_var_id_unchecked;
}
item_id_newtype! {
/// An identifier for an `Item` whose `ItemKind` is known to be
/// `ItemKind::Function`.
- pub struct FunctionId(ItemId)
+ pub(crate) struct FunctionId(ItemId)
where
/// Convert this `ItemId` into a `FunctionId` if its associated item is a function,
/// otherwise return `None`.
@@ -182,7 +184,7 @@ item_id_newtype! {
expected = expect_function_id,
/// Convert this `ItemId` into a `FunctionId` without actually checking whether
- /// this id actually points to a `Function`.
+ /// this ID actually points to a `Function`.
unchecked = as_function_id_unchecked;
}
@@ -193,8 +195,8 @@ impl From<ItemId> for usize {
}
impl ItemId {
- /// Get a numeric representation of this id.
- pub fn as_usize(&self) -> usize {
+ /// Get a numeric representation of this ID.
+ pub(crate) fn as_usize(&self) -> usize {
(*self).into()
}
}
@@ -305,7 +307,7 @@ enum TypeKey {
/// A context used during parsing and generation of structs.
#[derive(Debug)]
-pub struct BindgenContext {
+pub(crate) struct BindgenContext {
/// The map of all the items parsed so far, keyed off ItemId.
items: Vec<Option<Item>>,
@@ -313,7 +315,7 @@ pub struct BindgenContext {
/// item ids during parsing.
types: HashMap<TypeKey, TypeId>,
- /// Maps from a cursor to the item id of the named template type parameter
+ /// Maps from a cursor to the item ID of the named template type parameter
/// for that cursor.
type_params: HashMap<clang::Cursor, TypeId>,
@@ -326,7 +328,7 @@ pub struct BindgenContext {
/// Current module being traversed.
current_module: ModuleId,
- /// A HashMap keyed on a type definition, and whose value is the parent id
+ /// A HashMap keyed on a type definition, and whose value is the parent ID
/// of the declaration.
///
/// This is used to handle the cases where the semantic and the lexical
@@ -390,7 +392,7 @@ pub struct BindgenContext {
/// It's computed right after computing the allowlisted items.
codegen_items: Option<ItemSet>,
- /// Map from an item's id to the set of template parameter items that it
+ /// Map from an item's ID to the set of template parameter items that it
/// uses. See `ir::named` for more details. Always `Some` during the codegen
/// phase.
used_template_parameters: Option<HashMap<ItemId, ItemSet>>,
@@ -475,9 +477,6 @@ pub struct BindgenContext {
/// Populated when we enter codegen by `compute_has_float`; always `None`
/// before that and `Some` after.
has_float: Option<HashSet<ItemId>>,
-
- /// The set of warnings raised during binding generation.
- warnings: Vec<String>,
}
/// A traversal of allowlisted items.
@@ -504,7 +503,7 @@ impl<'ctx> Iterator for AllowlistedItemsTraversal<'ctx> {
impl<'ctx> AllowlistedItemsTraversal<'ctx> {
/// Construct a new allowlisted items traversal.
- pub fn new<R>(
+ pub(crate) fn new<R>(
ctx: &'ctx BindgenContext,
roots: R,
predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool,
@@ -593,51 +592,50 @@ If you encounter an error missing from this list, please file an issue or a PR!"
have_destructor: None,
has_type_param_in_array: None,
has_float: None,
- warnings: Vec::new(),
}
}
/// Returns `true` if the target architecture is wasm32
- pub fn is_target_wasm32(&self) -> bool {
+ pub(crate) fn is_target_wasm32(&self) -> bool {
self.target_info.triple.starts_with("wasm32-")
}
/// Creates a timer for the current bindgen phase. If time_phases is `true`,
/// the timer will print to stderr when it is dropped, otherwise it will do
/// nothing.
- pub fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
+ pub(crate) fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
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 {
+ pub(crate) fn target_pointer_size(&self) -> usize {
self.target_info.pointer_width / 8
}
/// Get the stack of partially parsed types that we are in the middle of
/// parsing.
- pub fn currently_parsed_types(&self) -> &[PartialType] {
+ pub(crate) fn currently_parsed_types(&self) -> &[PartialType] {
&self.currently_parsed_types[..]
}
/// Begin parsing the given partial type, and push it onto the
/// `currently_parsed_types` stack so that we won't infinite recurse if we
/// run into a reference to it while parsing it.
- pub fn begin_parsing(&mut self, partial_ty: PartialType) {
+ pub(crate) fn begin_parsing(&mut self, partial_ty: PartialType) {
self.currently_parsed_types.push(partial_ty);
}
/// Finish parsing the current partial type, pop it off the
/// `currently_parsed_types` stack, and return it.
- pub fn finish_parsing(&mut self) -> PartialType {
+ pub(crate) fn finish_parsing(&mut self) -> PartialType {
self.currently_parsed_types.pop().expect(
"should have been parsing a type, if we finished parsing a type",
)
}
/// Add another path to the set of included files.
- pub fn include_file(&mut self, filename: String) {
+ pub(crate) fn include_file(&mut self, filename: String) {
for cb in &self.options().parse_callbacks {
cb.include_file(&filename);
}
@@ -645,7 +643,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Get any included files.
- pub fn deps(&self) -> &BTreeSet<String> {
+ pub(crate) fn deps(&self) -> &BTreeSet<String> {
&self.deps
}
@@ -653,7 +651,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
///
/// This inserts it into the internal items set, and its type into the
/// internal types set.
- pub fn add_item(
+ pub(crate) fn add_item(
&mut self,
item: Item,
declaration: Option<Cursor>,
@@ -778,7 +776,11 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Add a new named template type parameter to this context's item set.
- pub fn add_type_param(&mut self, item: Item, definition: clang::Cursor) {
+ pub(crate) fn add_type_param(
+ &mut self,
+ item: Item,
+ definition: clang::Cursor,
+ ) {
debug!(
"BindgenContext::add_type_param: item = {:?}; definition = {:?}",
item, definition
@@ -813,7 +815,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Get the named type defined at the given cursor location, if we've
/// already added one.
- pub fn get_type_param(&self, definition: &clang::Cursor) -> Option<TypeId> {
+ pub(crate) fn get_type_param(
+ &self,
+ definition: &clang::Cursor,
+ ) -> Option<TypeId> {
assert_eq!(
definition.kind(),
clang_sys::CXCursor_TemplateTypeParameter
@@ -825,7 +830,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Mangles a name so it doesn't conflict with any keyword.
#[rustfmt::skip]
- pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
+ pub(crate) fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
if name.contains('@') ||
name.contains('?') ||
name.contains('$') ||
@@ -856,7 +861,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Returns a mangled name as a rust identifier.
- pub fn rust_ident<S>(&self, name: S) -> Ident
+ pub(crate) fn rust_ident<S>(&self, name: S) -> Ident
where
S: AsRef<str>,
{
@@ -864,7 +869,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Returns a mangled name as a rust identifier.
- pub fn rust_ident_raw<T>(&self, name: T) -> Ident
+ pub(crate) fn rust_ident_raw<T>(&self, name: T) -> Ident
where
T: AsRef<str>,
{
@@ -872,7 +877,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Iterate over all items that have been defined.
- pub fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
+ pub(crate) fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
self.items.iter().enumerate().filter_map(|(index, item)| {
let item = item.as_ref()?;
Some((ItemId(index), item))
@@ -880,7 +885,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Have we collected all unresolved type references yet?
- pub fn collected_typerefs(&self) -> bool {
+ pub(crate) fn collected_typerefs(&self) -> bool {
self.collected_typerefs
}
@@ -1077,7 +1082,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
// Relocate the replacement item from where it was declared, to
// where the thing it is replacing was declared.
//
- // First, we'll make sure that its parent id is correct.
+ // First, we'll make sure that its parent ID is correct.
let old_parent = self.resolve_item(replacement_id).parent_id();
if new_parent == old_parent {
@@ -1147,7 +1152,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
pub(crate) fn gen<F, Out>(
mut self,
cb: F,
- ) -> Result<(Out, BindgenOptions, Vec<String>), CodegenError>
+ ) -> Result<(Out, BindgenOptions), CodegenError>
where
F: FnOnce(&Self) -> Result<Out, CodegenError>,
{
@@ -1185,7 +1190,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
self.compute_cannot_derive_partialord_partialeq_or_eq();
let ret = cb(&self)?;
- Ok((ret, self.options, self.warnings))
+ Ok((ret, self.options))
}
/// When the `testing_only_extra_assertions` feature is enabled, this
@@ -1263,8 +1268,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
self.sizedness = Some(analyze::<SizednessAnalysis>(self));
}
- /// Look up whether the type with the given id is sized or not.
- pub fn lookup_sizedness(&self, id: TypeId) -> SizednessResult {
+ /// Look up whether the type with the given ID is sized or not.
+ pub(crate) fn lookup_sizedness(&self, id: TypeId) -> SizednessResult {
assert!(
self.in_codegen_phase(),
"We only compute sizedness after we've entered codegen"
@@ -1286,7 +1291,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Look up whether the item with `id` has vtable or not.
- pub fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult {
+ pub(crate) fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult {
assert!(
self.in_codegen_phase(),
"We only compute vtables when we enter codegen"
@@ -1310,7 +1315,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Look up whether the item with `id` has a destructor.
- pub fn lookup_has_destructor(&self, id: TypeId) -> bool {
+ pub(crate) fn lookup_has_destructor(&self, id: TypeId) -> bool {
assert!(
self.in_codegen_phase(),
"We only compute destructors when we enter codegen"
@@ -1354,7 +1359,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// manually provide a definition for them. To give them the most
/// flexibility when doing that, we assume that they use every template
/// parameter and always pass template arguments through in instantiations.
- pub fn uses_template_parameter(
+ pub(crate) fn uses_template_parameter(
&self,
item: ItemId,
template_param: TypeId,
@@ -1386,7 +1391,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// `false` otherwise.
///
/// Has the same restrictions that `uses_template_parameter` has.
- pub fn uses_any_template_parameters(&self, item: ItemId) -> bool {
+ pub(crate) fn uses_any_template_parameters(&self, item: ItemId) -> bool {
assert!(
self.in_codegen_phase(),
"We only compute template parameter usage as we enter codegen"
@@ -1424,38 +1429,38 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Get the root module.
- pub fn root_module(&self) -> ModuleId {
+ pub(crate) fn root_module(&self) -> ModuleId {
self.root_module
}
- /// Resolve a type with the given id.
+ /// Resolve a type with the given ID.
///
/// Panics if there is no item for the given `TypeId` or if the resolved
/// item is not a `Type`.
- pub fn resolve_type(&self, type_id: TypeId) -> &Type {
+ pub(crate) fn resolve_type(&self, type_id: TypeId) -> &Type {
self.resolve_item(type_id).kind().expect_type()
}
- /// Resolve a function with the given id.
+ /// Resolve a function with the given ID.
///
/// Panics if there is no item for the given `FunctionId` or if the resolved
/// item is not a `Function`.
- pub fn resolve_func(&self, func_id: FunctionId) -> &Function {
+ pub(crate) fn resolve_func(&self, func_id: FunctionId) -> &Function {
self.resolve_item(func_id).kind().expect_function()
}
/// Resolve the given `ItemId` as a type, or `None` if there is no item with
- /// the given id.
+ /// the given ID.
///
- /// Panics if the id resolves to an item that is not a type.
- pub fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
+ /// Panics if the ID resolves to an item that is not a type.
+ pub(crate) fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
self.resolve_item_fallible(type_id)
.map(|t| t.kind().expect_type())
}
/// Resolve the given `ItemId` into an `Item`, or `None` if no such item
/// exists.
- pub fn resolve_item_fallible<Id: Into<ItemId>>(
+ pub(crate) fn resolve_item_fallible<Id: Into<ItemId>>(
&self,
id: Id,
) -> Option<&Item> {
@@ -1464,8 +1469,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Resolve the given `ItemId` into an `Item`.
///
- /// Panics if the given id does not resolve to any item.
- pub fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
+ /// Panics if the given ID does not resolve to any item.
+ pub(crate) fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
let item_id = item_id.into();
match self.resolve_item_fallible(item_id) {
Some(item) => item,
@@ -1474,7 +1479,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Get the current module.
- pub fn current_module(&self) -> ModuleId {
+ pub(crate) fn current_module(&self) -> ModuleId {
self.current_module
}
@@ -1486,7 +1491,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// TODO(emilio): We could consider doing this only when
/// declaration.lexical_parent() != definition.lexical_parent(), but it's
/// not sure it's worth it.
- pub fn add_semantic_parent(
+ pub(crate) fn add_semantic_parent(
&mut self,
definition: clang::Cursor,
parent_id: ItemId,
@@ -1495,7 +1500,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Returns a known semantic parent for a given definition.
- pub fn known_semantic_parent(
+ pub(crate) fn known_semantic_parent(
&self,
definition: clang::Cursor,
) -> Option<ItemId> {
@@ -1649,7 +1654,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
clang_sys::CXCursor_TypeRef |
clang_sys::CXCursor_TypedefDecl |
clang_sys::CXCursor_TypeAliasDecl => {
- // The `with_id` id will potentially end up unused if we give up
+ // The `with_id` ID will potentially end up unused if we give up
// on this type (for example, because it has const value
// template args), so if we pass `with_id` as the parent, it is
// potentially a dangling reference. Instead, use the canonical
@@ -1808,7 +1813,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// If we have already resolved the type for the given type declaration,
/// return its `ItemId`. Otherwise, return `None`.
- pub fn get_resolved_type(
+ pub(crate) fn get_resolved_type(
&self,
decl: &clang::CanonicalTypeDeclaration,
) -> Option<TypeId> {
@@ -1824,7 +1829,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Looks up for an already resolved type, either because it's builtin, or
/// because we already have it in the map.
- pub fn builtin_or_resolved_ty(
+ pub(crate) fn builtin_or_resolved_ty(
&mut self,
with_id: ItemId,
parent_id: Option<ItemId>,
@@ -1894,7 +1899,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// We should probably make the constness tracking separate, so it doesn't
/// bloat that much, but hey, we already bloat the heck out of builtin
/// types.
- pub fn build_ty_wrapper(
+ pub(crate) fn build_ty_wrapper(
&mut self,
with_id: ItemId,
wrapped_id: TypeId,
@@ -1907,7 +1912,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// A wrapper over a type that adds a const qualifier explicitly.
///
/// Needed to handle const methods in C++, wrapping the type .
- pub fn build_const_wrapper(
+ pub(crate) fn build_const_wrapper(
&mut self,
with_id: ItemId,
wrapped_id: TypeId,
@@ -1944,8 +1949,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
with_id.as_type_id_unchecked()
}
- /// Returns the next item id to be used for an item.
- pub fn next_item_id(&mut self) -> ItemId {
+ /// Returns the next item ID to be used for an item.
+ pub(crate) fn next_item_id(&mut self) -> ItemId {
let ret = ItemId(self.items.len());
self.items.push(None);
ret
@@ -2015,17 +2020,17 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Get the current Clang translation unit that is being processed.
- pub fn translation_unit(&self) -> &clang::TranslationUnit {
+ pub(crate) fn translation_unit(&self) -> &clang::TranslationUnit {
&self.translation_unit
}
/// Have we parsed the macro named `macro_name` already?
- pub fn parsed_macro(&self, macro_name: &[u8]) -> bool {
+ pub(crate) fn parsed_macro(&self, macro_name: &[u8]) -> bool {
self.parsed_macros.contains_key(macro_name)
}
/// Get the currently parsed macros.
- pub fn parsed_macros(
+ pub(crate) fn parsed_macros(
&self,
) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult> {
debug_assert!(!self.in_codegen_phase());
@@ -2033,7 +2038,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Mark the macro named `macro_name` as parsed.
- pub fn note_parsed_macro(
+ pub(crate) fn note_parsed_macro(
&mut self,
id: Vec<u8>,
value: cexpr::expr::EvalResult,
@@ -2042,16 +2047,16 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Are we in the codegen phase?
- pub fn in_codegen_phase(&self) -> bool {
+ pub(crate) fn in_codegen_phase(&self) -> bool {
self.in_codegen
}
- /// Mark the type with the given `name` as replaced by the type with id
+ /// Mark the type with the given `name` as replaced by the type with ID
/// `potential_ty`.
///
/// Replacement types are declared using the `replaces="xxx"` annotation,
/// and implies that the original type is hidden.
- pub fn replace(&mut self, name: &[String], potential_ty: ItemId) {
+ pub(crate) fn replace(&mut self, name: &[String], potential_ty: ItemId) {
match self.replacements.entry(name.into()) {
Entry::Vacant(entry) => {
debug!(
@@ -2074,7 +2079,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Has the item with the given `name` and `id` been replaced by another
/// type?
- pub fn is_replaced_type<Id: Into<ItemId>>(
+ pub(crate) fn is_replaced_type<Id: Into<ItemId>>(
&self,
path: &[String],
id: Id,
@@ -2084,7 +2089,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Is the type with the given `name` marked as opaque?
- pub fn opaque_by_name(&self, path: &[String]) -> bool {
+ pub(crate) fn opaque_by_name(&self, path: &[String]) -> bool {
debug_assert!(
self.in_codegen_phase(),
"You're not supposed to call this yet"
@@ -2176,9 +2181,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
(module_name, kind)
}
- /// Given a CXCursor_Namespace cursor, return the item id of the
+ /// Given a CXCursor_Namespace cursor, return the item ID of the
/// corresponding module, or create one on the fly.
- pub fn module(&mut self, cursor: clang::Cursor) -> ModuleId {
+ pub(crate) fn module(&mut self, cursor: clang::Cursor) -> ModuleId {
use clang_sys::*;
assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person");
let cursor = cursor.canonical();
@@ -2209,7 +2214,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Start traversing the module with the given `module_id`, invoke the
/// callback `cb`, and then return to traversing the original module.
- pub fn with_module<F>(&mut self, module_id: ModuleId, cb: F)
+ pub(crate) fn with_module<F>(&mut self, module_id: ModuleId, cb: F)
where
F: FnOnce(&mut Self),
{
@@ -2227,7 +2232,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
///
/// If no items are explicitly allowlisted, then all items are considered
/// allowlisted.
- pub fn allowlisted_items(&self) -> &ItemSet {
+ pub(crate) fn allowlisted_items(&self) -> &ItemSet {
assert!(self.in_codegen_phase());
assert!(self.current_module == self.root_module);
@@ -2236,7 +2241,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Check whether a particular blocklisted type implements a trait or not.
/// Results may be cached.
- pub fn blocklisted_type_implements_trait(
+ pub(crate) fn blocklisted_type_implements_trait(
&self,
item: &Item,
derive_trait: DeriveTrait,
@@ -2277,7 +2282,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Is the given type a type from <stdint.h> that corresponds to a Rust primitive type?
- pub fn is_stdint_type(&self, name: &str) -> bool {
+ pub(crate) fn is_stdint_type(&self, name: &str) -> bool {
match name {
"int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" |
"uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" |
@@ -2288,7 +2293,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Get a reference to the set of items we should generate.
- pub fn codegen_items(&self) -> &ItemSet {
+ pub(crate) fn codegen_items(&self) -> &ItemSet {
assert!(self.in_codegen_phase());
assert!(self.current_module == self.root_module);
self.codegen_items.as_ref().unwrap()
@@ -2454,30 +2459,22 @@ If you encounter an error missing from this list, please file an issue or a PR!"
self.allowlisted = Some(allowlisted);
self.codegen_items = Some(codegen_items);
- let mut warnings = Vec::new();
-
for item in self.options().allowlisted_functions.unmatched_items() {
- warnings
- .push(format!("unused option: --allowlist-function {}", item));
+ unused_regex_diagnostic(item, "--allowlist-function", self);
}
for item in self.options().allowlisted_vars.unmatched_items() {
- warnings.push(format!("unused option: --allowlist-var {}", item));
+ unused_regex_diagnostic(item, "--allowlist-var", self);
}
for item in self.options().allowlisted_types.unmatched_items() {
- warnings.push(format!("unused option: --allowlist-type {}", item));
- }
-
- for msg in warnings {
- warn!("{}", msg);
- self.warnings.push(msg);
+ unused_regex_diagnostic(item, "--allowlist-type", self);
}
}
/// Convenient method for getting the prefix to use for most traits in
/// codegen depending on the `use_core` option.
- pub fn trait_prefix(&self) -> Ident {
+ pub(crate) fn trait_prefix(&self) -> Ident {
if self.options().use_core {
self.rust_ident_raw("core")
} else {
@@ -2486,12 +2483,12 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Call if a bindgen complex is generated
- pub fn generated_bindgen_complex(&self) {
+ pub(crate) fn generated_bindgen_complex(&self) {
self.generated_bindgen_complex.set(true)
}
/// Whether we need to generate the bindgen complex type
- pub fn need_bindgen_complex_type(&self) -> bool {
+ pub(crate) fn need_bindgen_complex_type(&self) -> bool {
self.generated_bindgen_complex.get()
}
@@ -2530,7 +2527,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
}
- // Find enums in this module, and record the id of each one that
+ // Find enums in this module, and record the ID of each one that
// has a typedef.
for child_id in module.children() {
if let Some(ItemKind::Type(ty)) =
@@ -2551,7 +2548,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Look up whether `id` refers to an `enum` whose underlying type is
/// defined by a `typedef`.
- pub fn is_enum_typedef_combo(&self, id: ItemId) -> bool {
+ pub(crate) fn is_enum_typedef_combo(&self, id: ItemId) -> bool {
assert!(
self.in_codegen_phase(),
"We only compute enum_typedef_combos when we enter codegen",
@@ -2574,7 +2571,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Look up whether the item with `id` can
/// derive debug or not.
- pub fn lookup_can_derive_debug<Id: Into<ItemId>>(&self, id: Id) -> bool {
+ pub(crate) fn lookup_can_derive_debug<Id: Into<ItemId>>(
+ &self,
+ id: Id,
+ ) -> bool {
let id = id.into();
assert!(
self.in_codegen_phase(),
@@ -2601,7 +2601,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Look up whether the item with `id` can
/// derive default or not.
- pub fn lookup_can_derive_default<Id: Into<ItemId>>(&self, id: Id) -> bool {
+ pub(crate) fn lookup_can_derive_default<Id: Into<ItemId>>(
+ &self,
+ id: Id,
+ ) -> bool {
let id = id.into();
assert!(
self.in_codegen_phase(),
@@ -2639,7 +2642,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// Look up whether the item with `id` can
/// derive hash or not.
- pub fn lookup_can_derive_hash<Id: Into<ItemId>>(&self, id: Id) -> bool {
+ pub(crate) fn lookup_can_derive_hash<Id: Into<ItemId>>(
+ &self,
+ id: Id,
+ ) -> bool {
let id = id.into();
assert!(
self.in_codegen_phase(),
@@ -2668,7 +2674,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Look up whether the item with `id` can derive `Partial{Eq,Ord}`.
- pub fn lookup_can_derive_partialeq_or_partialord<Id: Into<ItemId>>(
+ pub(crate) fn lookup_can_derive_partialeq_or_partialord<
+ Id: Into<ItemId>,
+ >(
&self,
id: Id,
) -> CanDerive {
@@ -2689,7 +2697,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Look up whether the item with `id` can derive `Copy` or not.
- pub fn lookup_can_derive_copy<Id: Into<ItemId>>(&self, id: Id) -> bool {
+ pub(crate) fn lookup_can_derive_copy<Id: Into<ItemId>>(
+ &self,
+ id: Id,
+ ) -> bool {
assert!(
self.in_codegen_phase(),
"We only compute can_derive_debug when we enter codegen"
@@ -2712,7 +2723,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Look up whether the item with `id` has type parameter in array or not.
- pub fn lookup_has_type_param_in_array<Id: Into<ItemId>>(
+ pub(crate) fn lookup_has_type_param_in_array<Id: Into<ItemId>>(
&self,
id: Id,
) -> bool {
@@ -2739,7 +2750,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Look up whether the item with `id` has array or not.
- pub fn lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool {
+ pub(crate) fn lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool {
assert!(
self.in_codegen_phase(),
"We only compute has float when we enter codegen"
@@ -2751,41 +2762,42 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
/// Check if `--no-partialeq` flag is enabled for this item.
- pub fn no_partialeq_by_name(&self, item: &Item) -> bool {
+ pub(crate) fn no_partialeq_by_name(&self, item: &Item) -> bool {
let name = item.path_for_allowlisting(self)[1..].join("::");
self.options().no_partialeq_types.matches(name)
}
/// Check if `--no-copy` flag is enabled for this item.
- pub fn no_copy_by_name(&self, item: &Item) -> bool {
+ pub(crate) fn no_copy_by_name(&self, item: &Item) -> bool {
let name = item.path_for_allowlisting(self)[1..].join("::");
self.options().no_copy_types.matches(name)
}
/// Check if `--no-debug` flag is enabled for this item.
- pub fn no_debug_by_name(&self, item: &Item) -> bool {
+ pub(crate) fn no_debug_by_name(&self, item: &Item) -> bool {
let name = item.path_for_allowlisting(self)[1..].join("::");
self.options().no_debug_types.matches(name)
}
/// Check if `--no-default` flag is enabled for this item.
- pub fn no_default_by_name(&self, item: &Item) -> bool {
+ pub(crate) fn no_default_by_name(&self, item: &Item) -> bool {
let name = item.path_for_allowlisting(self)[1..].join("::");
self.options().no_default_types.matches(name)
}
/// Check if `--no-hash` flag is enabled for this item.
- pub fn no_hash_by_name(&self, item: &Item) -> bool {
+ pub(crate) fn no_hash_by_name(&self, item: &Item) -> bool {
let name = item.path_for_allowlisting(self)[1..].join("::");
self.options().no_hash_types.matches(name)
}
/// Check if `--must-use-type` flag is enabled for this item.
- pub fn must_use_type_by_name(&self, item: &Item) -> bool {
+ pub(crate) fn must_use_type_by_name(&self, item: &Item) -> bool {
let name = item.path_for_allowlisting(self)[1..].join("::");
self.options().must_use_types.matches(name)
}
+ /// Wrap some tokens in an `unsafe` block if the `--wrap-unsafe-ops` option is enabled.
pub(crate) fn wrap_unsafe_ops(&self, tokens: impl ToTokens) -> TokenStream {
if self.options.wrap_unsafe_ops {
quote!(unsafe { #tokens })
@@ -2794,6 +2806,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
}
+ /// Get the suffix to be added to `static` functions if the `--wrap-static-fns` option is
+ /// enabled.
pub(crate) fn wrap_static_fns_suffix(&self) -> &str {
self.options()
.wrap_static_fns_suffix
@@ -2804,15 +2818,15 @@ If you encounter an error missing from this list, please file an issue or a PR!"
/// A builder struct for configuring item resolution options.
#[derive(Debug, Copy, Clone)]
-pub struct ItemResolver {
+pub(crate) struct ItemResolver {
id: ItemId,
through_type_refs: bool,
through_type_aliases: bool,
}
impl ItemId {
- /// Create an `ItemResolver` from this item id.
- pub fn into_resolver(self) -> ItemResolver {
+ /// Create an `ItemResolver` from this item ID.
+ pub(crate) fn into_resolver(self) -> ItemResolver {
self.into()
}
}
@@ -2827,8 +2841,8 @@ where
}
impl ItemResolver {
- /// Construct a new `ItemResolver` from the given id.
- pub fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
+ /// Construct a new `ItemResolver` from the given ID.
+ pub(crate) fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
let id = id.into();
ItemResolver {
id,
@@ -2838,19 +2852,19 @@ impl ItemResolver {
}
/// Keep resolving through `Type::TypeRef` items.
- pub fn through_type_refs(mut self) -> ItemResolver {
+ pub(crate) fn through_type_refs(mut self) -> ItemResolver {
self.through_type_refs = true;
self
}
/// Keep resolving through `Type::Alias` items.
- pub fn through_type_aliases(mut self) -> ItemResolver {
+ pub(crate) fn through_type_aliases(mut self) -> ItemResolver {
self.through_type_aliases = true;
self
}
/// Finish configuring and perform the actual item resolution.
- pub fn resolve(self, ctx: &BindgenContext) -> &Item {
+ pub(crate) fn resolve(self, ctx: &BindgenContext) -> &Item {
assert!(ctx.collected_typerefs());
let mut id = self.id;
@@ -2887,7 +2901,7 @@ impl ItemResolver {
/// A type that we are in the middle of parsing.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct PartialType {
+pub(crate) struct PartialType {
decl: Cursor,
// Just an ItemId, and not a TypeId, because we haven't finished this type
// yet, so there's still time for things to go wrong.
@@ -2896,19 +2910,19 @@ pub struct PartialType {
impl PartialType {
/// Construct a new `PartialType`.
- pub fn new(decl: Cursor, id: ItemId) -> PartialType {
+ pub(crate) fn new(decl: Cursor, id: ItemId) -> PartialType {
// assert!(decl == decl.canonical());
PartialType { decl, id }
}
/// The cursor pointing to this partial type's declaration location.
- pub fn decl(&self) -> &Cursor {
+ pub(crate) fn decl(&self) -> &Cursor {
&self.decl
}
/// The item ID allocated for this type. This is *NOT* a key for an entry in
/// the context's item set yet!
- pub fn id(&self) -> ItemId {
+ pub(crate) fn id(&self) -> ItemId {
self.id
}
}
@@ -2945,3 +2959,23 @@ impl TemplateParameters for PartialType {
}
}
}
+
+fn unused_regex_diagnostic(item: &str, name: &str, _ctx: &BindgenContext) {
+ warn!("unused option: {} {}", name, item);
+
+ #[cfg(feature = "experimental")]
+ if _ctx.options().emit_diagnostics {
+ use crate::diagnostics::{Diagnostic, Level};
+
+ Diagnostic::default()
+ .with_title(
+ format!("Unused regular expression: `{}`.", item),
+ Level::Warn,
+ )
+ .add_annotation(
+ format!("This regular expression was passed to `{}`.", name),
+ Level::Note,
+ )
+ .display();
+ }
+}
diff --git a/ir/derive.rs b/ir/derive.rs
index 594ce2a..3877b42 100644
--- a/ir/derive.rs
+++ b/ir/derive.rs
@@ -18,7 +18,7 @@ use std::ops;
/// A trait that encapsulates the logic for whether or not we can derive `Debug`
/// for a given thing.
-pub trait CanDeriveDebug {
+pub(crate) trait CanDeriveDebug {
/// Return `true` if `Debug` can be derived for this thing, `false`
/// otherwise.
fn can_derive_debug(&self, ctx: &BindgenContext) -> bool;
@@ -26,7 +26,7 @@ pub trait CanDeriveDebug {
/// A trait that encapsulates the logic for whether or not we can derive `Copy`
/// for a given thing.
-pub trait CanDeriveCopy {
+pub(crate) trait CanDeriveCopy {
/// Return `true` if `Copy` can be derived for this thing, `false`
/// otherwise.
fn can_derive_copy(&self, ctx: &BindgenContext) -> bool;
@@ -34,7 +34,7 @@ pub trait CanDeriveCopy {
/// A trait that encapsulates the logic for whether or not we can derive
/// `Default` for a given thing.
-pub trait CanDeriveDefault {
+pub(crate) trait CanDeriveDefault {
/// Return `true` if `Default` can be derived for this thing, `false`
/// otherwise.
fn can_derive_default(&self, ctx: &BindgenContext) -> bool;
@@ -42,7 +42,7 @@ pub trait CanDeriveDefault {
/// A trait that encapsulates the logic for whether or not we can derive `Hash`
/// for a given thing.
-pub trait CanDeriveHash {
+pub(crate) trait CanDeriveHash {
/// Return `true` if `Hash` can be derived for this thing, `false`
/// otherwise.
fn can_derive_hash(&self, ctx: &BindgenContext) -> bool;
@@ -50,7 +50,7 @@ pub trait CanDeriveHash {
/// A trait that encapsulates the logic for whether or not we can derive
/// `PartialEq` for a given thing.
-pub trait CanDerivePartialEq {
+pub(crate) trait CanDerivePartialEq {
/// Return `true` if `PartialEq` can be derived for this thing, `false`
/// otherwise.
fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool;
@@ -58,7 +58,7 @@ pub trait CanDerivePartialEq {
/// A trait that encapsulates the logic for whether or not we can derive
/// `PartialOrd` for a given thing.
-pub trait CanDerivePartialOrd {
+pub(crate) trait CanDerivePartialOrd {
/// Return `true` if `PartialOrd` can be derived for this thing, `false`
/// otherwise.
fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool;
@@ -66,14 +66,14 @@ pub trait CanDerivePartialOrd {
/// A trait that encapsulates the logic for whether or not we can derive `Eq`
/// for a given thing.
-pub trait CanDeriveEq {
+pub(crate) trait CanDeriveEq {
/// Return `true` if `Eq` can be derived for this thing, `false` otherwise.
fn can_derive_eq(&self, ctx: &BindgenContext) -> bool;
}
/// A trait that encapsulates the logic for whether or not we can derive `Ord`
/// for a given thing.
-pub trait CanDeriveOrd {
+pub(crate) trait CanDeriveOrd {
/// Return `true` if `Ord` can be derived for this thing, `false` otherwise.
fn can_derive_ord(&self, ctx: &BindgenContext) -> bool;
}
@@ -115,7 +115,7 @@ impl Default for CanDerive {
impl CanDerive {
/// Take the least upper bound of `self` and `rhs`.
- pub fn join(self, rhs: Self) -> Self {
+ pub(crate) fn join(self, rhs: Self) -> Self {
cmp::max(self, rhs)
}
}
diff --git a/ir/dot.rs b/ir/dot.rs
index f7d07f1..d5c1a42 100644
--- a/ir/dot.rs
+++ b/ir/dot.rs
@@ -8,7 +8,7 @@ use std::path::Path;
/// A trait for anything that can write attributes as `<table>` rows to a dot
/// file.
-pub trait DotAttributes {
+pub(crate) trait DotAttributes {
/// Write this thing's attributes to the given output. Each attribute must
/// be its own `<tr>...</tr>`.
fn dot_attributes<W>(
@@ -21,7 +21,7 @@ pub trait DotAttributes {
}
/// Write a graphviz dot file containing our IR.
-pub fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()>
+pub(crate) fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()>
where
P: AsRef<Path>,
{
diff --git a/ir/enum_ty.rs b/ir/enum_ty.rs
index 63871fd..70cf0ea 100644
--- a/ir/enum_ty.rs
+++ b/ir/enum_ty.rs
@@ -22,7 +22,7 @@ pub enum EnumVariantCustomBehavior {
/// A C/C++ enumeration.
#[derive(Debug)]
-pub struct Enum {
+pub(crate) struct Enum {
/// The representation used for this enum; it should be an `IntKind` type or
/// an alias to one.
///
@@ -36,22 +36,25 @@ pub struct Enum {
impl Enum {
/// Construct a new `Enum` with the given representation and variants.
- pub fn new(repr: Option<TypeId>, variants: Vec<EnumVariant>) -> Self {
+ pub(crate) fn new(
+ repr: Option<TypeId>,
+ variants: Vec<EnumVariant>,
+ ) -> Self {
Enum { repr, variants }
}
/// Get this enumeration's representation.
- pub fn repr(&self) -> Option<TypeId> {
+ pub(crate) fn repr(&self) -> Option<TypeId> {
self.repr
}
/// Get this enumeration's variants.
- pub fn variants(&self) -> &[EnumVariant] {
+ pub(crate) fn variants(&self) -> &[EnumVariant] {
&self.variants
}
/// Construct an enumeration from the given Clang type.
- pub fn from_ty(
+ pub(crate) fn from_ty(
ty: &clang::Type,
ctx: &mut BindgenContext,
) -> Result<Self, ParseError> {
@@ -169,7 +172,7 @@ impl Enum {
}
/// Returns the final representation of the enum.
- pub fn computed_enum_variation(
+ pub(crate) fn computed_enum_variation(
&self,
ctx: &BindgenContext,
item: &Item,
@@ -236,7 +239,7 @@ impl Enum {
/// A single enum variant, to be contained only in an enum.
#[derive(Debug)]
-pub struct EnumVariant {
+pub(crate) struct EnumVariant {
/// The name of the variant.
name: String,
@@ -268,7 +271,7 @@ pub enum EnumVariantValue {
impl EnumVariant {
/// Construct a new enumeration variant from the given parts.
- pub fn new(
+ pub(crate) fn new(
name: String,
name_for_allowlisting: String,
comment: Option<String>,
@@ -285,35 +288,35 @@ impl EnumVariant {
}
/// Get this variant's name.
- pub fn name(&self) -> &str {
+ pub(crate) fn name(&self) -> &str {
&self.name
}
/// Get this variant's name.
- pub fn name_for_allowlisting(&self) -> &str {
+ pub(crate) fn name_for_allowlisting(&self) -> &str {
&self.name_for_allowlisting
}
/// Get this variant's value.
- pub fn val(&self) -> EnumVariantValue {
+ pub(crate) fn val(&self) -> EnumVariantValue {
self.val
}
/// Get this variant's documentation.
- pub fn comment(&self) -> Option<&str> {
+ pub(crate) fn comment(&self) -> Option<&str> {
self.comment.as_deref()
}
/// Returns whether this variant should be enforced to be a constant by code
/// generation.
- pub fn force_constification(&self) -> bool {
+ pub(crate) fn force_constification(&self) -> bool {
self.custom_behavior
.map_or(false, |b| b == EnumVariantCustomBehavior::Constify)
}
/// Returns whether the current variant should be hidden completely from the
/// resulting rust enum.
- pub fn hidden(&self) -> bool {
+ pub(crate) fn hidden(&self) -> bool {
self.custom_behavior
.map_or(false, |b| b == EnumVariantCustomBehavior::Hide)
}
diff --git a/ir/function.rs b/ir/function.rs
index baa2c36..fab380e 100644
--- a/ir/function.rs
+++ b/ir/function.rs
@@ -10,8 +10,7 @@ use crate::callbacks::{ItemInfo, ItemKind};
use crate::clang::{self, Attribute};
use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
use clang_sys::{self, CXCallingConv};
-use proc_macro2;
-use quote;
+
use quote::TokenStreamExt;
use std::io;
use std::str::FromStr;
@@ -20,7 +19,7 @@ const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
/// What kind of a function are we looking at?
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum FunctionKind {
+pub(crate) enum FunctionKind {
/// A plain, free function.
Function,
/// A method of some kind.
@@ -30,7 +29,7 @@ pub enum FunctionKind {
impl FunctionKind {
/// Given a clang cursor, return the kind of function it represents, or
/// `None` otherwise.
- pub fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
+ pub(crate) fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
// FIXME(emilio): Deduplicate logic with `ir::comp`.
Some(match cursor.kind() {
clang_sys::CXCursor_FunctionDecl => FunctionKind::Function,
@@ -64,7 +63,7 @@ impl FunctionKind {
/// The style of linkage
#[derive(Debug, Clone, Copy)]
-pub enum Linkage {
+pub(crate) enum Linkage {
/// Externally visible and can be linked against
External,
/// Not exposed externally. 'static inline' functions will have this kind of linkage
@@ -76,18 +75,18 @@ pub enum Linkage {
/// The argument names vector must be the same length as the ones in the
/// signature.
#[derive(Debug)]
-pub struct Function {
+pub(crate) struct Function {
/// The name of this function.
name: String,
/// The mangled name, that is, the symbol.
mangled_name: Option<String>,
- /// The id pointing to the current function signature.
- signature: TypeId,
+ /// The link name. If specified, overwrite mangled_name.
+ link_name: Option<String>,
- /// The doc comment on the function, if any.
- comment: Option<String>,
+ /// The ID pointing to the current function signature.
+ signature: TypeId,
/// The kind of function this is.
kind: FunctionKind,
@@ -98,51 +97,51 @@ pub struct Function {
impl Function {
/// Construct a new function.
- pub fn new(
+ pub(crate) fn new(
name: String,
mangled_name: Option<String>,
+ link_name: Option<String>,
signature: TypeId,
- comment: Option<String>,
kind: FunctionKind,
linkage: Linkage,
) -> Self {
Function {
name,
mangled_name,
+ link_name,
signature,
- comment,
kind,
linkage,
}
}
/// Get this function's name.
- pub fn name(&self) -> &str {
+ pub(crate) fn name(&self) -> &str {
&self.name
}
/// Get this function's name.
- pub fn mangled_name(&self) -> Option<&str> {
+ pub(crate) fn mangled_name(&self) -> Option<&str> {
self.mangled_name.as_deref()
}
- /// Get this function's signature type.
- pub fn signature(&self) -> TypeId {
- self.signature
+ /// Get this function's link name.
+ pub fn link_name(&self) -> Option<&str> {
+ self.link_name.as_deref()
}
- /// Get this function's comment.
- pub fn comment(&self) -> Option<&str> {
- self.comment.as_deref()
+ /// Get this function's signature type.
+ pub(crate) fn signature(&self) -> TypeId {
+ self.signature
}
/// Get this function's kind.
- pub fn kind(&self) -> FunctionKind {
+ pub(crate) fn kind(&self) -> FunctionKind {
self.kind
}
/// Get this function's linkage.
- pub fn linkage(&self) -> Linkage {
+ pub(crate) fn linkage(&self) -> Linkage {
self.linkage
}
}
@@ -177,6 +176,8 @@ pub enum Abi {
C,
/// The "stdcall" ABI.
Stdcall,
+ /// The "efiapi" ABI.
+ EfiApi,
/// The "fastcall" ABI.
Fastcall,
/// The "thiscall" ABI.
@@ -198,6 +199,7 @@ impl FromStr for Abi {
match s {
"C" => Ok(Self::C),
"stdcall" => Ok(Self::Stdcall),
+ "efiapi" => Ok(Self::EfiApi),
"fastcall" => Ok(Self::Fastcall),
"thiscall" => Ok(Self::ThisCall),
"vectorcall" => Ok(Self::Vectorcall),
@@ -214,6 +216,7 @@ impl std::fmt::Display for Abi {
let s = match *self {
Self::C => "C",
Self::Stdcall => "stdcall",
+ Self::EfiApi => "efiapi",
Self::Fastcall => "fastcall",
Self::ThisCall => "thiscall",
Self::Vectorcall => "vectorcall",
@@ -236,6 +239,7 @@ impl quote::ToTokens for Abi {
/// An ABI extracted from a clang cursor.
#[derive(Debug, Copy, Clone)]
pub(crate) enum ClangAbi {
+ /// An ABI known by Rust.
Known(Abi),
/// An unknown or invalid ABI.
Unknown(CXCallingConv),
@@ -262,7 +266,10 @@ impl quote::ToTokens for ClangAbi {
/// A function signature.
#[derive(Debug)]
-pub struct FunctionSig {
+pub(crate) struct FunctionSig {
+ /// The name of this function signature.
+ name: String,
+
/// The return type of the function.
return_type: TypeId,
@@ -297,7 +304,7 @@ fn get_abi(cc: CXCallingConv) -> ClangAbi {
}
/// Get the mangled name for the cursor's referent.
-pub fn cursor_mangling(
+pub(crate) fn cursor_mangling(
ctx: &BindgenContext,
cursor: &clang::Cursor,
) -> Option<String> {
@@ -399,7 +406,7 @@ fn args_from_ty_and_cursor(
impl FunctionSig {
/// Construct a new function signature from the given Clang type.
- pub fn from_ty(
+ pub(crate) fn from_ty(
ty: &clang::Type,
cursor: &clang::Cursor,
ctx: &mut BindgenContext,
@@ -572,7 +579,8 @@ impl FunctionSig {
warn!("Unknown calling convention: {:?}", call_conv);
}
- Ok(FunctionSig {
+ Ok(Self {
+ name: spelling,
return_type: ret,
argument_types: args,
is_variadic: ty.is_variadic(),
@@ -583,12 +591,12 @@ impl FunctionSig {
}
/// Get this function signature's return type.
- pub fn return_type(&self) -> TypeId {
+ pub(crate) fn return_type(&self) -> TypeId {
self.return_type
}
/// Get this function signature's argument (name, type) pairs.
- pub fn argument_types(&self) -> &[(Option<String>, TypeId)] {
+ pub(crate) fn argument_types(&self) -> &[(Option<String>, TypeId)] {
&self.argument_types
}
@@ -611,13 +619,20 @@ impl FunctionSig {
} else {
self.abi
}
+ } else if let Some((abi, _)) = ctx
+ .options()
+ .abi_overrides
+ .iter()
+ .find(|(_, regex_set)| regex_set.matches(&self.name))
+ {
+ ClangAbi::Known(*abi)
} else {
self.abi
}
}
/// Is this function signature variadic?
- pub fn is_variadic(&self) -> bool {
+ pub(crate) fn is_variadic(&self) -> bool {
// Clang reports some functions as variadic when they *might* be
// variadic. We do the argument check because rust doesn't codegen well
// variadic functions without an initial argument.
@@ -625,7 +640,7 @@ impl FunctionSig {
}
/// Must this function's return value be used?
- pub fn must_use(&self) -> bool {
+ pub(crate) fn must_use(&self) -> bool {
self.must_use
}
@@ -635,10 +650,10 @@ impl FunctionSig {
///
/// For more details, see:
///
- /// * https://github.com/rust-lang/rust-bindgen/issues/547,
- /// * https://github.com/rust-lang/rust/issues/38848,
- /// * and https://github.com/rust-lang/rust/issues/40158
- pub fn function_pointers_can_derive(&self) -> bool {
+ /// * <https://github.com/rust-lang/rust-bindgen/issues/547>,
+ /// * <https://github.com/rust-lang/rust/issues/38848>,
+ /// * and <https://github.com/rust-lang/rust/issues/40158>
+ pub(crate) fn function_pointers_can_derive(&self) -> bool {
if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
return false;
}
@@ -646,6 +661,7 @@ impl FunctionSig {
matches!(self.abi, ClangAbi::Known(Abi::C) | ClangAbi::Unknown(..))
}
+ /// Whether this function has attributes marking it as divergent.
pub(crate) fn is_divergent(&self) -> bool {
self.is_divergent
}
@@ -734,10 +750,22 @@ impl ClangSubItemParser for Function {
assert!(!name.is_empty(), "Empty function name.");
let mangled_name = cursor_mangling(context, &cursor);
- let comment = cursor.raw_comment();
- let function =
- Self::new(name.clone(), mangled_name, sig, comment, kind, linkage);
+ let link_name = context.options().last_callback(|callbacks| {
+ callbacks.generated_link_name_override(ItemInfo {
+ name: name.as_str(),
+ kind: ItemKind::Function,
+ })
+ });
+
+ let function = Self::new(
+ name.clone(),
+ mangled_name,
+ link_name,
+ sig,
+ kind,
+ linkage,
+ );
Ok(ParseResult::New(function, Some(cursor)))
}
diff --git a/ir/int.rs b/ir/int.rs
index 22838e8..4251b37 100644
--- a/ir/int.rs
+++ b/ir/int.rs
@@ -12,7 +12,7 @@ pub enum IntKind {
/// An `unsigned char`.
UChar,
- /// An `wchar_t`.
+ /// A `wchar_t`.
WChar,
/// A platform-dependent `char` type, with the signedness support.
@@ -87,7 +87,7 @@ pub enum IntKind {
impl IntKind {
/// Is this integral type signed?
- pub fn is_signed(&self) -> bool {
+ pub(crate) fn is_signed(&self) -> bool {
use self::IntKind::*;
match *self {
// TODO(emilio): wchar_t can in theory be signed, but we have no way
@@ -108,7 +108,7 @@ impl IntKind {
/// If this type has a known size, return it (in bytes). This is to
/// alleviate libclang sometimes not giving us a layout (like in the case
/// when an enum is defined inside a class with template parameters).
- pub fn known_size(&self) -> Option<usize> {
+ pub(crate) fn known_size(&self) -> Option<usize> {
use self::IntKind::*;
Some(match *self {
Bool | UChar | SChar | U8 | I8 | Char { .. } => 1,
@@ -121,7 +121,7 @@ impl IntKind {
}
/// Whether this type's signedness matches the value.
- pub fn signedness_matches(&self, val: i64) -> bool {
+ pub(crate) fn signedness_matches(&self, val: i64) -> bool {
val >= 0 || self.is_signed()
}
}
diff --git a/ir/item.rs b/ir/item.rs
index 40f6f7d..a50d267 100644
--- a/ir/item.rs
+++ b/ir/item.rs
@@ -19,9 +19,9 @@ use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::{Type, TypeKind};
use crate::clang;
use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
-use clang_sys;
+
use lazycell::LazyCell;
-use regex;
+
use std::cell::Cell;
use std::collections::BTreeSet;
use std::fmt::Write;
@@ -38,7 +38,7 @@ use std::iter;
///
/// This name is required to be safe for Rust, that is, is not expected to
/// return any rust keyword from here.
-pub trait ItemCanonicalName {
+pub(crate) trait ItemCanonicalName {
/// Get the canonical name for this item.
fn canonical_name(&self, ctx: &BindgenContext) -> String;
}
@@ -55,7 +55,7 @@ pub trait ItemCanonicalName {
///
/// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical
/// name is just `"BAR"`.
-pub trait ItemCanonicalPath {
+pub(crate) trait ItemCanonicalPath {
/// Get the namespace-aware canonical path for this item. This means that if
/// namespaces are disabled, you'll get a single item, and otherwise you get
/// the whole path.
@@ -69,7 +69,7 @@ pub trait ItemCanonicalPath {
}
/// A trait for determining if some IR thing is opaque or not.
-pub trait IsOpaque {
+pub(crate) trait IsOpaque {
/// Extra context the IR thing needs to determine if it is opaque or not.
type Extra;
@@ -80,20 +80,20 @@ pub trait IsOpaque {
}
/// A trait for determining if some IR thing has type parameter in array or not.
-pub trait HasTypeParamInArray {
+pub(crate) trait HasTypeParamInArray {
/// Returns `true` if the thing has Array, and `false` otherwise.
fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool;
}
/// A trait for determining if some IR thing has float or not.
-pub trait HasFloat {
+pub(crate) trait HasFloat {
/// Returns `true` if the thing has float, and `false` otherwise.
fn has_float(&self, ctx: &BindgenContext) -> bool;
}
/// A trait for iterating over an item and its parents and up its ancestor chain
/// up to (but not including) the implicit root module.
-pub trait ItemAncestors {
+pub(crate) trait ItemAncestors {
/// Get an iterable over this item's ancestors.
fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>;
}
@@ -118,7 +118,7 @@ impl DebugOnlyItemSet {
}
/// An iterator over an item and its ancestors.
-pub struct ItemAncestorsIter<'a> {
+pub(crate) struct ItemAncestorsIter<'a> {
item: ItemId,
ctx: &'a BindgenContext,
seen: DebugOnlyItemSet,
@@ -362,7 +362,7 @@ impl CanDeriveOrd for Item {
/// information).
///
/// Items refer to each other by `ItemId`. Every item has its parent's
-/// id. Depending on the kind of item this is, it may also refer to other items,
+/// ID. Depending on the kind of item this is, it may also refer to other items,
/// such as a compound type item referring to other types. Collectively, these
/// references form a graph.
///
@@ -375,20 +375,20 @@ impl CanDeriveOrd for Item {
/// all of them apply to every item. Those rules are described in the
/// `annotations` module.
#[derive(Debug)]
-pub struct Item {
- /// This item's id.
+pub(crate) struct Item {
+ /// This item's ID.
id: ItemId,
- /// The item's local id, unique only amongst its siblings. Only used for
+ /// The item's local ID, unique only amongst its siblings. Only used for
/// anonymous items.
///
/// Lazily initialized in local_id().
///
- /// Note that only structs, unions, and enums get a local type id. In any
+ /// Note that only structs, unions, and enums get a local type ID. In any
/// case this is an implementation detail.
local_id: LazyCell<usize>,
- /// The next local id to use for a child or template instantiation.
+ /// The next local ID to use for a child or template instantiation.
next_child_local_id: Cell<usize>,
/// A cached copy of the canonical name, as returned by `canonical_name`.
@@ -406,11 +406,11 @@ pub struct Item {
/// Annotations extracted from the doc comment, or the default ones
/// otherwise.
annotations: Annotations,
- /// An item's parent id. This will most likely be a class where this item
+ /// An item's parent ID. This will most likely be a class where this item
/// was declared, or a module, etc.
///
/// All the items have a parent, except the root module, in which case the
- /// parent id is its own id.
+ /// parent ID is its own ID.
parent_id: ItemId,
/// The item kind.
kind: ItemKind,
@@ -426,7 +426,7 @@ impl AsRef<ItemId> for Item {
impl Item {
/// Construct a new `Item`.
- pub fn new(
+ pub(crate) fn new(
id: ItemId,
comment: Option<String>,
annotations: Option<Annotations>,
@@ -450,7 +450,7 @@ impl Item {
}
/// Construct a new opaque item type.
- pub fn new_opaque_type(
+ pub(crate) fn new_opaque_type(
with_id: ItemId,
ty: &clang::Type,
ctx: &mut BindgenContext,
@@ -468,28 +468,31 @@ impl Item {
}
/// Get this `Item`'s identifier.
- pub fn id(&self) -> ItemId {
+ pub(crate) fn id(&self) -> ItemId {
self.id
}
/// Get this `Item`'s parent's identifier.
///
/// For the root module, the parent's ID is its own ID.
- pub fn parent_id(&self) -> ItemId {
+ pub(crate) fn parent_id(&self) -> ItemId {
self.parent_id
}
- /// Set this item's parent id.
+ /// Set this item's parent ID.
///
/// This is only used so replacements get generated in the proper module.
- pub fn set_parent_for_replacement<Id: Into<ItemId>>(&mut self, id: Id) {
+ pub(crate) fn set_parent_for_replacement<Id: Into<ItemId>>(
+ &mut self,
+ id: Id,
+ ) {
self.parent_id = id.into();
}
/// Returns the depth this item is indented to.
///
/// FIXME(emilio): This may need fixes for the enums within modules stuff.
- pub fn codegen_depth(&self, ctx: &BindgenContext) -> usize {
+ pub(crate) fn codegen_depth(&self, ctx: &BindgenContext) -> usize {
if !ctx.options().enable_cxx_namespaces {
return 0;
}
@@ -507,7 +510,7 @@ impl Item {
/// Get this `Item`'s comment, if it has any, already preprocessed and with
/// the right indentation.
- pub fn comment(&self, ctx: &BindgenContext) -> Option<String> {
+ pub(crate) fn comment(&self, ctx: &BindgenContext) -> Option<String> {
if !ctx.options().generate_comments {
return None;
}
@@ -518,17 +521,17 @@ impl Item {
}
/// What kind of item is this?
- pub fn kind(&self) -> &ItemKind {
+ pub(crate) fn kind(&self) -> &ItemKind {
&self.kind
}
/// Get a mutable reference to this item's kind.
- pub fn kind_mut(&mut self) -> &mut ItemKind {
+ pub(crate) fn kind_mut(&mut self) -> &mut ItemKind {
&mut self.kind
}
/// Where in the source is this item located?
- pub fn location(&self) -> Option<&clang::SourceLocation> {
+ pub(crate) fn location(&self) -> Option<&clang::SourceLocation> {
self.location.as_ref()
}
@@ -537,7 +540,7 @@ impl Item {
/// This should stay relatively stable in the face of code motion outside or
/// below this item's lexical scope, meaning that this can be useful for
/// generating relatively stable identifiers within a scope.
- pub fn local_id(&self, ctx: &BindgenContext) -> usize {
+ pub(crate) fn local_id(&self, ctx: &BindgenContext) -> usize {
*self.local_id.borrow_with(|| {
let parent = ctx.resolve_item(self.parent_id);
parent.next_child_local_id()
@@ -550,7 +553,7 @@ impl Item {
/// This is currently used for anonymous items, and template instantiation
/// tests, in both cases in order to reduce noise when system headers are at
/// place.
- pub fn next_child_local_id(&self) -> usize {
+ pub(crate) fn next_child_local_id(&self) -> usize {
let local_id = self.next_child_local_id.get();
self.next_child_local_id.set(local_id + 1);
local_id
@@ -574,7 +577,7 @@ impl Item {
/// This function is used to determine when the codegen phase should call
/// `codegen` on an item, since any item that is not top-level will be
/// generated by its parent.
- pub fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
+ pub(crate) fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
// FIXME: Workaround for some types falling behind when parsing weird
// stl classes, for example.
if ctx.options().enable_cxx_namespaces &&
@@ -605,36 +608,36 @@ impl Item {
/// Get a reference to this item's underlying `Type`. Panic if this is some
/// other kind of item.
- pub fn expect_type(&self) -> &Type {
+ pub(crate) fn expect_type(&self) -> &Type {
self.kind().expect_type()
}
/// Get a reference to this item's underlying `Type`, or `None` if this is
/// some other kind of item.
- pub fn as_type(&self) -> Option<&Type> {
+ pub(crate) fn as_type(&self) -> Option<&Type> {
self.kind().as_type()
}
/// Get a reference to this item's underlying `Function`. Panic if this is
/// some other kind of item.
- pub fn expect_function(&self) -> &Function {
+ pub(crate) fn expect_function(&self) -> &Function {
self.kind().expect_function()
}
/// Is this item a module?
- pub fn is_module(&self) -> bool {
+ pub(crate) fn is_module(&self) -> bool {
matches!(self.kind, ItemKind::Module(..))
}
/// Get this item's annotations.
- pub fn annotations(&self) -> &Annotations {
+ pub(crate) fn annotations(&self) -> &Annotations {
&self.annotations
}
/// Whether this item should be blocklisted.
///
/// This may be due to either annotations or to other kind of configuration.
- pub fn is_blocklisted(&self, ctx: &BindgenContext) -> bool {
+ pub(crate) fn is_blocklisted(&self, ctx: &BindgenContext) -> bool {
debug_assert!(
ctx.in_codegen_phase(),
"You're not supposed to call this yet"
@@ -670,22 +673,15 @@ impl Item {
}
}
- /// Is this a reference to another type?
- pub fn is_type_ref(&self) -> bool {
- self.as_type().map_or(false, |ty| ty.is_type_ref())
- }
-
- /// Is this item a var type?
- pub fn is_var(&self) -> bool {
- matches!(*self.kind(), ItemKind::Var(..))
- }
-
/// Take out item NameOptions
- pub fn name<'a>(&'a self, ctx: &'a BindgenContext) -> NameOptions<'a> {
+ pub(crate) fn name<'a>(
+ &'a self,
+ ctx: &'a BindgenContext,
+ ) -> NameOptions<'a> {
NameOptions::new(self, ctx)
}
- /// Get the target item id for name generation.
+ /// Get the target item ID for name generation.
fn name_target(&self, ctx: &BindgenContext) -> ItemId {
let mut targets_seen = DebugOnlyItemSet::new();
let mut item = self;
@@ -715,7 +711,10 @@ impl Item {
/// Create a fully disambiguated name for an item, including template
/// parameters if it is a type
- pub fn full_disambiguated_name(&self, ctx: &BindgenContext) -> String {
+ pub(crate) fn full_disambiguated_name(
+ &self,
+ ctx: &BindgenContext,
+ ) -> String {
let mut s = String::new();
let level = 0;
self.push_disambiguated_name(ctx, &mut s, level);
@@ -839,7 +838,7 @@ impl Item {
/// If `BindgenOptions::disable_nested_struct_naming` is true then returned
/// name is the inner most non-anonymous name plus all the anonymous base names
/// that follows.
- pub fn real_canonical_name(
+ pub(crate) fn real_canonical_name(
&self,
ctx: &BindgenContext,
opt: &NameOptions,
@@ -862,7 +861,7 @@ impl Item {
return base_name;
}
- // Ancestors' id iter
+ // Ancestors' ID iter
let mut ids_iter = target
.parent_id()
.ancestors(ctx)
@@ -939,11 +938,11 @@ impl Item {
ctx.rust_mangle(&name).into_owned()
}
- /// The exposed id that represents an unique id among the siblings of a
+ /// The exposed ID that represents an unique ID among the siblings of a
/// given item.
- pub fn exposed_id(&self, ctx: &BindgenContext) -> String {
+ pub(crate) fn exposed_id(&self, ctx: &BindgenContext) -> String {
// Only use local ids for enums, classes, structs and union types. All
- // other items use their global id.
+ // other items use their global ID.
let ty_kind = self.kind().as_type().map(|t| t.kind());
if let Some(ty_kind) = ty_kind {
match *ty_kind {
@@ -955,14 +954,14 @@ impl Item {
}
// Note that this `id_` prefix prevents (really unlikely) collisions
- // between the global id and the local id of an item with the same
+ // between the global ID and the local ID of an item with the same
// parent.
format!("id_{}", self.id().as_usize())
}
/// Get a reference to this item's `Module`, or `None` if this is not a
/// `Module` item.
- pub fn as_module(&self) -> Option<&Module> {
+ pub(crate) fn as_module(&self) -> Option<&Module> {
match self.kind {
ItemKind::Module(ref module) => Some(module),
_ => None,
@@ -971,7 +970,7 @@ impl Item {
/// Get a mutable reference to this item's `Module`, or `None` if this is
/// not a `Module` item.
- pub fn as_module_mut(&mut self) -> Option<&mut Module> {
+ pub(crate) fn as_module_mut(&mut self) -> Option<&mut Module> {
match self.kind {
ItemKind::Module(ref mut module) => Some(module),
_ => None,
@@ -1010,7 +1009,7 @@ impl Item {
}
/// Is this item of a kind that is enabled for code generation?
- pub fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
+ pub(crate) fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
let cc = &ctx.options().codegen_config;
match *self.kind() {
ItemKind::Module(..) => true,
@@ -1036,7 +1035,10 @@ impl Item {
/// Returns the path we should use for allowlisting / blocklisting, which
/// doesn't include user-mangling.
- pub fn path_for_allowlisting(&self, ctx: &BindgenContext) -> &Vec<String> {
+ pub(crate) fn path_for_allowlisting(
+ &self,
+ ctx: &BindgenContext,
+ ) -> &Vec<String> {
self.path_for_allowlisting
.borrow_with(|| self.compute_path(ctx, UserMangled::No))
}
@@ -1094,8 +1096,8 @@ impl Item {
})
}
- /// Whether this is a #[must_use] type.
- pub fn must_use(&self, ctx: &BindgenContext) -> bool {
+ /// Whether this is a `#[must_use]` type.
+ pub(crate) fn must_use(&self, ctx: &BindgenContext) -> bool {
self.annotations().must_use_type() || ctx.must_use_type_by_name(self)
}
}
@@ -1222,7 +1224,7 @@ impl HasFloat for Item {
}
/// A set of items.
-pub type ItemSet = BTreeSet<ItemId>;
+pub(crate) type ItemSet = BTreeSet<ItemId>;
impl DotAttributes for Item {
fn dot_attributes<W>(
@@ -1306,6 +1308,7 @@ fn visit_child(
}
impl Item {
+ /// Create a builtin type.
pub(crate) fn builtin_type(
kind: TypeKind,
is_const: bool,
@@ -1331,6 +1334,7 @@ impl Item {
id.as_type_id_unchecked()
}
+ /// Parse this item from the given Clang cursor.
pub(crate) fn parse(
cursor: clang::Cursor,
parent_id: Option<ItemId>,
@@ -1349,6 +1353,7 @@ impl Item {
let current_module = ctx.current_module().into();
let relevant_parent_id = parent_id.unwrap_or(current_module);
+ #[allow(clippy::missing_docs_in_private_items)]
macro_rules! try_parse {
($what:ident) => {
match $what::parse(cursor, ctx) {
@@ -1477,6 +1482,8 @@ impl Item {
}
}
+ /// Parse this item from the given Clang type, or if we haven't resolved all
+ /// the other items this one depends on, an unresolved reference.
pub(crate) fn from_ty_or_ref(
ty: clang::Type,
location: clang::Cursor,
@@ -1552,6 +1559,7 @@ impl Item {
potential_id.as_type_id_unchecked()
}
+ /// Parse this item from the given Clang type. See [`Item::from_ty_with_id`].
pub(crate) fn from_ty(
ty: &clang::Type,
location: clang::Cursor,
@@ -1565,10 +1573,10 @@ impl Item {
/// This is one of the trickiest methods you'll find (probably along with
/// some of the ones that handle templates in `BindgenContext`).
///
- /// This method parses a type, given the potential id of that type (if
+ /// This method parses a type, given the potential ID of that type (if
/// parsing it was correct), an optional location we're scanning, which is
- /// critical some times to obtain information, an optional parent item id,
- /// that will, if it's `None`, become the current module id, and the
+ /// critical some times to obtain information, an optional parent item ID,
+ /// that will, if it's `None`, become the current module ID, and the
/// context.
pub(crate) fn from_ty_with_id(
id: ItemId,
@@ -1617,7 +1625,11 @@ impl Item {
canonical_def.unwrap_or_else(|| ty.declaration())
};
- let comment = decl.raw_comment().or_else(|| location.raw_comment());
+ let comment = location
+ .raw_comment()
+ .or_else(|| decl.raw_comment())
+ .or_else(|| location.raw_comment());
+
let annotations =
Annotations::new(&decl).or_else(|| Annotations::new(&location));
@@ -1737,9 +1749,8 @@ impl Item {
ret
}
- /// A named type is a template parameter, e.g., the "T" in Foo<T>. They're
- /// always local so it's the only exception when there's no declaration for
- /// a type.
+ /// A named type is a template parameter, e.g., the `T` in `Foo<T>`. They're always local so
+ /// it's the only exception when there's no declaration for a type.
pub(crate) fn type_param(
with_id: Option<ItemId>,
location: clang::Cursor,
@@ -1978,7 +1989,7 @@ enum UserMangled {
/// Builder struct for naming variations, which hold inside different
/// flags for naming options.
#[derive(Debug)]
-pub struct NameOptions<'a> {
+pub(crate) struct NameOptions<'a> {
item: &'a Item,
ctx: &'a BindgenContext,
within_namespaces: bool,
@@ -1987,7 +1998,7 @@ pub struct NameOptions<'a> {
impl<'a> NameOptions<'a> {
/// Construct a new `NameOptions`
- pub fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
+ pub(crate) fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
NameOptions {
item,
ctx,
@@ -1998,7 +2009,7 @@ impl<'a> NameOptions<'a> {
/// Construct the name without the item's containing C++ namespaces mangled
/// into it. In other words, the item's name within the item's namespace.
- pub fn within_namespaces(&mut self) -> &mut Self {
+ pub(crate) fn within_namespaces(&mut self) -> &mut Self {
self.within_namespaces = true;
self
}
@@ -2009,7 +2020,7 @@ impl<'a> NameOptions<'a> {
}
/// Construct a name `String`
- pub fn get(&self) -> String {
+ pub(crate) fn get(&self) -> String {
self.item.real_canonical_name(self.ctx, self)
}
}
diff --git a/ir/item_kind.rs b/ir/item_kind.rs
index 4a12fef..e861849 100644
--- a/ir/item_kind.rs
+++ b/ir/item_kind.rs
@@ -10,7 +10,7 @@ use std::io;
/// A item we parse and translate.
#[derive(Debug)]
-pub enum ItemKind {
+pub(crate) enum ItemKind {
/// A module, created implicitly once (the root module), or via C++
/// namespaces.
Module(Module),
@@ -28,7 +28,7 @@ pub enum ItemKind {
impl ItemKind {
/// Get a reference to this `ItemKind`'s underying `Module`, or `None` if it
/// is some other kind.
- pub fn as_module(&self) -> Option<&Module> {
+ pub(crate) fn as_module(&self) -> Option<&Module> {
match *self {
ItemKind::Module(ref module) => Some(module),
_ => None,
@@ -36,7 +36,7 @@ impl ItemKind {
}
/// Transform our `ItemKind` into a string.
- pub fn kind_name(&self) -> &'static str {
+ pub(crate) fn kind_name(&self) -> &'static str {
match *self {
ItemKind::Module(..) => "Module",
ItemKind::Type(..) => "Type",
@@ -46,19 +46,13 @@ impl ItemKind {
}
/// Is this a module?
- pub fn is_module(&self) -> bool {
+ pub(crate) fn is_module(&self) -> bool {
self.as_module().is_some()
}
- /// Get a reference to this `ItemKind`'s underying `Module`, or panic if it
- /// is some other kind.
- pub fn expect_module(&self) -> &Module {
- self.as_module().expect("Not a module")
- }
-
/// Get a reference to this `ItemKind`'s underying `Function`, or `None` if
/// it is some other kind.
- pub fn as_function(&self) -> Option<&Function> {
+ pub(crate) fn as_function(&self) -> Option<&Function> {
match *self {
ItemKind::Function(ref func) => Some(func),
_ => None,
@@ -66,19 +60,19 @@ impl ItemKind {
}
/// Is this a function?
- pub fn is_function(&self) -> bool {
+ pub(crate) fn is_function(&self) -> bool {
self.as_function().is_some()
}
/// Get a reference to this `ItemKind`'s underying `Function`, or panic if
/// it is some other kind.
- pub fn expect_function(&self) -> &Function {
+ pub(crate) fn expect_function(&self) -> &Function {
self.as_function().expect("Not a function")
}
/// Get a reference to this `ItemKind`'s underying `Type`, or `None` if
/// it is some other kind.
- pub fn as_type(&self) -> Option<&Type> {
+ pub(crate) fn as_type(&self) -> Option<&Type> {
match *self {
ItemKind::Type(ref ty) => Some(ty),
_ => None,
@@ -87,7 +81,7 @@ impl ItemKind {
/// Get a mutable reference to this `ItemKind`'s underying `Type`, or `None`
/// if it is some other kind.
- pub fn as_type_mut(&mut self) -> Option<&mut Type> {
+ pub(crate) fn as_type_mut(&mut self) -> Option<&mut Type> {
match *self {
ItemKind::Type(ref mut ty) => Some(ty),
_ => None,
@@ -95,19 +89,19 @@ impl ItemKind {
}
/// Is this a type?
- pub fn is_type(&self) -> bool {
+ pub(crate) fn is_type(&self) -> bool {
self.as_type().is_some()
}
/// Get a reference to this `ItemKind`'s underying `Type`, or panic if it is
/// some other kind.
- pub fn expect_type(&self) -> &Type {
+ pub(crate) fn expect_type(&self) -> &Type {
self.as_type().expect("Not a type")
}
/// Get a reference to this `ItemKind`'s underying `Var`, or `None` if it is
/// some other kind.
- pub fn as_var(&self) -> Option<&Var> {
+ pub(crate) fn as_var(&self) -> Option<&Var> {
match *self {
ItemKind::Var(ref v) => Some(v),
_ => None,
@@ -115,15 +109,9 @@ impl ItemKind {
}
/// Is this a variable?
- pub fn is_var(&self) -> bool {
+ pub(crate) fn is_var(&self) -> bool {
self.as_var().is_some()
}
-
- /// Get a reference to this `ItemKind`'s underying `Var`, or panic if it is
- /// some other kind.
- pub fn expect_var(&self) -> &Var {
- self.as_var().expect("Not a var")
- }
}
impl DotAttributes for ItemKind {
diff --git a/ir/layout.rs b/ir/layout.rs
index 6f45030..ba944b0 100644
--- a/ir/layout.rs
+++ b/ir/layout.rs
@@ -8,13 +8,13 @@ use std::cmp;
/// A type that represents the struct layout of a type.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct Layout {
+pub(crate) struct Layout {
/// The size (in bytes) of this layout.
- pub size: usize,
+ pub(crate) size: usize,
/// The alignment (in bytes) of this layout.
- pub align: usize,
+ pub(crate) align: usize,
/// Whether this layout's members are packed or not.
- pub packed: bool,
+ pub(crate) packed: bool,
}
#[test]
@@ -34,7 +34,7 @@ fn test_layout_for_size() {
impl Layout {
/// Gets the integer type name for a given known size.
- pub fn known_type_for_size(
+ pub(crate) fn known_type_for_size(
ctx: &BindgenContext,
size: usize,
) -> Option<&'static str> {
@@ -50,7 +50,7 @@ impl Layout {
/// Construct a new `Layout` with the given `size` and `align`. It is not
/// packed.
- pub fn new(size: usize, align: usize) -> Self {
+ pub(crate) fn new(size: usize, align: usize) -> Self {
Layout {
size,
align,
@@ -72,33 +72,26 @@ 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 {
+ pub(crate) 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
- }
-
- /// Construct a zero-sized layout.
- pub fn zero() -> Self {
- Self::new(0, 0)
- }
-
/// Get this layout as an opaque type.
- pub fn opaque(&self) -> Opaque {
+ pub(crate) fn opaque(&self) -> Opaque {
Opaque(*self)
}
}
/// When we are treating a type as opaque, it is just a blob with a `Layout`.
#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Opaque(pub Layout);
+pub(crate) struct Opaque(pub(crate) Layout);
impl Opaque {
/// Construct a new opaque type from the given clang type.
- pub fn from_clang_ty(ty: &clang::Type, ctx: &BindgenContext) -> Type {
+ pub(crate) fn from_clang_ty(
+ ty: &clang::Type,
+ ctx: &BindgenContext,
+ ) -> Type {
let layout = Layout::new(ty.size(ctx), ty.align(ctx));
let ty_kind = TypeKind::Opaque;
let is_const = ty.is_const();
@@ -107,7 +100,7 @@ impl Opaque {
/// Return the known rust type we should use to create a correctly-aligned
/// field with this layout.
- pub fn known_rust_type_for_array(
+ pub(crate) fn known_rust_type_for_array(
&self,
ctx: &BindgenContext,
) -> Option<&'static str> {
@@ -116,7 +109,7 @@ impl Opaque {
/// Return the array size that an opaque type for this layout should have if
/// we know the correct type for it, or `None` otherwise.
- pub fn array_size(&self, ctx: &BindgenContext) -> Option<usize> {
+ pub(crate) fn array_size(&self, ctx: &BindgenContext) -> Option<usize> {
if self.known_rust_type_for_array(ctx).is_some() {
Some(self.0.size / cmp::max(self.0.align, 1))
} else {
@@ -127,7 +120,7 @@ impl Opaque {
/// Return `true` if this opaque layout's array size will fit within the
/// maximum number of array elements that Rust allows deriving traits
/// with. Return `false` otherwise.
- pub fn array_size_within_derive_limit(
+ pub(crate) fn array_size_within_derive_limit(
&self,
ctx: &BindgenContext,
) -> CanDerive {
diff --git a/ir/mod.rs b/ir/mod.rs
index 8f6a2da..acdb489 100644
--- a/ir/mod.rs
+++ b/ir/mod.rs
@@ -2,23 +2,24 @@
//!
//! Parsing C/C++ generates the IR, while code generation outputs Rust code from
//! the IR.
+#![deny(clippy::missing_docs_in_private_items)]
-pub mod analysis;
-pub mod annotations;
-pub mod comment;
-pub mod comp;
-pub mod context;
-pub mod derive;
-pub mod dot;
-pub mod enum_ty;
-pub mod function;
-pub mod int;
-pub mod item;
-pub mod item_kind;
-pub mod layout;
-pub mod module;
-pub mod objc;
-pub mod template;
-pub mod traversal;
-pub mod ty;
-pub mod var;
+pub(crate) mod analysis;
+pub(crate) mod annotations;
+pub(crate) mod comment;
+pub(crate) mod comp;
+pub(crate) mod context;
+pub(crate) mod derive;
+pub(crate) mod dot;
+pub(crate) mod enum_ty;
+pub(crate) mod function;
+pub(crate) mod int;
+pub(crate) mod item;
+pub(crate) mod item_kind;
+pub(crate) mod layout;
+pub(crate) mod module;
+pub(crate) mod objc;
+pub(crate) mod template;
+pub(crate) mod traversal;
+pub(crate) mod ty;
+pub(crate) mod var;
diff --git a/ir/module.rs b/ir/module.rs
index d5aca94..f25ef40 100644
--- a/ir/module.rs
+++ b/ir/module.rs
@@ -10,7 +10,7 @@ use std::io;
/// Whether this module is inline or not.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum ModuleKind {
+pub(crate) enum ModuleKind {
/// This module is not inline.
Normal,
/// This module is inline, as in `inline namespace foo {}`.
@@ -19,7 +19,7 @@ pub enum ModuleKind {
/// A module, as in, a C++ namespace.
#[derive(Clone, Debug)]
-pub struct Module {
+pub(crate) struct Module {
/// The name of the module, or none if it's anonymous.
name: Option<String>,
/// The kind of module this is.
@@ -30,7 +30,7 @@ pub struct Module {
impl Module {
/// Construct a new `Module`.
- pub fn new(name: Option<String>, kind: ModuleKind) -> Self {
+ pub(crate) fn new(name: Option<String>, kind: ModuleKind) -> Self {
Module {
name,
kind,
@@ -39,22 +39,22 @@ impl Module {
}
/// Get this module's name.
- pub fn name(&self) -> Option<&str> {
+ pub(crate) fn name(&self) -> Option<&str> {
self.name.as_deref()
}
/// Get a mutable reference to this module's children.
- pub fn children_mut(&mut self) -> &mut ItemSet {
+ pub(crate) fn children_mut(&mut self) -> &mut ItemSet {
&mut self.children
}
/// Get this module's children.
- pub fn children(&self) -> &ItemSet {
+ pub(crate) fn children(&self) -> &ItemSet {
&self.children
}
/// Whether this namespace is inline.
- pub fn is_inline(&self) -> bool {
+ pub(crate) fn is_inline(&self) -> bool {
self.kind == ModuleKind::Inline
}
}
diff --git a/ir/objc.rs b/ir/objc.rs
index 4f340f6..eaf3b8a 100644
--- a/ir/objc.rs
+++ b/ir/objc.rs
@@ -21,7 +21,7 @@ use proc_macro2::{Ident, Span, TokenStream};
///
/// Also protocols and categories are parsed as this type
#[derive(Debug)]
-pub struct ObjCInterface {
+pub(crate) struct ObjCInterface {
/// The name
/// like, NSObject
name: String,
@@ -31,13 +31,13 @@ pub struct ObjCInterface {
is_protocol: bool,
/// The list of template names almost always, ObjectType or KeyType
- pub template_names: Vec<String>,
+ pub(crate) template_names: Vec<String>,
/// The list of protocols that this interface conforms to.
- pub conforms_to: Vec<ItemId>,
+ pub(crate) conforms_to: Vec<ItemId>,
/// The direct parent for this interface.
- pub parent_class: Option<ItemId>,
+ pub(crate) parent_class: Option<ItemId>,
/// List of the methods defined in this interfae
methods: Vec<ObjCMethod>,
@@ -47,7 +47,7 @@ pub struct ObjCInterface {
/// The objective c methods
#[derive(Debug)]
-pub struct ObjCMethod {
+pub(crate) struct ObjCMethod {
/// The original method selector name
/// like, dataWithBytes:length:
name: String,
@@ -78,14 +78,14 @@ impl ObjCInterface {
/// The name
/// like, NSObject
- pub fn name(&self) -> &str {
+ pub(crate) fn name(&self) -> &str {
self.name.as_ref()
}
/// Formats the name for rust
/// Can be like NSObject, but with categories might be like NSObject_NSCoderMethods
/// and protocols are like PNSObject
- pub fn rust_name(&self) -> String {
+ pub(crate) fn rust_name(&self) -> String {
if let Some(ref cat) = self.category {
format!("{}_{}", self.name(), cat)
} else if self.is_protocol {
@@ -96,32 +96,32 @@ impl ObjCInterface {
}
/// Is this a template interface?
- pub fn is_template(&self) -> bool {
+ pub(crate) fn is_template(&self) -> bool {
!self.template_names.is_empty()
}
/// List of the methods defined in this interface
- pub fn methods(&self) -> &Vec<ObjCMethod> {
+ pub(crate) fn methods(&self) -> &Vec<ObjCMethod> {
&self.methods
}
/// Is this a protocol?
- pub fn is_protocol(&self) -> bool {
+ pub(crate) fn is_protocol(&self) -> bool {
self.is_protocol
}
/// Is this a category?
- pub fn is_category(&self) -> bool {
+ pub(crate) fn is_category(&self) -> bool {
self.category.is_some()
}
/// List of the class methods defined in this interface
- pub fn class_methods(&self) -> &Vec<ObjCMethod> {
+ pub(crate) fn class_methods(&self) -> &Vec<ObjCMethod> {
&self.class_methods
}
/// Parses the Objective C interface from the cursor
- pub fn from_ty(
+ pub(crate) fn from_ty(
cursor: &clang::Cursor,
ctx: &mut BindgenContext,
) -> Option<Self> {
@@ -229,30 +229,27 @@ impl ObjCMethod {
}
}
- /// The original method selector name
- /// like, dataWithBytes:length:
- pub fn name(&self) -> &str {
- self.name.as_ref()
- }
-
/// Method name as converted to rust
/// like, dataWithBytes_length_
- pub fn rust_name(&self) -> &str {
+ pub(crate) fn rust_name(&self) -> &str {
self.rust_name.as_ref()
}
/// Returns the methods signature as FunctionSig
- pub fn signature(&self) -> &FunctionSig {
+ pub(crate) fn signature(&self) -> &FunctionSig {
&self.signature
}
/// Is this a class method?
- pub fn is_class_method(&self) -> bool {
+ pub(crate) fn is_class_method(&self) -> bool {
self.is_class_method
}
/// Formats the method call
- pub fn format_method_call(&self, args: &[TokenStream]) -> TokenStream {
+ pub(crate) fn format_method_call(
+ &self,
+ args: &[TokenStream],
+ ) -> TokenStream {
let split_name: Vec<Option<Ident>> = self
.name
.split(':')
diff --git a/ir/template.rs b/ir/template.rs
index e3ef6a9..4dd8442 100644
--- a/ir/template.rs
+++ b/ir/template.rs
@@ -77,28 +77,28 @@ use crate::clang;
/// The following table depicts the results of each trait method when invoked on
/// each of the declarations above:
///
-/// +------+----------------------+--------------------------+------------------------+----
-/// |Decl. | self_template_params | num_self_template_params | all_template_parameters| ...
-/// +------+----------------------+--------------------------+------------------------+----
-/// |Foo | [T, U] | 2 | [T, U] | ...
-/// |Bar | [V] | 1 | [T, U, V] | ...
-/// |Inner | [] | 0 | [T, U] | ...
-/// |Lol | [W] | 1 | [T, U, W] | ...
-/// |Wtf | [X] | 1 | [T, U, X] | ...
-/// |Qux | [] | 0 | [] | ...
+/// +------+----------------------+--------------------------+-------------------------+----
+/// |Decl. | self_template_params | num_self_template_params | all_template_parameters | ...
+/// +------+----------------------+--------------------------+-------------------------+----
+/// |Foo | T, U | 2 | T, U | ...
+/// |Bar | V | 1 | T, U, V | ...
+/// |Inner | | 0 | T, U | ...
+/// |Lol | W | 1 | T, U, W | ...
+/// |Wtf | X | 1 | T, U, X | ...
+/// |Qux | | 0 | | ...
/// +------+----------------------+--------------------------+------------------------+----
///
/// ----+------+-----+----------------------+
/// ... |Decl. | ... | used_template_params |
/// ----+------+-----+----------------------+
-/// ... |Foo | ... | [T, U] |
-/// ... |Bar | ... | [V] |
-/// ... |Inner | ... | [] |
-/// ... |Lol | ... | [T] |
-/// ... |Wtf | ... | [T] |
-/// ... |Qux | ... | [] |
+/// ... |Foo | ... | T, U |
+/// ... |Bar | ... | V |
+/// ... |Inner | ... | |
+/// ... |Lol | ... | T |
+/// ... |Wtf | ... | T |
+/// ... |Qux | ... | |
/// ----+------+-----+----------------------+
-pub trait TemplateParameters: Sized {
+pub(crate) trait TemplateParameters: Sized {
/// Get the set of `ItemId`s that make up this template declaration's free
/// template parameters.
///
@@ -163,11 +163,11 @@ pub trait TemplateParameters: Sized {
}
/// A trait for things which may or may not be a named template type parameter.
-pub trait AsTemplateParam {
+pub(crate) trait AsTemplateParam {
/// Any extra information the implementor might need to make this decision.
type Extra;
- /// Convert this thing to the item id of a named template type parameter.
+ /// Convert this thing to the item ID of a named template type parameter.
fn as_template_param(
&self,
ctx: &BindgenContext,
@@ -186,7 +186,7 @@ pub trait AsTemplateParam {
/// A concrete instantiation of a generic template.
#[derive(Clone, Debug)]
-pub struct TemplateInstantiation {
+pub(crate) struct TemplateInstantiation {
/// The template definition which this is instantiating.
definition: TypeId,
/// The concrete template arguments, which will be substituted in the
@@ -196,7 +196,7 @@ pub struct TemplateInstantiation {
impl TemplateInstantiation {
/// Construct a new template instantiation from the given parts.
- pub fn new<I>(definition: TypeId, args: I) -> TemplateInstantiation
+ pub(crate) fn new<I>(definition: TypeId, args: I) -> TemplateInstantiation
where
I: IntoIterator<Item = TypeId>,
{
@@ -207,17 +207,17 @@ impl TemplateInstantiation {
}
/// Get the template definition for this instantiation.
- pub fn template_definition(&self) -> TypeId {
+ pub(crate) fn template_definition(&self) -> TypeId {
self.definition
}
/// Get the concrete template arguments used in this instantiation.
- pub fn template_arguments(&self) -> &[TypeId] {
+ pub(crate) fn template_arguments(&self) -> &[TypeId] {
&self.args[..]
}
/// Parse a `TemplateInstantiation` from a clang `Type`.
- pub fn from_ty(
+ pub(crate) fn from_ty(
ty: &clang::Type,
ctx: &mut BindgenContext,
) -> Option<TemplateInstantiation> {
diff --git a/ir/traversal.rs b/ir/traversal.rs
index f14483f..17e24f7 100644
--- a/ir/traversal.rs
+++ b/ir/traversal.rs
@@ -12,14 +12,14 @@ use std::collections::{BTreeMap, VecDeque};
/// The `from` is left implicit: it is the concrete `Trace` implementer which
/// yielded this outgoing edge.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct Edge {
+pub(crate) struct Edge {
to: ItemId,
kind: EdgeKind,
}
impl Edge {
/// Construct a new edge whose referent is `to` and is of the given `kind`.
- pub fn new(to: ItemId, kind: EdgeKind) -> Edge {
+ pub(crate) fn new(to: ItemId, kind: EdgeKind) -> Edge {
Edge { to, kind }
}
}
@@ -33,7 +33,7 @@ impl From<Edge> for ItemId {
/// The kind of edge reference. This is useful when we wish to only consider
/// certain kinds of edges for a particular traversal or analysis.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum EdgeKind {
+pub(crate) enum EdgeKind {
/// A generic, catch-all edge.
Generic,
@@ -182,12 +182,13 @@ pub enum EdgeKind {
///
/// The predicate must return true if the traversal should follow this edge
/// and visit everything that is reachable through it.
-pub type TraversalPredicate = for<'a> fn(&'a BindgenContext, Edge) -> bool;
+pub(crate) type TraversalPredicate =
+ for<'a> fn(&'a BindgenContext, Edge) -> bool;
/// A `TraversalPredicate` implementation that follows all edges, and therefore
/// traversals using this predicate will see the whole IR graph reachable from
/// the traversal's roots.
-pub fn all_edges(_: &BindgenContext, _: Edge) -> bool {
+pub(crate) fn all_edges(_: &BindgenContext, _: Edge) -> bool {
true
}
@@ -196,14 +197,14 @@ pub fn all_edges(_: &BindgenContext, _: Edge) -> bool {
/// will only visit the traversal's roots and their inner types. This is used
/// in no-recursive-allowlist mode, where inner types such as anonymous
/// structs/unions still need to be processed.
-pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool {
+pub(crate) fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool {
edge.kind == EdgeKind::InnerType
}
/// A `TraversalPredicate` implementation that only follows edges to items that
/// are enabled for code generation. This lets us skip considering items for
/// which are not reachable from code generation.
-pub fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool {
+pub(crate) fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool {
let cc = &ctx.options().codegen_config;
match edge.kind {
EdgeKind::Generic => {
@@ -233,7 +234,7 @@ pub fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool {
/// The storage for the set of items that have been seen (although their
/// outgoing edges might not have been fully traversed yet) in an active
/// traversal.
-pub trait TraversalStorage<'ctx> {
+pub(crate) trait TraversalStorage<'ctx> {
/// Construct a new instance of this TraversalStorage, for a new traversal.
fn new(ctx: &'ctx BindgenContext) -> Self;
@@ -259,7 +260,7 @@ impl<'ctx> TraversalStorage<'ctx> for ItemSet {
/// each item. This is useful for providing debug assertions with meaningful
/// diagnostic messages about dangling items.
#[derive(Debug)]
-pub struct Paths<'ctx>(BTreeMap<ItemId, ItemId>, &'ctx BindgenContext);
+pub(crate) struct Paths<'ctx>(BTreeMap<ItemId, ItemId>, &'ctx BindgenContext);
impl<'ctx> TraversalStorage<'ctx> for Paths<'ctx> {
fn new(ctx: &'ctx BindgenContext) -> Self {
@@ -300,7 +301,7 @@ impl<'ctx> TraversalStorage<'ctx> for Paths<'ctx> {
/// Using a FIFO queue with a traversal will yield a breadth-first traversal,
/// while using a LIFO queue will result in a depth-first traversal of the IR
/// graph.
-pub trait TraversalQueue: Default {
+pub(crate) trait TraversalQueue: Default {
/// Add a newly discovered item to the queue.
fn push(&mut self, item: ItemId);
@@ -329,7 +330,7 @@ impl TraversalQueue for VecDeque<ItemId> {
}
/// Something that can receive edges from a `Trace` implementation.
-pub trait Tracer {
+pub(crate) trait Tracer {
/// Note an edge between items. Called from within a `Trace` implementation.
fn visit_kind(&mut self, item: ItemId, kind: EdgeKind);
@@ -351,7 +352,7 @@ where
/// Trace all of the outgoing edges to other items. Implementations should call
/// one of `tracer.visit(edge)` or `tracer.visit_kind(edge, EdgeKind::Whatever)`
/// for each of their outgoing edges.
-pub trait Trace {
+pub(crate) trait Trace {
/// If a particular type needs extra information beyond what it has in
/// `self` and `context` to find its referenced items, its implementation
/// can define this associated type, forcing callers to pass the needed
@@ -371,7 +372,7 @@ pub trait Trace {
/// An graph traversal of the transitive closure of references between items.
///
/// See `BindgenContext::allowlisted_items` for more information.
-pub struct ItemTraversal<'ctx, Storage, Queue>
+pub(crate) struct ItemTraversal<'ctx, Storage, Queue>
where
Storage: TraversalStorage<'ctx>,
Queue: TraversalQueue,
@@ -397,7 +398,7 @@ where
Queue: TraversalQueue,
{
/// Begin a new traversal, starting from the given roots.
- pub fn new<R>(
+ pub(crate) fn new<R>(
ctx: &'ctx BindgenContext,
roots: R,
predicate: TraversalPredicate,
@@ -474,5 +475,5 @@ where
///
/// See `BindgenContext::assert_no_dangling_item_traversal` for more
/// information.
-pub type AssertNoDanglingItemsTraversal<'ctx> =
+pub(crate) type AssertNoDanglingItemsTraversal<'ctx> =
ItemTraversal<'ctx, Paths<'ctx>, VecDeque<ItemId>>;
diff --git a/ir/ty.rs b/ir/ty.rs
index fef340d..8c505aa 100644
--- a/ir/ty.rs
+++ b/ir/ty.rs
@@ -24,7 +24,7 @@ use std::io;
/// (size, alignment and packedness) if known, a `Kind`, which determines which
/// kind of type it is, and whether the type is const.
#[derive(Debug)]
-pub struct Type {
+pub(crate) struct Type {
/// The name of the type, or None if it was an unnamed struct or union.
name: Option<String>,
/// The layout of the type, if known.
@@ -39,21 +39,12 @@ pub struct Type {
/// traits, and so if we have a type containing an array with more than this
/// many items, we won't be able to derive common traits on that type.
///
-pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
+pub(crate) const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
impl Type {
- /// Get the underlying `CompInfo` for this type, or `None` if this is some
- /// other kind of type.
- pub fn as_comp(&self) -> Option<&CompInfo> {
- match self.kind {
- TypeKind::Comp(ref ci) => Some(ci),
- _ => None,
- }
- }
-
/// Get the underlying `CompInfo` for this type as a mutable reference, or
/// `None` if this is some other kind of type.
- pub fn as_comp_mut(&mut self) -> Option<&mut CompInfo> {
+ pub(crate) fn as_comp_mut(&mut self) -> Option<&mut CompInfo> {
match self.kind {
TypeKind::Comp(ref mut ci) => Some(ci),
_ => None,
@@ -61,7 +52,7 @@ impl Type {
}
/// Construct a new `Type`.
- pub fn new(
+ pub(crate) fn new(
name: Option<String>,
layout: Option<Layout>,
kind: TypeKind,
@@ -76,37 +67,37 @@ impl Type {
}
/// Which kind of type is this?
- pub fn kind(&self) -> &TypeKind {
+ pub(crate) fn kind(&self) -> &TypeKind {
&self.kind
}
/// Get a mutable reference to this type's kind.
- pub fn kind_mut(&mut self) -> &mut TypeKind {
+ pub(crate) fn kind_mut(&mut self) -> &mut TypeKind {
&mut self.kind
}
/// Get this type's name.
- pub fn name(&self) -> Option<&str> {
+ pub(crate) fn name(&self) -> Option<&str> {
self.name.as_deref()
}
/// Whether this is a block pointer type.
- pub fn is_block_pointer(&self) -> bool {
+ pub(crate) fn is_block_pointer(&self) -> bool {
matches!(self.kind, TypeKind::BlockPointer(..))
}
/// Is this an integer type, including `bool` or `char`?
- pub fn is_int(&self) -> bool {
+ pub(crate) fn is_int(&self) -> bool {
matches!(self.kind, TypeKind::Int(_))
}
/// Is this a compound type?
- pub fn is_comp(&self) -> bool {
+ pub(crate) fn is_comp(&self) -> bool {
matches!(self.kind, TypeKind::Comp(..))
}
/// Is this a union?
- pub fn is_union(&self) -> bool {
+ pub(crate) fn is_union(&self) -> bool {
match self.kind {
TypeKind::Comp(ref comp) => comp.is_union(),
_ => false,
@@ -114,32 +105,27 @@ impl Type {
}
/// Is this type of kind `TypeKind::TypeParam`?
- pub fn is_type_param(&self) -> bool {
+ pub(crate) fn is_type_param(&self) -> bool {
matches!(self.kind, TypeKind::TypeParam)
}
/// Is this a template instantiation type?
- pub fn is_template_instantiation(&self) -> bool {
+ pub(crate) fn is_template_instantiation(&self) -> bool {
matches!(self.kind, TypeKind::TemplateInstantiation(..))
}
- /// Is this a template alias type?
- pub fn is_template_alias(&self) -> bool {
- matches!(self.kind, TypeKind::TemplateAlias(..))
- }
-
/// Is this a function type?
- pub fn is_function(&self) -> bool {
+ pub(crate) fn is_function(&self) -> bool {
matches!(self.kind, TypeKind::Function(..))
}
/// Is this an enum type?
- pub fn is_enum(&self) -> bool {
+ pub(crate) fn is_enum(&self) -> bool {
matches!(self.kind, TypeKind::Enum(..))
}
/// Is this either a builtin or named type?
- pub fn is_builtin_or_type_param(&self) -> bool {
+ pub(crate) fn is_builtin_or_type_param(&self) -> bool {
matches!(
self.kind,
TypeKind::Void |
@@ -155,29 +141,29 @@ impl Type {
}
/// Creates a new named type, with name `name`.
- pub fn named(name: String) -> Self {
+ pub(crate) fn named(name: String) -> Self {
let name = if name.is_empty() { None } else { Some(name) };
Self::new(name, None, TypeKind::TypeParam, false)
}
/// Is this a floating point type?
- pub fn is_float(&self) -> bool {
+ pub(crate) fn is_float(&self) -> bool {
matches!(self.kind, TypeKind::Float(..))
}
/// Is this a boolean type?
- pub fn is_bool(&self) -> bool {
+ pub(crate) fn is_bool(&self) -> bool {
matches!(self.kind, TypeKind::Int(IntKind::Bool))
}
/// Is this an integer type?
- pub fn is_integer(&self) -> bool {
+ pub(crate) fn is_integer(&self) -> bool {
matches!(self.kind, TypeKind::Int(..))
}
/// Cast this type to an integer kind, or `None` if it is not an integer
/// type.
- pub fn as_integer(&self) -> Option<IntKind> {
+ pub(crate) fn as_integer(&self) -> Option<IntKind> {
match self.kind {
TypeKind::Int(int_kind) => Some(int_kind),
_ => None,
@@ -185,25 +171,20 @@ impl Type {
}
/// Is this a `const` qualified type?
- pub fn is_const(&self) -> bool {
+ pub(crate) fn is_const(&self) -> bool {
self.is_const
}
- /// Is this a reference to another type?
- pub fn is_type_ref(&self) -> bool {
- matches!(
- self.kind,
- TypeKind::ResolvedTypeRef(_) | TypeKind::UnresolvedTypeRef(_, _, _)
- )
- }
-
/// Is this an unresolved reference?
- pub fn is_unresolved_ref(&self) -> bool {
+ pub(crate) fn is_unresolved_ref(&self) -> bool {
matches!(self.kind, TypeKind::UnresolvedTypeRef(_, _, _))
}
/// Is this a incomplete array type?
- pub fn is_incomplete_array(&self, ctx: &BindgenContext) -> Option<ItemId> {
+ pub(crate) fn is_incomplete_array(
+ &self,
+ ctx: &BindgenContext,
+ ) -> Option<ItemId> {
match self.kind {
TypeKind::Array(item, len) => {
if len == 0 {
@@ -220,7 +201,7 @@ impl Type {
}
/// What is the layout of this type?
- pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
+ pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
self.layout.or_else(|| {
match self.kind {
TypeKind::Comp(ref ci) => ci.layout(ctx),
@@ -245,7 +226,7 @@ impl Type {
/// avoid generating invalid code with some cases we can't handle, see:
///
/// tests/headers/381-decltype-alias.hpp
- pub fn is_invalid_type_param(&self) -> bool {
+ pub(crate) fn is_invalid_type_param(&self) -> bool {
match self.kind {
TypeKind::TypeParam => {
let name = self.name().expect("Unnamed named type?");
@@ -266,7 +247,7 @@ impl Type {
}
/// Get this type's santizied name.
- pub fn sanitized_name<'a>(
+ pub(crate) fn sanitized_name<'a>(
&'a self,
ctx: &BindgenContext,
) -> Option<Cow<'a, str>> {
@@ -289,7 +270,7 @@ impl Type {
}
/// See safe_canonical_type.
- pub fn canonical_type<'tr>(
+ pub(crate) fn canonical_type<'tr>(
&'tr self,
ctx: &'tr BindgenContext,
) -> &'tr Type {
@@ -302,7 +283,7 @@ impl Type {
/// For example, for a `typedef`, the canonical type would be the
/// `typedef`ed type, for a template instantiation, would be the template
/// its specializing, and so on. Return None if the type is unresolved.
- pub fn safe_canonical_type<'tr>(
+ pub(crate) fn safe_canonical_type<'tr>(
&'tr self,
ctx: &'tr BindgenContext,
) -> Option<&'tr Type> {
@@ -341,7 +322,7 @@ impl Type {
/// There are some types we don't want to stop at when finding an opaque
/// item, so we can arrive to the proper item that needs to be generated.
- pub fn should_be_traced_unconditionally(&self) -> bool {
+ pub(crate) fn should_be_traced_unconditionally(&self) -> bool {
matches!(
self.kind,
TypeKind::Comp(..) |
@@ -570,7 +551,7 @@ impl TemplateParameters for TypeKind {
/// The kind of float this type represents.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum FloatKind {
+pub(crate) enum FloatKind {
/// A `float`.
Float,
/// A `double`.
@@ -583,7 +564,7 @@ pub enum FloatKind {
/// The different kinds of types that we can parse.
#[derive(Debug)]
-pub enum TypeKind {
+pub(crate) enum TypeKind {
/// The void type.
Void,
@@ -680,7 +661,7 @@ impl Type {
///
/// It's sort of nasty and full of special-casing, but hopefully the
/// comments in every special case justify why they're there.
- pub fn from_clang_ty(
+ pub(crate) fn from_clang_ty(
potential_id: ItemId,
ty: &clang::Type,
location: Cursor,
@@ -730,7 +711,7 @@ impl Type {
// Objective C template type parameter
// FIXME: This is probably wrong, we are attempting to find the
// objc template params, which seem to manifest as a typedef.
- // We are rewriting them as id to suppress multiple conflicting
+ // We are rewriting them as ID to suppress multiple conflicting
// typedefs at root level
if ty_kind == CXType_Typedef {
let is_template_type_param =
diff --git a/ir/var.rs b/ir/var.rs
index 903e1ff..a548ec8 100644
--- a/ir/var.rs
+++ b/ir/var.rs
@@ -11,13 +11,13 @@ use crate::callbacks::{ItemInfo, ItemKind, MacroParsingBehavior};
use crate::clang;
use crate::clang::ClangToken;
use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
-use cexpr;
+
use std::io;
use std::num::Wrapping;
/// The type for a constant variable.
#[derive(Debug)]
-pub enum VarType {
+pub(crate) enum VarType {
/// A boolean.
Bool(bool),
/// An integer.
@@ -32,11 +32,13 @@ pub enum VarType {
/// A `Var` is our intermediate representation of a variable.
#[derive(Debug)]
-pub struct Var {
+pub(crate) struct Var {
/// The name of the variable.
name: String,
/// The mangled name of the variable.
mangled_name: Option<String>,
+ /// The link name of the variable.
+ link_name: Option<String>,
/// The type of the variable.
ty: TypeId,
/// The value of the variable, that needs to be suitable for `ty`.
@@ -47,9 +49,10 @@ pub struct Var {
impl Var {
/// Construct a new `Var`.
- pub fn new(
+ pub(crate) fn new(
name: String,
mangled_name: Option<String>,
+ link_name: Option<String>,
ty: TypeId,
val: Option<VarType>,
is_const: bool,
@@ -58,6 +61,7 @@ impl Var {
Var {
name,
mangled_name,
+ link_name,
ty,
val,
is_const,
@@ -65,29 +69,34 @@ impl Var {
}
/// Is this variable `const` qualified?
- pub fn is_const(&self) -> bool {
+ pub(crate) fn is_const(&self) -> bool {
self.is_const
}
/// The value of this constant variable, if any.
- pub fn val(&self) -> Option<&VarType> {
+ pub(crate) fn val(&self) -> Option<&VarType> {
self.val.as_ref()
}
/// Get this variable's type.
- pub fn ty(&self) -> TypeId {
+ pub(crate) fn ty(&self) -> TypeId {
self.ty
}
/// Get this variable's name.
- pub fn name(&self) -> &str {
+ pub(crate) fn name(&self) -> &str {
&self.name
}
/// Get this variable's mangled name.
- pub fn mangled_name(&self) -> Option<&str> {
+ pub(crate) fn mangled_name(&self) -> Option<&str> {
self.mangled_name.as_deref()
}
+
+ /// Get this variable's link name.
+ pub fn link_name(&self) -> Option<&str> {
+ self.link_name.as_deref()
+ }
}
impl DotAttributes for Var {
@@ -213,7 +222,7 @@ impl ClangSubItemParser for Var {
if previously_defined {
let name = String::from_utf8(id).unwrap();
- warn!("Duplicated macro definition: {}", name);
+ duplicated_macro_diagnostic(&name, cursor.location(), ctx);
return Err(ParseError::Continue);
}
@@ -267,7 +276,7 @@ impl ClangSubItemParser for Var {
let ty = Item::builtin_type(type_kind, true, ctx);
Ok(ParseResult::New(
- Var::new(name, None, ty, Some(val), true),
+ Var::new(name, None, None, ty, Some(val), true),
Some(cursor),
))
}
@@ -291,6 +300,13 @@ impl ClangSubItemParser for Var {
return Err(ParseError::Continue);
}
+ let link_name = ctx.options().last_callback(|callbacks| {
+ callbacks.generated_link_name_override(ItemInfo {
+ name: name.as_str(),
+ kind: ItemKind::Var,
+ })
+ });
+
let ty = cursor.cur_type();
// TODO(emilio): do we have to special-case constant arrays in
@@ -360,7 +376,8 @@ impl ClangSubItemParser for Var {
};
let mangling = cursor_mangling(ctx, &cursor);
- let var = Var::new(name, mangling, ty, value, is_const);
+ let var =
+ Var::new(name, mangling, link_name, ty, value, is_const);
Ok(ParseResult::New(var, Some(cursor)))
}
@@ -423,3 +440,49 @@ fn get_integer_literal_from_cursor(cursor: &clang::Cursor) -> Option<i64> {
});
value
}
+
+fn duplicated_macro_diagnostic(
+ macro_name: &str,
+ _location: crate::clang::SourceLocation,
+ _ctx: &BindgenContext,
+) {
+ warn!("Duplicated macro definition: {}", macro_name);
+
+ #[cfg(feature = "experimental")]
+ // FIXME (pvdrz & amanjeev): This diagnostic message shows way too often to be actually
+ // useful. We have to change the logic where this function is called to be able to emit this
+ // message only when the duplication is an actuall issue.
+ //
+ // If I understood correctly, `bindgen` ignores all `#undef` directives. Meaning that this:
+ // ```c
+ // #define FOO 1
+ // #undef FOO
+ // #define FOO 2
+ // ```
+ //
+ // Will trigger this message even though there's nothing wrong with it.
+ #[allow(clippy::overly_complex_bool_expr)]
+ if false && _ctx.options().emit_diagnostics {
+ use crate::diagnostics::{get_line, Diagnostic, Level, Slice};
+ use std::borrow::Cow;
+
+ let mut slice = Slice::default();
+ let mut source = Cow::from(macro_name);
+
+ let (file, line, col, _) = _location.location();
+ if let Some(filename) = file.name() {
+ if let Ok(Some(code)) = get_line(&filename, line) {
+ source = code.into();
+ }
+ slice.with_location(filename, line, col);
+ }
+
+ slice.with_source(source);
+
+ Diagnostic::default()
+ .with_title("Duplicated macro definition.", Level::Warn)
+ .add_slice(slice)
+ .add_annotation("This macro had a duplicate.", Level::Note)
+ .display();
+ }
+}
diff --git a/lib.rs b/lib.rs
index 1af6f26..482c1a3 100644
--- a/lib.rs
+++ b/lib.rs
@@ -9,6 +9,7 @@
//! additional documentation.
#![deny(missing_docs)]
#![deny(unused_extern_crates)]
+#![deny(clippy::disallowed_methods)]
// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]
@@ -33,82 +34,55 @@ mod log_stubs;
#[macro_use]
mod extra_assertions;
-// A macro to declare an internal module for which we *must* provide
-// documentation for. If we are building with the "testing_only_docs" feature,
-// then the module is declared public, and our `#![deny(missing_docs)]` pragma
-// applies to it. This feature is used in CI, so we won't let anything slip by
-// undocumented. Normal builds, however, will leave the module private, so that
-// we don't expose internals to library consumers.
-macro_rules! doc_mod {
- ($m:ident, $doc_mod_name:ident) => {
- #[cfg(feature = "testing_only_docs")]
- pub mod $doc_mod_name {
- //! Autogenerated documentation module.
- pub use super::$m::*;
- }
- };
-}
+mod codegen;
+mod deps;
+mod options;
+mod time;
-macro_rules! fn_with_regex_arg {
- ($(#[$attrs:meta])* pub fn $($tokens:tt)*) => {
- $(#[$attrs])*
- /// Check the [regular expression arguments] section and the [regex] crate
- /// documentation for further information.
- ///
- /// [regular expression arguments]: ./struct.Builder.html#regular-expression-arguments
- /// [regex]: <https://docs.rs/regex>
- pub fn $($tokens)*
- };
-}
+pub mod callbacks;
mod clang;
-mod codegen;
-mod deps;
+#[cfg(feature = "experimental")]
+mod diagnostics;
mod features;
-pub mod ir;
+mod ir;
mod parse;
mod regex_set;
-mod time;
-
-pub mod callbacks;
-doc_mod!(clang, clang_docs);
-doc_mod!(features, features_docs);
-doc_mod!(ir, ir_docs);
-doc_mod!(parse, parse_docs);
-doc_mod!(regex_set, regex_set_docs);
+pub use codegen::{
+ AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle,
+};
+pub use features::{RustTarget, LATEST_STABLE_RUST, RUST_TARGET_STRINGS};
+pub use ir::annotations::FieldVisibilityKind;
+pub use ir::function::Abi;
+pub use regex_set::RegexSet;
use codegen::CodegenError;
+use features::RustFeatures;
use ir::comment;
-
-pub use crate::codegen::{
- AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle,
-};
-use crate::features::RustFeatures;
-pub use crate::features::{
- RustTarget, LATEST_STABLE_RUST, RUST_TARGET_STRINGS,
-};
-use crate::ir::context::{BindgenContext, ItemId};
-pub use crate::ir::function::Abi;
-use crate::ir::item::Item;
-use crate::parse::ParseError;
-pub use crate::regex_set::RegexSet;
+use ir::context::{BindgenContext, ItemId};
+use ir::item::Item;
+use options::BindgenOptions;
+use parse::ParseError;
use std::borrow::Cow;
+use std::collections::hash_map::Entry;
use std::env;
+use std::ffi::OsStr;
use std::fs::{File, OpenOptions};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::rc::Rc;
+use std::str::FromStr;
// Some convenient typedefs for a fast hash map and hash set.
-type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
-type HashSet<K> = ::rustc_hash::FxHashSet<K>;
-pub(crate) use std::collections::hash_map::Entry;
+type HashMap<K, V> = rustc_hash::FxHashMap<K, V>;
+type HashSet<K> = rustc_hash::FxHashSet<K>;
/// Default prefix for the anon fields.
pub const DEFAULT_ANON_FIELDS_PREFIX: &str = "__bindgen_anon_";
+
const DEFAULT_NON_EXTERN_FNS_SUFFIX: &str = "__extern";
fn file_is_cpp(name_file: &str) -> bool {
@@ -134,6 +108,7 @@ fn args_are_cpp(clang_args: &[String]) -> bool {
}
bitflags! {
+ #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
/// A type used to indicate which kind of items we have to generate.
pub struct CodegenConfig: u32 {
/// Whether to generate functions.
@@ -189,6 +164,52 @@ impl Default for CodegenConfig {
}
}
+/// Formatting tools that can be used to format the bindings
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[non_exhaustive]
+pub enum Formatter {
+ /// Do not format the bindings.
+ None,
+ /// Use `rustfmt` to format the bindings.
+ Rustfmt,
+ #[cfg(feature = "prettyplease")]
+ /// Use `prettyplease` to format the bindings.
+ Prettyplease,
+}
+
+impl Default for Formatter {
+ fn default() -> Self {
+ Self::Rustfmt
+ }
+}
+
+impl FromStr for Formatter {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "none" => Ok(Self::None),
+ "rustfmt" => Ok(Self::Rustfmt),
+ #[cfg(feature = "prettyplease")]
+ "prettyplease" => Ok(Self::Prettyplease),
+ _ => Err(format!("`{}` is not a valid formatter", s)),
+ }
+ }
+}
+
+impl std::fmt::Display for Formatter {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let s = match self {
+ Self::None => "none",
+ Self::Rustfmt => "rustfmt",
+ #[cfg(feature = "prettyplease")]
+ Self::Prettyplease => "prettyplease",
+ };
+
+ s.fmt(f)
+ }
+}
+
/// Configure and generate Rust bindings for a C/C++ header.
///
/// This is the main entry point to the library.
@@ -242,14 +263,27 @@ impl Default for CodegenConfig {
///
/// # Regular expression arguments
///
-/// Some [`Builder`] methods like the `allowlist_*` and `blocklist_*` family of methods allow
-/// regular expressions as arguments. These regular expressions will be parenthesized and wrapped
-/// in `^` and `$`. So if `<regex>` is passed as argument, the regular expression to be stored will
-/// be `^(<regex>)$`.
+/// Some [`Builder`] methods such as the `allowlist_*` and `blocklist_*` methods allow regular
+/// expressions as arguments. These regular expressions will be enclosed in parentheses and
+/// anchored with `^` and `$`. So if the argument passed is `<regex>`, the regular expression to be
+/// stored will be `^(<regex>)$`.
+///
+/// As a consequence, regular expressions passed to `bindgen` will try to match the whole name of
+/// an item instead of a section of it, which means that to match any items with the prefix
+/// `prefix`, the `prefix.*` regular expression must be used.
+///
+/// Certain methods, like [`Builder::allowlist_function`], use regular expressions over function
+/// names. To match C++ methods, prefix the name of the type where they belong followed by an
+/// underscore. So if the type `Foo` has a method `bar`, it can be matched with the `Foo_bar`
+/// regular expression.
+///
+/// Additionally, Objective-C interfaces can be matched by prefixing the regular expression with
+/// `I`. For example, the `IFoo` regular expression matches the `Foo` interface and the `IFoo_foo`
+/// regular expression matches the `foo` method of the `Foo` interface.
///
/// Releases of `bindgen` with a version lesser or equal to `0.62.0` used to accept the wildcard
/// pattern `*` as a valid regular expression. This behavior has been deprecated and the `.*`
-/// pattern must be used instead.
+/// regular expression must be used instead.
#[derive(Debug, Default, Clone)]
pub struct Builder {
options: BindgenOptions,
@@ -260,13 +294,18 @@ pub fn builder() -> Builder {
Default::default()
}
-fn get_extra_clang_args() -> Vec<String> {
+fn get_extra_clang_args(
+ parse_callbacks: &[Rc<dyn callbacks::ParseCallbacks>],
+) -> Vec<String> {
// Add any extra arguments from the environment to the clang command line.
- let extra_clang_args =
- match get_target_dependent_env_var("BINDGEN_EXTRA_CLANG_ARGS") {
- None => return vec![],
- Some(s) => s,
- };
+ let extra_clang_args = match get_target_dependent_env_var(
+ parse_callbacks,
+ "BINDGEN_EXTRA_CLANG_ARGS",
+ ) {
+ None => return vec![],
+ Some(s) => s,
+ };
+
// Try to parse it with shell quoting. If we fail, make it one single big argument.
if let Some(strings) = shlex::split(&extra_clang_args) {
return strings;
@@ -275,1306 +314,12 @@ fn get_extra_clang_args() -> Vec<String> {
}
impl Builder {
- /// Generates the command line flags use for creating `Builder`.
- pub fn command_line_flags(&self) -> Vec<String> {
- let mut output_vector: Vec<String> = Vec::new();
-
- if let Some(header) = self.options.input_headers.last().cloned() {
- // Positional argument 'header'
- output_vector.push(header);
- }
-
- output_vector.push("--rust-target".into());
- output_vector.push(self.options.rust_target.into());
-
- // FIXME(emilio): This is a bit hacky, maybe we should stop re-using the
- // RustFeatures to store the "disable_untagged_union" call, and make it
- // a different flag that we check elsewhere / in generate().
- if !self.options.rust_features.untagged_union &&
- RustFeatures::from(self.options.rust_target).untagged_union
- {
- output_vector.push("--disable-untagged-union".into());
- }
-
- if self.options.default_enum_style != Default::default() {
- output_vector.push("--default-enum-style".into());
- output_vector.push(
- match self.options.default_enum_style {
- codegen::EnumVariation::Rust {
- non_exhaustive: false,
- } => "rust",
- codegen::EnumVariation::Rust {
- non_exhaustive: true,
- } => "rust_non_exhaustive",
- codegen::EnumVariation::NewType {
- is_bitfield: true,
- ..
- } => "bitfield",
- codegen::EnumVariation::NewType {
- is_bitfield: false,
- is_global,
- } => {
- if is_global {
- "newtype_global"
- } else {
- "newtype"
- }
- }
- codegen::EnumVariation::Consts => "consts",
- codegen::EnumVariation::ModuleConsts => "moduleconsts",
- }
- .into(),
- )
- }
-
- if self.options.default_macro_constant_type != Default::default() {
- output_vector.push("--default-macro-constant-type".into());
- output_vector
- .push(self.options.default_macro_constant_type.as_str().into());
- }
-
- if self.options.default_alias_style != Default::default() {
- output_vector.push("--default-alias-style".into());
- output_vector
- .push(self.options.default_alias_style.as_str().into());
- }
-
- if self.options.default_non_copy_union_style != Default::default() {
- output_vector.push("--default-non-copy-union-style".into());
- output_vector.push(
- self.options.default_non_copy_union_style.as_str().into(),
- );
- }
-
- let regex_sets = &[
- (&self.options.bitfield_enums, "--bitfield-enum"),
- (&self.options.newtype_enums, "--newtype-enum"),
- (&self.options.newtype_global_enums, "--newtype-global-enum"),
- (&self.options.rustified_enums, "--rustified-enum"),
- (
- &self.options.rustified_non_exhaustive_enums,
- "--rustified-enum-non-exhaustive",
- ),
- (
- &self.options.constified_enum_modules,
- "--constified-enum-module",
- ),
- (&self.options.constified_enums, "--constified-enum"),
- (&self.options.type_alias, "--type-alias"),
- (&self.options.new_type_alias, "--new-type-alias"),
- (&self.options.new_type_alias_deref, "--new-type-alias-deref"),
- (
- &self.options.bindgen_wrapper_union,
- "--bindgen-wrapper-union",
- ),
- (&self.options.manually_drop_union, "--manually-drop-union"),
- (&self.options.blocklisted_types, "--blocklist-type"),
- (&self.options.blocklisted_functions, "--blocklist-function"),
- (&self.options.blocklisted_items, "--blocklist-item"),
- (&self.options.blocklisted_files, "--blocklist-file"),
- (&self.options.opaque_types, "--opaque-type"),
- (&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"),
- (&self.options.no_default_types, "--no-default"),
- (&self.options.no_hash_types, "--no-hash"),
- (&self.options.must_use_types, "--must-use-type"),
- ];
-
- for (set, flag) in regex_sets {
- for item in set.get_items() {
- output_vector.push((*flag).to_owned());
- output_vector.push(item.to_owned());
- }
- }
-
- for (abi, set) in &self.options.abi_overrides {
- for item in set.get_items() {
- output_vector.push("--override-abi".to_owned());
- output_vector.push(format!("{}={}", item, abi));
- }
- }
-
- if !self.options.layout_tests {
- output_vector.push("--no-layout-tests".into());
- }
-
- if self.options.impl_debug {
- output_vector.push("--impl-debug".into());
- }
-
- if self.options.impl_partialeq {
- output_vector.push("--impl-partialeq".into());
- }
-
- if !self.options.derive_copy {
- output_vector.push("--no-derive-copy".into());
- }
-
- if !self.options.derive_debug {
- output_vector.push("--no-derive-debug".into());
- }
-
- if !self.options.derive_default {
- output_vector.push("--no-derive-default".into());
- } else {
- output_vector.push("--with-derive-default".into());
- }
-
- if self.options.derive_hash {
- output_vector.push("--with-derive-hash".into());
- }
-
- if self.options.derive_partialord {
- output_vector.push("--with-derive-partialord".into());
- }
-
- if self.options.derive_ord {
- output_vector.push("--with-derive-ord".into());
- }
-
- if self.options.derive_partialeq {
- output_vector.push("--with-derive-partialeq".into());
- }
-
- if self.options.derive_eq {
- output_vector.push("--with-derive-eq".into());
- }
-
- if self.options.time_phases {
- output_vector.push("--time-phases".into());
- }
-
- if !self.options.generate_comments {
- output_vector.push("--no-doc-comments".into());
- }
-
- if !self.options.allowlist_recursively {
- output_vector.push("--no-recursive-allowlist".into());
- }
-
- if self.options.objc_extern_crate {
- output_vector.push("--objc-extern-crate".into());
- }
-
- if self.options.generate_block {
- output_vector.push("--generate-block".into());
- }
-
- if self.options.block_extern_crate {
- output_vector.push("--block-extern-crate".into());
- }
-
- if self.options.builtins {
- output_vector.push("--builtins".into());
- }
-
- if let Some(ref prefix) = self.options.ctypes_prefix {
- output_vector.push("--ctypes-prefix".into());
- output_vector.push(prefix.clone());
- }
-
- if self.options.anon_fields_prefix != DEFAULT_ANON_FIELDS_PREFIX {
- output_vector.push("--anon-fields-prefix".into());
- output_vector.push(self.options.anon_fields_prefix.clone());
- }
-
- if self.options.emit_ast {
- output_vector.push("--emit-clang-ast".into());
- }
-
- if self.options.emit_ir {
- output_vector.push("--emit-ir".into());
- }
- if let Some(ref graph) = self.options.emit_ir_graphviz {
- output_vector.push("--emit-ir-graphviz".into());
- output_vector.push(graph.clone())
- }
- if self.options.enable_cxx_namespaces {
- output_vector.push("--enable-cxx-namespaces".into());
- }
- if self.options.enable_function_attribute_detection {
- output_vector.push("--enable-function-attribute-detection".into());
- }
- if self.options.disable_name_namespacing {
- output_vector.push("--disable-name-namespacing".into());
- }
- if self.options.disable_nested_struct_naming {
- output_vector.push("--disable-nested-struct-naming".into());
- }
-
- if self.options.disable_header_comment {
- output_vector.push("--disable-header-comment".into());
- }
-
- if !self.options.codegen_config.functions() {
- output_vector.push("--ignore-functions".into());
- }
-
- output_vector.push("--generate".into());
-
- //Temporary placeholder for below 4 options
- let mut options: Vec<String> = Vec::new();
- if self.options.codegen_config.functions() {
- options.push("functions".into());
- }
- if self.options.codegen_config.types() {
- options.push("types".into());
- }
- if self.options.codegen_config.vars() {
- options.push("vars".into());
- }
- if self.options.codegen_config.methods() {
- options.push("methods".into());
- }
- if self.options.codegen_config.constructors() {
- options.push("constructors".into());
- }
- if self.options.codegen_config.destructors() {
- options.push("destructors".into());
- }
-
- output_vector.push(options.join(","));
-
- if !self.options.codegen_config.methods() {
- output_vector.push("--ignore-methods".into());
- }
-
- if !self.options.convert_floats {
- output_vector.push("--no-convert-floats".into());
- }
-
- if !self.options.prepend_enum_name {
- output_vector.push("--no-prepend-enum-name".into());
- }
-
- if self.options.fit_macro_constants {
- output_vector.push("--fit-macro-constant-types".into());
- }
-
- if self.options.array_pointers_in_arguments {
- output_vector.push("--use-array-pointers-in-arguments".into());
- }
-
- if let Some(ref wasm_import_module_name) =
- self.options.wasm_import_module_name
- {
- output_vector.push("--wasm-import-module-name".into());
- output_vector.push(wasm_import_module_name.clone());
- }
-
- for line in &self.options.raw_lines {
- output_vector.push("--raw-line".into());
- output_vector.push(line.clone());
- }
-
- for (module, lines) in &self.options.module_lines {
- for line in lines.iter() {
- output_vector.push("--module-raw-line".into());
- output_vector.push(module.clone());
- output_vector.push(line.clone());
- }
- }
-
- if self.options.use_core {
- output_vector.push("--use-core".into());
- }
-
- if self.options.conservative_inline_namespaces {
- output_vector.push("--conservative-inline-namespaces".into());
- }
-
- if self.options.generate_inline_functions {
- output_vector.push("--generate-inline-functions".into());
- }
-
- if !self.options.record_matches {
- output_vector.push("--no-record-matches".into());
- }
-
- if !self.options.size_t_is_usize {
- output_vector.push("--no-size_t-is-usize".into());
- }
-
- if !self.options.rustfmt_bindings {
- output_vector.push("--no-rustfmt-bindings".into());
- }
-
- if let Some(path) = self
- .options
- .rustfmt_configuration_file
- .as_ref()
- .and_then(|f| f.to_str())
- {
- output_vector.push("--rustfmt-configuration-file".into());
- output_vector.push(path.into());
- }
-
- if let Some(ref name) = self.options.dynamic_library_name {
- output_vector.push("--dynamic-loading".into());
- output_vector.push(name.clone());
- }
-
- if self.options.dynamic_link_require_all {
- output_vector.push("--dynamic-link-require-all".into());
- }
-
- if self.options.respect_cxx_access_specs {
- output_vector.push("--respect-cxx-access-specs".into());
- }
-
- if self.options.translate_enum_integer_types {
- output_vector.push("--translate-enum-integer-types".into());
- }
-
- if self.options.c_naming {
- output_vector.push("--c-naming".into());
- }
-
- if self.options.force_explicit_padding {
- output_vector.push("--explicit-padding".into());
- }
-
- if self.options.vtable_generation {
- output_vector.push("--vtable-generation".into());
- }
-
- if self.options.sort_semantically {
- output_vector.push("--sort-semantically".into());
- }
-
- if self.options.merge_extern_blocks {
- output_vector.push("--merge-extern-blocks".into());
- }
-
- if self.options.wrap_unsafe_ops {
- output_vector.push("--wrap-unsafe-ops".into());
- }
-
- #[cfg(feature = "cli")]
- for callbacks in &self.options.parse_callbacks {
- output_vector.extend(callbacks.cli_args());
- }
- if self.options.wrap_static_fns {
- output_vector.push("--wrap-static-fns".into())
- }
-
- if let Some(ref path) = self.options.wrap_static_fns_path {
- output_vector.push("--wrap-static-fns-path".into());
- output_vector.push(path.display().to_string());
- }
-
- if let Some(ref suffix) = self.options.wrap_static_fns_suffix {
- output_vector.push("--wrap-static-fns-suffix".into());
- output_vector.push(suffix.clone());
- }
-
- if cfg!(feature = "experimental") {
- output_vector.push("--experimental".into());
- }
-
- // Add clang arguments
-
- output_vector.push("--".into());
-
- if !self.options.clang_args.is_empty() {
- output_vector.extend(self.options.clang_args.iter().cloned());
- }
-
- // To pass more than one header, we need to pass all but the last
- // header via the `-include` clang arg
- for header in &self.options.input_headers
- [..self.options.input_headers.len().saturating_sub(1)]
- {
- output_vector.push("-include".to_string());
- output_vector.push(header.clone());
- }
-
- output_vector
- }
-
- /// Add an input C/C++ header to generate bindings for.
- ///
- /// This can be used to generate bindings to a single header:
- ///
- /// ```ignore
- /// let bindings = bindgen::Builder::default()
- /// .header("input.h")
- /// .generate()
- /// .unwrap();
- /// ```
- ///
- /// Or you can invoke it multiple times to generate bindings to multiple
- /// headers:
- ///
- /// ```ignore
- /// let bindings = bindgen::Builder::default()
- /// .header("first.h")
- /// .header("second.h")
- /// .header("third.h")
- /// .generate()
- /// .unwrap();
- /// ```
- pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
- self.options.input_headers.push(header.into());
- self
- }
-
- /// Add a depfile output which will be written alongside the generated bindings.
- pub fn depfile<H: Into<String>, D: Into<PathBuf>>(
- mut self,
- output_module: H,
- depfile: D,
- ) -> Builder {
- self.options.depfile = Some(deps::DepfileSpec {
- output_module: output_module.into(),
- depfile_path: depfile.into(),
- });
- 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 {
- // Apparently clang relies on having virtual FS correspondent to
- // the real one, so we need absolute paths here
- let absolute_path = env::current_dir()
- .expect("Cannot retrieve current directory")
- .join(name)
- .to_str()
- .expect("Cannot convert current directory name to string")
- .to_owned();
- self.options
- .input_header_contents
- .push((absolute_path, contents.into()));
- self
- }
-
- /// Specify the rust target
- ///
- /// The default is the latest stable Rust version
- pub fn rust_target(mut self, rust_target: RustTarget) -> Self {
- #[allow(deprecated)]
- if rust_target <= RustTarget::Stable_1_30 {
- warn!(
- "The {} rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues",
- String::from(rust_target)
- );
- }
- self.options.set_rust_target(rust_target);
- self
- }
-
- /// Disable support for native Rust unions, if supported.
- pub fn disable_untagged_union(mut self) -> Self {
- self.options.rust_features.untagged_union = false;
- self
- }
-
- /// Disable insertion of bindgen's version identifier into generated
- /// bindings.
- pub fn disable_header_comment(mut self) -> Self {
- self.options.disable_header_comment = true;
- self
- }
-
- /// Set the output graphviz file.
- pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
- let path = path.into();
- self.options.emit_ir_graphviz = Some(path);
- self
- }
-
- /// Whether the generated bindings should contain documentation comments
- /// (docstrings) or not. This is set to true by default.
- ///
- /// Note that clang by default excludes comments from system headers, pass
- /// `-fretain-comments-from-system-headers` as
- /// [`clang_arg`][Builder::clang_arg] to include them. It can also be told
- /// to process all comments (not just documentation ones) using the
- /// `-fparse-all-comments` flag. See [slides on clang comment parsing](
- /// https://llvm.org/devmtg/2012-11/Gribenko_CommentParsing.pdf) for
- /// background and examples.
- pub fn generate_comments(mut self, doit: bool) -> Self {
- self.options.generate_comments = doit;
- self
- }
-
- /// Whether to allowlist recursively or not. Defaults to true.
- ///
- /// Given that we have explicitly allowlisted the "initiate_dance_party"
- /// function in this C header:
- ///
- /// ```c
- /// typedef struct MoonBoots {
- /// int bouncy_level;
- /// } MoonBoots;
- ///
- /// void initiate_dance_party(MoonBoots* boots);
- /// ```
- ///
- /// We would normally generate bindings to both the `initiate_dance_party`
- /// function and the `MoonBoots` struct that it transitively references. By
- /// configuring with `allowlist_recursively(false)`, `bindgen` will not emit
- /// bindings for anything except the explicitly allowlisted items, and there
- /// would be no emitted struct definition for `MoonBoots`. However, the
- /// `initiate_dance_party` function would still reference `MoonBoots`!
- ///
- /// **Disabling this feature will almost certainly cause `bindgen` to emit
- /// bindings that will not compile!** If you disable this feature, then it
- /// is *your* responsibility to provide definitions for every type that is
- /// referenced from an explicitly allowlisted item. One way to provide the
- /// definitions is by using the [`Builder::raw_line`](#method.raw_line)
- /// method, another would be to define them in Rust and then `include!(...)`
- /// the bindings immediately afterwards.
- pub fn allowlist_recursively(mut self, doit: bool) -> Self {
- self.options.allowlist_recursively = doit;
- self
- }
-
- /// Generate `#[macro_use] extern crate objc;` instead of `use objc;`
- /// in the prologue of the files generated from objective-c files
- pub fn objc_extern_crate(mut self, doit: bool) -> Self {
- self.options.objc_extern_crate = doit;
- self
- }
-
- /// Generate proper block signatures instead of void pointers.
- pub fn generate_block(mut self, doit: bool) -> Self {
- self.options.generate_block = doit;
- self
- }
-
- /// Generate `#[macro_use] extern crate block;` instead of `use block;`
- /// in the prologue of the files generated from apple block files
- pub fn block_extern_crate(mut self, doit: bool) -> Self {
- self.options.block_extern_crate = doit;
- self
- }
-
- /// Whether to use the clang-provided name mangling. This is true by default
- /// and probably needed for C++ features.
- ///
- /// However, some old libclang versions seem to return incorrect results in
- /// some cases for non-mangled functions, see [1], so we allow disabling it.
- ///
- /// [1]: https://github.com/rust-lang/rust-bindgen/issues/528
- pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
- self.options.enable_mangling = doit;
- self
- }
-
- fn_with_regex_arg! {
- /// Hide the given type from the generated bindings. Regular expressions are
- /// supported.
- ///
- /// To blocklist types prefixed with "mylib" use `"mylib_.*"`.
- pub fn blocklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.blocklisted_types.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Hide the given function from the generated bindings. Regular expressions
- /// are supported.
- ///
- /// Methods can be blocklisted by prefixing the name of the type implementing
- /// them followed by an underscore. So if `Foo` has a method `bar`, it can
- /// be blocklisted as `Foo_bar`.
- ///
- /// To blocklist functions prefixed with "mylib" use `"mylib_.*"`.
- pub fn blocklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.blocklisted_functions.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Hide the given item from the generated bindings, regardless of
- /// whether it's a type, function, module, etc. Regular
- /// expressions are supported.
- ///
- /// To blocklist items prefixed with "mylib" use `"mylib_.*"`.
- pub fn blocklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.blocklisted_items.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Hide any contents of the given file from the generated bindings,
- /// regardless of whether it's a type, function, module etc.
- pub fn blocklist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.blocklisted_files.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Treat the given type as opaque in the generated bindings. Regular
- /// expressions are supported.
- ///
- /// To change types prefixed with "mylib" into opaque, use `"mylib_.*"`.
- pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.opaque_types.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Allowlist the given type so that it (and all types that it transitively
- /// refers to) appears in the generated bindings. Regular expressions are
- /// supported.
- ///
- /// To allowlist types prefixed with "mylib" use `"mylib_.*"`.
- pub fn allowlist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.allowlisted_types.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Allowlist the given function so that it (and all types that it
- /// transitively refers to) appears in the generated bindings. Regular
- /// expressions are supported.
- ///
- /// Methods can be allowlisted by prefixing the name of the type
- /// implementing them followed by an underscore. So if `Foo` has a method
- /// `bar`, it can be allowlisted as `Foo_bar`.
- ///
- /// To allowlist functions prefixed with "mylib" use `"mylib_.*"`.
- pub fn allowlist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.allowlisted_functions.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Allowlist the given variable so that it (and all types that it
- /// transitively refers to) appears in the generated bindings. Regular
- /// expressions are supported.
- ///
- /// To allowlist variables prefixed with "mylib" use `"mylib_.*"`.
- pub fn allowlist_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.allowlisted_vars.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// 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
- }
- }
-
- /// Set the default style of code to generate for enums
- pub fn default_enum_style(
- mut self,
- arg: codegen::EnumVariation,
- ) -> Builder {
- self.options.default_enum_style = arg;
- self
- }
-
- fn_with_regex_arg! {
- /// Mark the given enum (or set of enums, if using a pattern) as being
- /// bitfield-like. Regular expressions are supported.
- ///
- /// This makes bindgen generate a type that isn't a rust `enum`. Regular
- /// expressions are supported.
- ///
- /// This is similar to the newtype enum style, but with the bitwise
- /// operators implemented.
- pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.bitfield_enums.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given enum (or set of enums, if using a pattern) as a newtype.
- /// Regular expressions are supported.
- ///
- /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
- /// expressions are supported.
- pub fn newtype_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.newtype_enums.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given enum (or set of enums, if using a pattern) as a newtype
- /// whose variants are exposed as global constants.
- ///
- /// Regular expressions are supported.
- ///
- /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
- /// expressions are supported.
- pub fn newtype_global_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.newtype_global_enums.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given enum (or set of enums, if using a pattern) as a Rust
- /// enum.
- ///
- /// This makes bindgen generate enums instead of constants. Regular
- /// expressions are supported.
- ///
- /// **Use this with caution**, creating this in unsafe code
- /// (including FFI) with an invalid value will invoke undefined behaviour.
- /// You may want to use the newtype enum style instead.
- pub fn rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.rustified_enums.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given enum (or set of enums, if using a pattern) as a Rust
- /// enum with the `#[non_exhaustive]` attribute.
- ///
- /// This makes bindgen generate enums instead of constants. Regular
- /// expressions are supported.
- ///
- /// **Use this with caution**, creating this in unsafe code
- /// (including FFI) with an invalid value will invoke undefined behaviour.
- /// You may want to use the newtype enum style instead.
- pub fn rustified_non_exhaustive_enum<T: AsRef<str>>(
- mut self,
- arg: T,
- ) -> Builder {
- self.options.rustified_non_exhaustive_enums.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given enum (or set of enums, if using a pattern) as a set of
- /// constants that are not to be put into a module.
- pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.constified_enums.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given enum (or set of enums, if using a pattern) as a set of
- /// constants that should be put into a module.
- ///
- /// This makes bindgen generate modules containing constants instead of
- /// just constants. Regular expressions are supported.
- pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.constified_enum_modules.insert(arg);
- self
- }
- }
-
- /// Set the default type for macro constants
- pub fn default_macro_constant_type(
- mut self,
- arg: codegen::MacroTypeVariation,
- ) -> Builder {
- self.options.default_macro_constant_type = arg;
- self
- }
-
- /// Set the default style of code to generate for typedefs
- pub fn default_alias_style(
- mut self,
- arg: codegen::AliasVariation,
- ) -> Builder {
- self.options.default_alias_style = arg;
- self
- }
-
- fn_with_regex_arg! {
- /// Mark the given typedef alias (or set of aliases, if using a pattern) to
- /// use regular Rust type aliasing.
- ///
- /// This is the default behavior and should be used if `default_alias_style`
- /// was set to NewType or NewTypeDeref and you want to override it for a
- /// set of typedefs.
- pub fn type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.type_alias.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given typedef alias (or set of aliases, if using a pattern) to
- /// be generated as a new type by having the aliased type be wrapped in a
- /// #[repr(transparent)] struct.
- ///
- /// Used to enforce stricter type checking.
- pub fn new_type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.new_type_alias.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given typedef alias (or set of aliases, if using a pattern) to
- /// be generated as a new type by having the aliased type be wrapped in a
- /// #[repr(transparent)] struct and also have an automatically generated
- /// impl's of `Deref` and `DerefMut` to their aliased type.
- pub fn new_type_alias_deref<T: AsRef<str>>(mut self, arg: T) -> Builder {
- self.options.new_type_alias_deref.insert(arg);
- self
- }
- }
-
- /// Set the default style of code to generate for unions with a non-Copy member.
- pub fn default_non_copy_union_style(
- mut self,
- arg: codegen::NonCopyUnionStyle,
- ) -> Self {
- self.options.default_non_copy_union_style = arg;
- self
- }
-
- fn_with_regex_arg! {
- /// Mark the given union (or set of union, if using a pattern) to use
- /// a bindgen-generated wrapper for its members if at least one is non-Copy.
- pub fn bindgen_wrapper_union<T: AsRef<str>>(mut self, arg: T) -> Self {
- self.options.bindgen_wrapper_union.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Mark the given union (or set of union, if using a pattern) to use
- /// [`::core::mem::ManuallyDrop`] for its members if at least one is non-Copy.
- ///
- /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your
- /// MSRV is lower.
- pub fn manually_drop_union<T: AsRef<str>>(mut self, arg: T) -> Self {
- self.options.manually_drop_union.insert(arg);
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Add a string to prepend to the generated bindings. The string is passed
- /// through without any modification.
- pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
- self.options.raw_lines.push(arg.into());
- self
- }
- }
-
- /// Add a given line to the beginning of module `mod`.
- pub fn module_raw_line<T, U>(mut self, mod_: T, line: U) -> Self
- where
- T: Into<String>,
- U: Into<String>,
- {
- self.options
- .module_lines
- .entry(mod_.into())
- .or_insert_with(Vec::new)
- .push(line.into());
- self
- }
-
- /// Add a given set of lines to the beginning of module `mod`.
- pub fn module_raw_lines<T, I>(mut self, mod_: T, lines: I) -> Self
- where
- T: Into<String>,
- I: IntoIterator,
- I::Item: Into<String>,
- {
- self.options
- .module_lines
- .entry(mod_.into())
- .or_insert_with(Vec::new)
- .extend(lines.into_iter().map(Into::into));
- self
- }
-
- /// Add an argument to be passed straight through to clang.
- pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.clang_args.push(arg.into());
- self
- }
-
- /// Add arguments to be passed straight through to clang.
- pub fn clang_args<I>(mut self, iter: I) -> Builder
- where
- I: IntoIterator,
- I::Item: AsRef<str>,
- {
- for arg in iter {
- self = self.clang_arg(arg.as_ref())
- }
- self
- }
-
- /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
- /// in the generated Rust.
- pub fn emit_builtins(mut self) -> Builder {
- self.options.builtins = true;
- self
- }
-
- /// Avoid converting floats to `f32`/`f64` by default.
- pub fn no_convert_floats(mut self) -> Self {
- self.options.convert_floats = false;
- self
- }
-
- /// Set whether layout tests should be generated.
- pub fn layout_tests(mut self, doit: bool) -> Self {
- self.options.layout_tests = doit;
- self
- }
-
- /// Set whether `Debug` should be implemented, if it can not be derived automatically.
- pub fn impl_debug(mut self, doit: bool) -> Self {
- self.options.impl_debug = doit;
- self
- }
-
- /// Set whether `PartialEq` should be implemented, if it can not be derived automatically.
- pub fn impl_partialeq(mut self, doit: bool) -> Self {
- self.options.impl_partialeq = doit;
- self
- }
-
- /// Set whether `Copy` should be derived by default.
- pub fn derive_copy(mut self, doit: bool) -> Self {
- self.options.derive_copy = doit;
- self
- }
-
- /// Set whether `Debug` should be derived by default.
- pub fn derive_debug(mut self, doit: bool) -> Self {
- self.options.derive_debug = doit;
- self
- }
-
- /// Set whether `Default` should be derived by default.
- pub fn derive_default(mut self, doit: bool) -> Self {
- self.options.derive_default = doit;
- self
- }
-
- /// Set whether `Hash` should be derived by default.
- pub fn derive_hash(mut self, doit: bool) -> Self {
- self.options.derive_hash = doit;
- self
- }
-
- /// Set whether `PartialOrd` should be derived by default.
- /// If we don't compute partialord, we also cannot compute
- /// ord. Set the derive_ord to `false` when doit is `false`.
- pub fn derive_partialord(mut self, doit: bool) -> Self {
- self.options.derive_partialord = doit;
- if !doit {
- self.options.derive_ord = false;
- }
- self
- }
-
- /// Set whether `Ord` should be derived by default.
- /// We can't compute `Ord` without computing `PartialOrd`,
- /// so we set the same option to derive_partialord.
- pub fn derive_ord(mut self, doit: bool) -> Self {
- self.options.derive_ord = doit;
- self.options.derive_partialord = doit;
- self
- }
-
- /// Set whether `PartialEq` should be derived by default.
- ///
- /// If we don't derive `PartialEq`, we also cannot derive `Eq`, so deriving
- /// `Eq` is also disabled when `doit` is `false`.
- pub fn derive_partialeq(mut self, doit: bool) -> Self {
- self.options.derive_partialeq = doit;
- if !doit {
- self.options.derive_eq = false;
- }
- self
- }
-
- /// Set whether `Eq` should be derived by default.
- ///
- /// We can't derive `Eq` without also deriving `PartialEq`, so we also
- /// enable deriving `PartialEq` when `doit` is `true`.
- pub fn derive_eq(mut self, doit: bool) -> Self {
- self.options.derive_eq = doit;
- if doit {
- self.options.derive_partialeq = doit;
- }
- self
- }
-
- /// Set whether or not to time bindgen phases, and print information to
- /// stderr.
- pub fn time_phases(mut self, doit: bool) -> Self {
- self.options.time_phases = doit;
- self
- }
-
- /// Emit Clang AST.
- pub fn emit_clang_ast(mut self) -> Builder {
- self.options.emit_ast = true;
- self
- }
-
- /// Emit IR.
- pub fn emit_ir(mut self) -> Builder {
- self.options.emit_ir = true;
- self
- }
-
- /// Enable C++ namespaces.
- pub fn enable_cxx_namespaces(mut self) -> Builder {
- self.options.enable_cxx_namespaces = true;
- self
- }
-
- /// Enable detecting must_use attributes on C functions.
- ///
- /// This is quite slow in some cases (see #1465), so it's disabled by
- /// default.
- ///
- /// Note that for this to do something meaningful for now at least, the rust
- /// target version has to have support for `#[must_use]`.
- pub fn enable_function_attribute_detection(mut self) -> Self {
- self.options.enable_function_attribute_detection = true;
- self
- }
-
- /// Disable name auto-namespacing.
- ///
- /// By default, bindgen mangles names like `foo::bar::Baz` to look like
- /// `foo_bar_Baz` instead of just `Baz`.
- ///
- /// This method disables that behavior.
- ///
- /// Note that this intentionally does not change the names used for
- /// allowlisting and blocklisting, which should still be mangled with the
- /// namespaces.
- ///
- /// Note, also, that this option may cause bindgen to generate duplicate
- /// names.
- pub fn disable_name_namespacing(mut self) -> Builder {
- self.options.disable_name_namespacing = true;
- self
- }
-
- /// Disable nested struct naming.
- ///
- /// The following structs have different names for C and C++. In case of C
- /// they are visible as `foo` and `bar`. In case of C++ they are visible as
- /// `foo` and `foo::bar`.
- ///
- /// ```c
- /// struct foo {
- /// struct bar {
- /// } b;
- /// };
- /// ```
- ///
- /// Bindgen wants to avoid duplicate names by default so it follows C++ naming
- /// and it generates `foo`/`foo_bar` instead of just `foo`/`bar`.
- ///
- /// This method disables this behavior and it is indented to be used only
- /// for headers that were written for C.
- pub fn disable_nested_struct_naming(mut self) -> Builder {
- self.options.disable_nested_struct_naming = true;
- self
- }
-
- /// Treat inline namespaces conservatively.
- ///
- /// This is tricky, because in C++ is technically legal to override an item
- /// defined in an inline namespace:
- ///
- /// ```cpp
- /// inline namespace foo {
- /// using Bar = int;
- /// }
- /// using Bar = long;
- /// ```
- ///
- /// Even though referencing `Bar` is a compiler error.
- ///
- /// We want to support this (arguably esoteric) use case, but we don't want
- /// to make the rest of bindgen users pay an usability penalty for that.
- ///
- /// To support this, we need to keep all the inline namespaces around, but
- /// then bindgen usage is a bit more difficult, because you cannot
- /// reference, e.g., `std::string` (you'd need to use the proper inline
- /// namespace).
- ///
- /// We could complicate a lot of the logic to detect name collisions, and if
- /// not detected generate a `pub use inline_ns::*` or something like that.
- ///
- /// That's probably something we can do if we see this option is needed in a
- /// lot of cases, to improve it's usability, but my guess is that this is
- /// not going to be too useful.
- pub fn conservative_inline_namespaces(mut self) -> Builder {
- self.options.conservative_inline_namespaces = true;
- 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.remove(CodegenConfig::FUNCTIONS);
- self
- }
-
- /// Ignore methods.
- pub fn ignore_methods(mut self) -> Builder {
- self.options.codegen_config.remove(CodegenConfig::METHODS);
- self
- }
-
- /// Use core instead of libstd in the generated bindings.
- pub fn use_core(mut self) -> Builder {
- self.options.use_core = true;
- self
- }
-
- /// Use the given prefix for the raw types instead of `::std::os::raw`.
- pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
- self.options.ctypes_prefix = Some(prefix.into());
- self
- }
-
- /// Use the given prefix for the anon fields.
- pub fn anon_fields_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
- self.options.anon_fields_prefix = prefix.into();
- self
- }
-
- /// Allows configuring types in different situations, see the
- /// [`ParseCallbacks`](./callbacks/trait.ParseCallbacks.html) documentation.
- pub fn parse_callbacks(
- mut self,
- cb: Box<dyn callbacks::ParseCallbacks>,
- ) -> Self {
- self.options.parse_callbacks.push(Rc::from(cb));
- self
- }
-
- /// Choose what to generate using a
- /// [`CodegenConfig`](./struct.CodegenConfig.html).
- pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self {
- self.options.codegen_config = config;
- self
- }
-
- /// Whether to detect include paths using clang_sys.
- pub fn detect_include_paths(mut self, doit: bool) -> Self {
- self.options.detect_include_paths = doit;
- self
- }
-
- /// Whether to try to fit macro constants to types smaller than u32/i32
- pub fn fit_macro_constants(mut self, doit: bool) -> Self {
- self.options.fit_macro_constants = doit;
- self
- }
-
- /// Prepend the enum name to constant or newtype variants.
- pub fn prepend_enum_name(mut self, doit: bool) -> Self {
- self.options.prepend_enum_name = doit;
- self
- }
-
- /// Set whether `size_t` should be translated to `usize` automatically.
- pub fn size_t_is_usize(mut self, is: bool) -> Self {
- self.options.size_t_is_usize = is;
- self
- }
-
- /// Set whether rustfmt should format the generated bindings.
- pub fn rustfmt_bindings(mut self, doit: bool) -> Self {
- self.options.rustfmt_bindings = doit;
- self
- }
-
- /// Set whether we should record matched items in our regex sets.
- pub fn record_matches(mut self, doit: bool) -> Self {
- self.options.record_matches = doit;
- self
- }
-
- /// Set the absolute path to the rustfmt configuration file, if None, the standard rustfmt
- /// options are used.
- pub fn rustfmt_configuration_file(mut self, path: Option<PathBuf>) -> Self {
- self = self.rustfmt_bindings(true);
- self.options.rustfmt_configuration_file = path;
- self
- }
-
- /// Sets an explicit path to rustfmt, to be used when rustfmt is enabled.
- pub fn with_rustfmt<P: Into<PathBuf>>(mut self, path: P) -> Self {
- self.options.rustfmt_path = Some(path.into());
- self
- }
-
- /// If true, always emit explicit padding fields.
- ///
- /// If a struct needs to be serialized in its native format (padding bytes
- /// and all), for example writing it to a file or sending it on the network,
- /// then this should be enabled, as anything reading the padding bytes of
- /// a struct may lead to Undefined Behavior.
- pub fn explicit_padding(mut self, doit: bool) -> Self {
- self.options.force_explicit_padding = doit;
- self
- }
-
- /// If true, enables experimental support to generate vtable functions.
- ///
- /// Should mostly work, though some edge cases are likely to be broken.
- pub fn vtable_generation(mut self, doit: bool) -> Self {
- self.options.vtable_generation = doit;
- self
- }
-
- /// If true, enables the sorting of the output in a predefined manner.
- ///
- /// TODO: Perhaps move the sorting order out into a config
- pub fn sort_semantically(mut self, doit: bool) -> Self {
- self.options.sort_semantically = doit;
- self
- }
-
- /// If true, merges extern blocks.
- pub fn merge_extern_blocks(mut self, doit: bool) -> Self {
- self.options.merge_extern_blocks = doit;
- self
- }
-
/// Generate the Rust bindings using the options built up thus far.
pub fn generate(mut self) -> Result<Bindings, BindgenError> {
// Add any extra arguments from the environment to the clang command line.
- self.options.clang_args.extend(get_extra_clang_args());
+ self.options
+ .clang_args
+ .extend(get_extra_clang_args(&self.options.parse_callbacks));
// Transform input headers to arguments on the clang command line.
self.options.clang_args.extend(
@@ -1657,7 +402,7 @@ impl Builder {
cmd.arg(a);
}
- for a in get_extra_clang_args() {
+ for a in get_extra_clang_args(&self.options.parse_callbacks) {
cmd.arg(a);
}
@@ -1680,510 +425,13 @@ impl Builder {
))
}
}
-
- fn_with_regex_arg! {
- /// Don't derive `PartialEq` for a given type. Regular
- /// expressions are supported.
- pub fn no_partialeq<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.no_partialeq_types.insert(arg.into());
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Don't derive `Copy` for a given type. Regular
- /// expressions are supported.
- pub fn no_copy<T: Into<String>>(mut self, arg: T) -> Self {
- self.options.no_copy_types.insert(arg.into());
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Don't derive `Debug` for a given type. Regular
- /// expressions are supported.
- pub fn no_debug<T: Into<String>>(mut self, arg: T) -> Self {
- self.options.no_debug_types.insert(arg.into());
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Don't derive/impl `Default` for a given type. Regular
- /// expressions are supported.
- pub fn no_default<T: Into<String>>(mut self, arg: T) -> Self {
- self.options.no_default_types.insert(arg.into());
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Don't derive `Hash` for a given type. Regular
- /// expressions are supported.
- pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.no_hash_types.insert(arg.into());
- self
- }
- }
-
- fn_with_regex_arg! {
- /// Add `#[must_use]` for the given type. Regular
- /// expressions are supported.
- pub fn must_use_type<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.must_use_types.insert(arg.into());
- self
- }
- }
-
- /// Set whether `arr[size]` should be treated as `*mut T` or `*mut [T; size]` (same for mut)
- pub fn array_pointers_in_arguments(mut self, doit: bool) -> Self {
- self.options.array_pointers_in_arguments = doit;
- self
- }
-
- /// Set the wasm import module name
- pub fn wasm_import_module_name<T: Into<String>>(
- mut self,
- import_name: T,
- ) -> Self {
- self.options.wasm_import_module_name = Some(import_name.into());
- self
- }
-
- /// Specify the dynamic library name if we are generating bindings for a shared library.
- pub fn dynamic_library_name<T: Into<String>>(
- mut self,
- dynamic_library_name: T,
- ) -> Self {
- self.options.dynamic_library_name = Some(dynamic_library_name.into());
- self
- }
-
- /// Require successful linkage for all routines in a shared library.
- /// This allows us to optimize function calls by being able to safely assume function pointers
- /// are valid.
- pub fn dynamic_link_require_all(mut self, req: bool) -> Self {
- self.options.dynamic_link_require_all = req;
- self
- }
-
- /// Generate bindings as `pub` only if the bound item is publically accessible by C++.
- pub fn respect_cxx_access_specs(mut self, doit: bool) -> Self {
- self.options.respect_cxx_access_specs = doit;
- self
- }
-
- /// Always translate enum integer types to native Rust integer types.
- ///
- /// This will result in enums having types such as `u32` and `i16` instead
- /// of `c_uint` and `c_short`. Types for Rustified enums are always
- /// translated.
- pub fn translate_enum_integer_types(mut self, doit: bool) -> Self {
- self.options.translate_enum_integer_types = doit;
- self
- }
-
- /// Generate types with C style naming.
- ///
- /// This will add prefixes to the generated type names. For example instead of a struct `A` we
- /// will generate struct `struct_A`. Currently applies to structs, unions, and enums.
- pub fn c_naming(mut self, doit: bool) -> Self {
- self.options.c_naming = doit;
- self
- }
-
- /// Override the ABI of a given function. Regular expressions are supported.
- pub fn override_abi<T: Into<String>>(mut self, abi: Abi, arg: T) -> Self {
- self.options
- .abi_overrides
- .entry(abi)
- .or_default()
- .insert(arg.into());
- self
- }
-
- /// If true, wraps unsafe operations in unsafe blocks.
- pub fn wrap_unsafe_ops(mut self, doit: bool) -> Self {
- self.options.wrap_unsafe_ops = doit;
- self
- }
-
- #[cfg(feature = "experimental")]
- /// Whether to generate extern wrappers for `static` and `static inline` functions. Defaults to
- /// false.
- pub fn wrap_static_fns(mut self, doit: bool) -> Self {
- self.options.wrap_static_fns = doit;
- self
- }
-
- #[cfg(feature = "experimental")]
- /// Set the path for the source code file that would be created if any wrapper functions must
- /// be generated due to the presence of static functions.
- ///
- /// Bindgen will automatically add the right extension to the header and source code files.
- pub fn wrap_static_fns_path<T: AsRef<Path>>(mut self, path: T) -> Self {
- self.options.wrap_static_fns_path = Some(path.as_ref().to_owned());
- self
- }
-
- #[cfg(feature = "experimental")]
- /// Set the suffix added to the extern wrapper functions generated for `static` and `static
- /// inline` functions.
- pub fn wrap_static_fns_suffix<T: AsRef<str>>(mut self, suffix: T) -> Self {
- self.options.wrap_static_fns_suffix = Some(suffix.as_ref().to_owned());
- self
- }
-}
-
-/// Configuration options for generated bindings.
-#[derive(Clone, Debug)]
-struct BindgenOptions {
- /// The set of types that have been blocklisted and should not appear
- /// anywhere in the generated code.
- blocklisted_types: RegexSet,
-
- /// The set of functions that have been blocklisted and should not appear
- /// in the generated code.
- blocklisted_functions: RegexSet,
-
- /// The set of items, regardless of item-type, that have been
- /// blocklisted and should not appear in the generated code.
- blocklisted_items: RegexSet,
-
- /// The set of files whose contents should be blocklisted and should not
- /// appear in the generated code.
- blocklisted_files: RegexSet,
-
- /// The set of types that should be treated as opaque structures in the
- /// generated code.
- opaque_types: RegexSet,
-
- /// The explicit rustfmt path.
- rustfmt_path: Option<PathBuf>,
-
- /// The path to which we should write a Makefile-syntax depfile (if any).
- depfile: Option<deps::DepfileSpec>,
-
- /// The set of types that we should have bindings for in the generated
- /// code.
- ///
- /// This includes all types transitively reachable from any type in this
- /// set. One might think of allowlisted types/vars/functions as GC roots,
- /// and the generated Rust code as including everything that gets marked.
- allowlisted_types: RegexSet,
-
- /// Allowlisted functions. See docs for `allowlisted_types` for more.
- allowlisted_functions: RegexSet,
-
- /// 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,
-
- /// The enum patterns to mark an enum as a bitfield
- /// (newtype with bitwise operations).
- bitfield_enums: RegexSet,
-
- /// The enum patterns to mark an enum as a newtype.
- newtype_enums: RegexSet,
-
- /// The enum patterns to mark an enum as a global newtype.
- newtype_global_enums: RegexSet,
-
- /// The enum patterns to mark an enum as a Rust enum.
- rustified_enums: RegexSet,
-
- /// The enum patterns to mark an enum as a non-exhaustive Rust enum.
- rustified_non_exhaustive_enums: RegexSet,
-
- /// The enum patterns to mark an enum as a module of constants.
- constified_enum_modules: RegexSet,
-
- /// The enum patterns to mark an enum as a set of constants.
- constified_enums: RegexSet,
-
- /// The default type for C macro constants.
- default_macro_constant_type: codegen::MacroTypeVariation,
-
- /// The default style of code to generate for typedefs.
- default_alias_style: codegen::AliasVariation,
-
- /// Typedef patterns that will use regular type aliasing.
- type_alias: RegexSet,
-
- /// Typedef patterns that will be aliased by creating a new struct.
- new_type_alias: RegexSet,
-
- /// Typedef patterns that will be wrapped in a new struct and have
- /// Deref and Deref to their aliased type.
- new_type_alias_deref: RegexSet,
-
- /// The default style of code to generate for union containing non-Copy
- /// members.
- default_non_copy_union_style: codegen::NonCopyUnionStyle,
-
- /// The union patterns to mark an non-Copy union as using the bindgen
- /// generated wrapper.
- bindgen_wrapper_union: RegexSet,
-
- /// The union patterns to mark an non-Copy union as using the
- /// `::core::mem::ManuallyDrop` wrapper.
- manually_drop_union: RegexSet,
-
- /// Whether we should generate builtins or not.
- builtins: bool,
-
- /// True if we should dump the Clang AST for debugging purposes.
- emit_ast: bool,
-
- /// True if we should dump our internal IR for debugging purposes.
- emit_ir: bool,
-
- /// Output graphviz dot file.
- emit_ir_graphviz: Option<String>,
-
- /// True if we should emulate C++ namespaces with Rust modules in the
- /// generated bindings.
- enable_cxx_namespaces: bool,
-
- /// True if we should try to find unexposed attributes in functions, in
- /// order to be able to generate #[must_use] attributes in Rust.
- enable_function_attribute_detection: bool,
-
- /// True if we should avoid mangling names with namespaces.
- disable_name_namespacing: bool,
-
- /// True if we should avoid generating nested struct names.
- disable_nested_struct_naming: bool,
-
- /// True if we should avoid embedding version identifiers into source code.
- disable_header_comment: bool,
-
- /// True if we should generate layout tests for generated structures.
- layout_tests: bool,
-
- /// True if we should implement the Debug trait for C/C++ structures and types
- /// that do not support automatically deriving Debug.
- impl_debug: bool,
-
- /// True if we should implement the PartialEq trait for C/C++ structures and types
- /// that do not support automatically deriving PartialEq.
- impl_partialeq: bool,
-
- /// True if we should derive Copy trait implementations for C/C++ structures
- /// and types.
- derive_copy: bool,
-
- /// True if we should derive Debug trait implementations for C/C++ structures
- /// and types.
- derive_debug: bool,
-
- /// True if we should derive Default trait implementations for C/C++ structures
- /// and types.
- derive_default: bool,
-
- /// True if we should derive Hash trait implementations for C/C++ structures
- /// and types.
- derive_hash: bool,
-
- /// True if we should derive PartialOrd trait implementations for C/C++ structures
- /// and types.
- derive_partialord: bool,
-
- /// True if we should derive Ord trait implementations for C/C++ structures
- /// and types.
- derive_ord: bool,
-
- /// True if we should derive PartialEq trait implementations for C/C++ structures
- /// and types.
- derive_partialeq: bool,
-
- /// True if we should derive Eq trait implementations for C/C++ structures
- /// and types.
- derive_eq: bool,
-
- /// True if we should avoid using libstd to use libcore instead.
- use_core: bool,
-
- /// An optional prefix for the "raw" types, like `c_int`, `c_void`...
- ctypes_prefix: Option<String>,
-
- /// The prefix for the anon fields.
- anon_fields_prefix: String,
-
- /// Whether to time the bindgen phases.
- time_phases: bool,
-
- /// Whether we should convert float types to f32/f64 types.
- convert_floats: bool,
-
- /// The set of raw lines to prepend to the top-level module of generated
- /// Rust code.
- raw_lines: Vec<String>,
-
- /// The set of raw lines to prepend to each of the modules.
- ///
- /// This only makes sense if the `enable_cxx_namespaces` option is set.
- module_lines: HashMap<String, Vec<String>>,
-
- /// The set of arguments to pass straight through to Clang.
- clang_args: Vec<String>,
-
- /// The input header files.
- input_headers: Vec<String>,
-
- /// Tuples of unsaved file contents of the form (name, contents).
- input_header_contents: Vec<(String, String)>,
-
- /// A user-provided visitor to allow customizing different kinds of
- /// situations.
- parse_callbacks: Vec<Rc<dyn callbacks::ParseCallbacks>>,
-
- /// Which kind of items should we generate? By default, we'll generate all
- /// of them.
- codegen_config: CodegenConfig,
-
- /// Whether to treat inline namespaces conservatively.
- ///
- /// See the builder method description for more details.
- conservative_inline_namespaces: bool,
-
- /// Whether to keep documentation comments in the generated output. See the
- /// documentation for more details. Defaults to true.
- generate_comments: bool,
-
- /// Whether to generate inline functions. Defaults to false.
- generate_inline_functions: bool,
-
- /// Whether to allowlist types recursively. Defaults to true.
- allowlist_recursively: bool,
-
- /// Instead of emitting 'use objc;' to files generated from objective c files,
- /// generate '#[macro_use] extern crate objc;'
- objc_extern_crate: bool,
-
- /// Instead of emitting 'use block;' to files generated from objective c files,
- /// generate '#[macro_use] extern crate block;'
- generate_block: bool,
-
- /// Instead of emitting 'use block;' to files generated from objective c files,
- /// generate '#[macro_use] extern crate block;'
- block_extern_crate: bool,
-
- /// Whether to use the clang-provided name mangling. This is true and
- /// probably needed for C++ features.
- ///
- /// However, some old libclang versions seem to return incorrect results in
- /// some cases for non-mangled functions, see [1], so we allow disabling it.
- ///
- /// [1]: https://github.com/rust-lang/rust-bindgen/issues/528
- enable_mangling: bool,
-
- /// Whether to detect include paths using clang_sys.
- detect_include_paths: bool,
-
- /// Whether to try to fit macro constants into types smaller than u32/i32
- fit_macro_constants: bool,
-
- /// Whether to prepend the enum name to constant or newtype variants.
- prepend_enum_name: bool,
-
- /// Version of the Rust compiler to target
- rust_target: RustTarget,
-
- /// Features to enable, derived from `rust_target`
- rust_features: RustFeatures,
-
- /// Whether we should record which items in the regex sets ever matched.
- ///
- /// This may be a bit slower, but will enable reporting of unused allowlist
- /// items via the `error!` log.
- record_matches: bool,
-
- /// Whether `size_t` should be translated to `usize` automatically.
- size_t_is_usize: bool,
-
- /// Whether rustfmt should format the generated bindings.
- rustfmt_bindings: bool,
-
- /// The absolute path to the rustfmt configuration file, if None, the standard rustfmt
- /// options are used.
- rustfmt_configuration_file: Option<PathBuf>,
-
- /// The set of types that we should not derive `PartialEq` for.
- no_partialeq_types: RegexSet,
-
- /// The set of types that we should not derive `Copy` for.
- no_copy_types: RegexSet,
-
- /// The set of types that we should not derive `Debug` for.
- no_debug_types: RegexSet,
-
- /// The set of types that we should not derive/impl `Default` for.
- no_default_types: RegexSet,
-
- /// The set of types that we should not derive `Hash` for.
- no_hash_types: RegexSet,
-
- /// The set of types that we should be annotated with `#[must_use]`.
- must_use_types: RegexSet,
-
- /// Decide if C arrays should be regular pointers in rust or array pointers
- array_pointers_in_arguments: bool,
-
- /// Wasm import module name.
- wasm_import_module_name: Option<String>,
-
- /// The name of the dynamic library (if we are generating bindings for a shared library). If
- /// this is None, no dynamic bindings are created.
- dynamic_library_name: Option<String>,
-
- /// Require successful linkage for all routines in a shared library.
- /// This allows us to optimize function calls by being able to safely assume function pointers
- /// are valid. No effect if `dynamic_library_name` is None.
- dynamic_link_require_all: bool,
-
- /// Only make generated bindings `pub` if the items would be publically accessible
- /// by C++.
- respect_cxx_access_specs: bool,
-
- /// Always translate enum integer types to native Rust integer types.
- translate_enum_integer_types: bool,
-
- /// Generate types with C style naming.
- c_naming: bool,
-
- /// Always output explicit padding fields
- force_explicit_padding: bool,
-
- /// Emit vtable functions.
- vtable_generation: bool,
-
- /// Sort the code generation.
- sort_semantically: bool,
-
- /// Deduplicate `extern` blocks.
- merge_extern_blocks: bool,
-
- abi_overrides: HashMap<Abi, RegexSet>,
-
- /// Whether to wrap unsafe operations in unsafe blocks or not.
- wrap_unsafe_ops: bool,
-
- wrap_static_fns: bool,
-
- wrap_static_fns_suffix: Option<String>,
-
- wrap_static_fns_path: Option<PathBuf>,
}
impl BindgenOptions {
fn build(&mut self) {
- let regex_sets = [
+ const REGEX_SETS_LEN: usize = 27;
+
+ let regex_sets: [_; REGEX_SETS_LEN] = [
&mut self.allowlisted_vars,
&mut self.allowlisted_types,
&mut self.allowlisted_functions,
@@ -2212,10 +460,69 @@ impl BindgenOptions {
&mut self.no_hash_types,
&mut self.must_use_types,
];
+
let record_matches = self.record_matches;
+ #[cfg(feature = "experimental")]
+ {
+ let sets_len = REGEX_SETS_LEN + self.abi_overrides.len();
+ let names = if self.emit_diagnostics {
+ <[&str; REGEX_SETS_LEN]>::into_iter([
+ "--blocklist-type",
+ "--blocklist-function",
+ "--blocklist-item",
+ "--blocklist-file",
+ "--opaque-type",
+ "--allowlist-type",
+ "--allowlist-function",
+ "--allowlist-var",
+ "--allowlist-file",
+ "--bitfield-enum",
+ "--newtype-enum",
+ "--newtype-global-enum",
+ "--rustified-enum",
+ "--rustified-enum-non-exhaustive",
+ "--constified-enum-module",
+ "--constified-enum",
+ "--type-alias",
+ "--new-type-alias",
+ "--new-type-alias-deref",
+ "--bindgen-wrapper-union",
+ "--manually-drop-union",
+ "--no-partialeq",
+ "--no-copy",
+ "--no-debug",
+ "--no-default",
+ "--no-hash",
+ "--must-use",
+ ])
+ .chain((0..self.abi_overrides.len()).map(|_| "--override-abi"))
+ .map(Some)
+ .collect()
+ } else {
+ vec![None; sets_len]
+ };
+
+ for (regex_set, name) in
+ self.abi_overrides.values_mut().chain(regex_sets).zip(names)
+ {
+ regex_set.build_with_diagnostics(record_matches, name);
+ }
+ }
+ #[cfg(not(feature = "experimental"))]
for regex_set in self.abi_overrides.values_mut().chain(regex_sets) {
regex_set.build(record_matches);
}
+
+ let rust_target = self.rust_target;
+ #[allow(deprecated)]
+ if rust_target <= RustTarget::Stable_1_30 {
+ deprecated_target_diagnostic(rust_target, self);
+ }
+
+ // Disable `untagged_union` if the target does not support it.
+ if !self.rust_features.untagged_union {
+ self.untagged_union = false;
+ }
}
/// Update rust target version
@@ -2260,121 +567,25 @@ impl BindgenOptions {
}
}
-impl Default for BindgenOptions {
- fn default() -> BindgenOptions {
- macro_rules! options {
- ($($field:ident $(: $value:expr)?,)* --default-fields-- $($default_field:ident,)*) => {
- BindgenOptions {
- $($field $(: $value)*,)*
- $($default_field: Default::default(),)*
- }
- };
- }
+fn deprecated_target_diagnostic(target: RustTarget, _options: &BindgenOptions) {
+ let target = String::from(target);
+ warn!("The {} Rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues", target,);
- let rust_target = RustTarget::default();
-
- options! {
- rust_target,
- rust_features: rust_target.into(),
- layout_tests: true,
- derive_copy: true,
- derive_debug: true,
- anon_fields_prefix: DEFAULT_ANON_FIELDS_PREFIX.into(),
- convert_floats: true,
- codegen_config: CodegenConfig::all(),
- generate_comments: true,
- allowlist_recursively: true,
- enable_mangling: true,
- detect_include_paths: true,
- prepend_enum_name: true,
- record_matches: true,
- rustfmt_bindings: true,
- size_t_is_usize: true,
-
- --default-fields--
- blocklisted_types,
- blocklisted_functions,
- blocklisted_items,
- blocklisted_files,
- opaque_types,
- rustfmt_path,
- depfile,
- allowlisted_types,
- allowlisted_functions,
- allowlisted_vars,
- allowlisted_files,
- default_enum_style,
- bitfield_enums,
- newtype_enums,
- newtype_global_enums,
- rustified_enums,
- rustified_non_exhaustive_enums,
- constified_enums,
- constified_enum_modules,
- default_macro_constant_type,
- default_alias_style,
- type_alias,
- new_type_alias,
- new_type_alias_deref,
- default_non_copy_union_style,
- bindgen_wrapper_union,
- manually_drop_union,
- builtins,
- emit_ast,
- emit_ir,
- emit_ir_graphviz,
- impl_debug,
- impl_partialeq,
- derive_default,
- derive_hash,
- derive_partialord,
- derive_ord,
- derive_partialeq,
- derive_eq,
- enable_cxx_namespaces,
- enable_function_attribute_detection,
- disable_name_namespacing,
- disable_nested_struct_naming,
- disable_header_comment,
- use_core,
- ctypes_prefix,
- raw_lines,
- module_lines,
- clang_args,
- input_headers,
- input_header_contents,
- parse_callbacks,
- conservative_inline_namespaces,
- generate_inline_functions,
- generate_block,
- objc_extern_crate,
- block_extern_crate,
- fit_macro_constants,
- time_phases,
- rustfmt_configuration_file,
- no_partialeq_types,
- no_copy_types,
- no_debug_types,
- no_default_types,
- no_hash_types,
- must_use_types,
- array_pointers_in_arguments,
- wasm_import_module_name,
- dynamic_library_name,
- dynamic_link_require_all,
- respect_cxx_access_specs,
- translate_enum_integer_types,
- c_naming,
- force_explicit_padding,
- vtable_generation,
- sort_semantically,
- merge_extern_blocks,
- abi_overrides,
- wrap_unsafe_ops,
- wrap_static_fns,
- wrap_static_fns_suffix,
- wrap_static_fns_path,
- }
+ #[cfg(feature = "experimental")]
+ if _options.emit_diagnostics {
+ use crate::diagnostics::{Diagnostic, Level};
+
+ let mut diagnostic = Diagnostic::default();
+ diagnostic.with_title(
+ format!("The {} Rust target is deprecated.", target),
+ Level::Warn,
+ );
+ diagnostic.add_annotation(
+ "This Rust target was passed to `--rust-target`",
+ Level::Info,
+ );
+ diagnostic.add_annotation("If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues", Level::Help);
+ diagnostic.display();
}
}
@@ -2448,7 +659,6 @@ impl std::error::Error for BindgenError {}
#[derive(Debug)]
pub struct Bindings {
options: BindgenOptions,
- warnings: Vec<String>,
module: proc_macro2::TokenStream,
}
@@ -2673,14 +883,10 @@ impl Bindings {
parse(&mut context)?;
}
- let (module, options, warnings) =
+ let (module, options) =
codegen::codegen(context).map_err(BindgenError::Codegen)?;
- Ok(Bindings {
- options,
- warnings,
- module,
- })
+ Ok(Bindings { options, module })
}
/// Write these bindings as source text to a file.
@@ -2697,7 +903,7 @@ impl Bindings {
/// Write these bindings as source text to the given `Write`able.
pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> {
if !self.options.disable_header_comment {
- let version = Some("0.64.0");
+ let version = Some("0.65.1");
let header = format!(
"/* automatically generated by rust-bindgen {} */\n\n",
version.unwrap_or("(unknown version)")
@@ -2714,18 +920,16 @@ impl Bindings {
writer.write_all("\n".as_bytes())?;
}
- let bindings = self.module.to_string();
-
- match self.rustfmt_generated_string(&bindings) {
- Ok(rustfmt_bindings) => {
- writer.write_all(rustfmt_bindings.as_bytes())?;
+ match self.format_tokens(&self.module) {
+ Ok(formatted_bindings) => {
+ writer.write_all(formatted_bindings.as_bytes())?;
}
Err(err) => {
eprintln!(
"Failed to run rustfmt: {} (non-fatal, continuing)",
err
);
- writer.write_all(bindings.as_bytes())?;
+ writer.write_all(self.module.to_string().as_bytes())?;
}
}
Ok(())
@@ -2733,7 +937,7 @@ impl Bindings {
/// Gets the rustfmt path to rustfmt the generated bindings.
fn rustfmt_path(&self) -> io::Result<Cow<PathBuf>> {
- debug_assert!(self.options.rustfmt_bindings);
+ debug_assert!(matches!(self.options.formatter, Formatter::Rustfmt));
if let Some(ref p) = self.options.rustfmt_path {
return Ok(Cow::Borrowed(p));
}
@@ -2753,16 +957,22 @@ impl Bindings {
Ok(Cow::Owned("rustfmt".into()))
}
- /// Checks if rustfmt_bindings is set and runs rustfmt on the string
- fn rustfmt_generated_string<'a>(
+ /// Formats a token stream with the formatter set up in `BindgenOptions`.
+ fn format_tokens(
&self,
- source: &'a str,
- ) -> io::Result<Cow<'a, str>> {
+ tokens: &proc_macro2::TokenStream,
+ ) -> io::Result<String> {
let _t = time::Timer::new("rustfmt_generated_string")
.with_output(self.options.time_phases);
- if !self.options.rustfmt_bindings {
- return Ok(Cow::Borrowed(source));
+ match self.options.formatter {
+ Formatter::None => return Ok(tokens.to_string()),
+
+ #[cfg(feature = "prettyplease")]
+ Formatter::Prettyplease => {
+ return Ok(prettyplease::unparse(&syn::parse_quote!(#tokens)));
+ }
+ Formatter::Rustfmt => (),
}
let rustfmt = self.rustfmt_path()?;
@@ -2783,7 +993,7 @@ impl Bindings {
let mut child_stdin = child.stdin.take().unwrap();
let mut child_stdout = child.stdout.take().unwrap();
- let source = source.to_owned();
+ let source = tokens.to_string();
// Write to stdin in a new thread, so that we can read from stdout on this
// thread. This keeps the child from blocking on writing to its stdout which
@@ -2804,39 +1014,42 @@ impl Bindings {
match String::from_utf8(output) {
Ok(bindings) => match status.code() {
- Some(0) => Ok(Cow::Owned(bindings)),
+ Some(0) => Ok(bindings),
Some(2) => Err(io::Error::new(
io::ErrorKind::Other,
"Rustfmt parsing errors.".to_string(),
)),
Some(3) => {
- warn!("Rustfmt could not format some lines.");
- Ok(Cow::Owned(bindings))
+ rustfmt_non_fatal_error_diagnostic(
+ "Rustfmt could not format some lines",
+ &self.options,
+ );
+ Ok(bindings)
}
_ => Err(io::Error::new(
io::ErrorKind::Other,
"Internal rustfmt error".to_string(),
)),
},
- _ => Ok(Cow::Owned(source)),
+ _ => Ok(source),
}
}
+}
- /// Emit all the warning messages raised while generating the bindings in a build script.
- ///
- /// If you are using `bindgen` outside of a build script you should use [`Bindings::warnings`]
- /// and handle the messages accordingly instead.
- #[inline]
- pub fn emit_warnings(&self) {
- for message in &self.warnings {
- println!("cargo:warning={}", message);
- }
- }
+fn rustfmt_non_fatal_error_diagnostic(msg: &str, _options: &BindgenOptions) {
+ warn!("{}", msg);
- /// Return all the warning messages raised while generating the bindings.
- #[inline]
- pub fn warnings(&self) -> &[String] {
- &self.warnings
+ #[cfg(feature = "experimental")]
+ if _options.emit_diagnostics {
+ use crate::diagnostics::{Diagnostic, Level};
+
+ Diagnostic::default()
+ .with_title(msg, Level::Warn)
+ .add_annotation(
+ "The bindings will be generated but not formatted.",
+ Level::Note,
+ )
+ .display();
}
}
@@ -2962,22 +1175,38 @@ pub fn clang_version() -> ClangVersion {
}
}
+fn env_var<K: AsRef<str> + AsRef<OsStr>>(
+ parse_callbacks: &[Rc<dyn callbacks::ParseCallbacks>],
+ key: K,
+) -> Result<String, std::env::VarError> {
+ for callback in parse_callbacks {
+ callback.read_env_var(key.as_ref());
+ }
+ std::env::var(key)
+}
+
/// Looks for the env var `var_${TARGET}`, and falls back to just `var` when it is not found.
-fn get_target_dependent_env_var(var: &str) -> Option<String> {
- if let Ok(target) = env::var("TARGET") {
- if let Ok(v) = env::var(format!("{}_{}", var, target)) {
+fn get_target_dependent_env_var(
+ parse_callbacks: &[Rc<dyn callbacks::ParseCallbacks>],
+ var: &str,
+) -> Option<String> {
+ if let Ok(target) = env_var(parse_callbacks, "TARGET") {
+ if let Ok(v) = env_var(parse_callbacks, format!("{}_{}", var, target)) {
return Some(v);
}
- if let Ok(v) = env::var(format!("{}_{}", var, target.replace('-', "_")))
- {
+ if let Ok(v) = env_var(
+ parse_callbacks,
+ format!("{}_{}", var, target.replace('-', "_")),
+ ) {
return Some(v);
}
}
- env::var(var).ok()
+
+ env_var(parse_callbacks, var).ok()
}
/// A ParseCallbacks implementation that will act on file includes by echoing a rerun-if-changed
-/// line
+/// line and on env variable usage by echoing a rerun-if-env-changed line
///
/// When running inside a `build.rs` script, this can be used to make cargo invalidate the
/// generated bindings whenever any of the files included from the header change:
@@ -2995,6 +1224,10 @@ impl callbacks::ParseCallbacks for CargoCallbacks {
fn include_file(&self, filename: &str) {
println!("cargo:rerun-if-changed={}", filename);
}
+
+ fn read_env_var(&self, key: &str) {
+ println!("cargo:rerun-if-env-changed={}", key);
+ }
}
/// Test command_line_flag function.
diff --git a/options/as_args.rs b/options/as_args.rs
new file mode 100644
index 0000000..13439c4
--- /dev/null
+++ b/options/as_args.rs
@@ -0,0 +1,52 @@
+use std::path::PathBuf;
+
+use crate::RegexSet;
+
+/// Trait used to turn [`crate::BindgenOptions`] fields into CLI args.
+pub(super) trait AsArgs {
+ fn as_args(&self, args: &mut Vec<String>, flag: &str);
+}
+
+/// If the `bool` is `true`, `flag` is pushed into `args`.
+///
+/// be careful about the truth value of the field as some options, like `--no-layout-tests`, are
+/// actually negations of the fields.
+impl AsArgs for bool {
+ fn as_args(&self, args: &mut Vec<String>, flag: &str) {
+ if *self {
+ args.push(flag.to_string());
+ }
+ }
+}
+
+/// Iterate over all the items of the `RegexSet` and push `flag` followed by the item into `args`
+/// for each item.
+impl AsArgs for RegexSet {
+ fn as_args(&self, args: &mut Vec<String>, flag: &str) {
+ for item in self.get_items() {
+ args.extend_from_slice(&[flag.to_owned(), item.clone()]);
+ }
+ }
+}
+
+/// If the `Option` is `Some(value)`, push `flag` followed by `value`.
+impl AsArgs for Option<String> {
+ fn as_args(&self, args: &mut Vec<String>, flag: &str) {
+ if let Some(string) = self {
+ args.extend_from_slice(&[flag.to_owned(), string.clone()]);
+ }
+ }
+}
+
+/// If the `Option` is `Some(path)`, push `flag` followed by the [`std::path::Path::display`]
+/// representation of `path`.
+impl AsArgs for Option<PathBuf> {
+ fn as_args(&self, args: &mut Vec<String>, flag: &str) {
+ if let Some(path) = self {
+ args.extend_from_slice(&[
+ flag.to_owned(),
+ path.display().to_string(),
+ ]);
+ }
+ }
+}
diff --git a/options/helpers.rs b/options/helpers.rs
new file mode 100644
index 0000000..1816c72
--- /dev/null
+++ b/options/helpers.rs
@@ -0,0 +1,43 @@
+/// Helper function that appends extra documentation to [`crate::Builder`] methods that support regular
+/// expressions in their input.
+macro_rules! regex_option {
+ ($(#[$attrs:meta])* pub fn $($tokens:tt)*) => {
+ $(#[$attrs])*
+ ///
+ /// Regular expressions are supported. Check the [regular expression
+ /// arguments](./struct.Builder.html#regular-expression-arguments) section and the
+ /// [regex](https://docs.rs/regex) crate documentation for further information.
+ pub fn $($tokens)*
+ };
+}
+
+/// Helper macro to set the default value of each option.
+///
+/// This macro is an internal implementation detail of the `options` macro and should not be used
+/// directly.
+macro_rules! default {
+ () => {
+ Default::default()
+ };
+ ($expr:expr) => {
+ $expr
+ };
+}
+
+/// Helper macro to set the conversion to CLI arguments for each option.
+///
+/// This macro is an internal implementation detail of the `options` macro and should not be used
+/// directly.
+macro_rules! as_args {
+ ($flag:literal) => {
+ |field, args| AsArgs::as_args(field, args, $flag)
+ };
+ ($expr:expr) => {
+ $expr
+ };
+}
+
+/// Helper function to ignore an option when converting it into CLI arguments.
+///
+/// This function is only used inside `options` and should not be used in other contexts.
+pub(super) fn ignore<T>(_: &T, _: &mut Vec<String>) {}
diff --git a/options/mod.rs b/options/mod.rs
new file mode 100644
index 0000000..c60da71
--- /dev/null
+++ b/options/mod.rs
@@ -0,0 +1,2008 @@
+//! Declarations and setter methods for `bindgen` options.
+//!
+//! The main entry point of this module is the `options` macro.
+#[macro_use]
+mod helpers;
+mod as_args;
+
+use crate::callbacks::ParseCallbacks;
+use crate::codegen::{
+ AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle,
+};
+use crate::deps::DepfileSpec;
+use crate::features::{RustFeatures, RustTarget};
+use crate::regex_set::RegexSet;
+use crate::Abi;
+use crate::Builder;
+use crate::CodegenConfig;
+use crate::FieldVisibilityKind;
+use crate::Formatter;
+use crate::HashMap;
+use crate::DEFAULT_ANON_FIELDS_PREFIX;
+
+use std::env;
+#[cfg(feature = "experimental")]
+use std::path::Path;
+use std::path::PathBuf;
+use std::rc::Rc;
+
+use as_args::AsArgs;
+use helpers::ignore;
+
+/// Macro used to generate the [`BindgenOptions`] type and the [`Builder`] setter methods for each
+/// one of the fields of `BindgenOptions`.
+///
+/// The input format of this macro resembles a `struct` pattern. Each field of the `BindgenOptions`
+/// type is declared by adding the name of the field and its type using the `name: type` syntax and
+/// a block of code with the following items:
+///
+/// - `default`: The default value for the field. If this item is omitted, `Default::default()` is
+/// used instead, meaning that the type of the field must implement `Default`.
+/// - `methods`: A block of code containing methods for the `Builder` type. These methods should be
+/// related to the field being declared.
+/// - `as_args`: This item declares how the field should be converted into a valid CLI argument for
+/// `bindgen` and is used in the [`Builder::command_line_flags`] method which is used to do a
+/// roundtrip test of the CLI args in the `bindgen-test` crate. This item can take one of the
+/// following:
+/// - A string literal with the flag if the type of the field implements the [`AsArgs`] trait.
+/// - A closure with the signature `|field, args: &mut Vec<String>| -> ()` that pushes arguments
+/// into the `args` buffer based on the value of the field. This is used if the field does not
+/// implement `AsArgs` or if the implementation of the trait is not logically correct for the
+/// option and a custom behavior must be taken into account.
+/// - The `ignore` literal, which does not emit any CLI arguments for this field. This is useful
+/// if the field cannot be used from the `bindgen` CLI.
+///
+/// As an example, this would be the declaration of a `bool` field called `be_fun` whose default
+/// value is `false` (the `Default` value for `bool`):
+/// ```rust,ignore
+/// be_fun: bool {
+/// methods: {
+/// /// Ask `bindgen` to be fun. This option is disabled by default.
+/// fn be_fun(mut self) -> Self {
+/// self.options.be_fun = true;
+/// self
+/// }
+/// },
+/// as_args: "--be-fun",
+/// }
+/// ```
+///
+/// However, we could also set the `be_fun` field to `true` by default and use a `--not-fun` flag
+/// instead. This means that we have to add the `default` item and use a closure in the `as_args`
+/// item:
+/// ```rust,ignore
+/// be_fun: bool {
+/// default: true,
+/// methods: {
+/// /// Ask `bindgen` to not be fun. `bindgen` is fun by default.
+/// fn not_fun(mut self) -> Self {
+/// self.options.be_fun = false;
+/// self
+/// }
+/// },
+/// as_args: |be_fun, args| (!be_fun).as_args(args, "--not-fun"),
+/// }
+/// ```
+/// More complex examples can be found in the sole invocation of this macro.
+macro_rules! options {
+ ($(
+ $(#[doc = $docs:literal])+
+ $field:ident: $ty:ty {
+ $(default: $default:expr,)?
+ methods: {$($methods_tokens:tt)*}$(,)?
+ as_args: $as_args:expr$(,)?
+ }$(,)?
+ )*) => {
+ #[derive(Debug, Clone)]
+ pub(crate) struct BindgenOptions {
+ $($(#[doc = $docs])* pub(crate) $field: $ty,)*
+ }
+
+ impl Default for BindgenOptions {
+ fn default() -> Self {
+ Self {
+ $($field: default!($($default)*),)*
+ }
+ }
+ }
+
+ impl Builder {
+ /// Generates the command line flags used to create this [`Builder`].
+ pub fn command_line_flags(&self) -> Vec<String> {
+ let mut args = vec![];
+
+ let headers = match self.options.input_headers.split_last() {
+ Some((header, headers)) => {
+ // The last input header is passed as an argument in the first position.
+ args.push(header.clone());
+ headers
+ },
+ None => &[]
+ };
+
+ $({
+ let func: fn(&$ty, &mut Vec<String>) = as_args!($as_args);
+ func(&self.options.$field, &mut args);
+ })*
+
+ // Add the `--experimental` flag if `bindgen` is built with the `experimental`
+ // feature.
+ if cfg!(feature = "experimental") {
+ args.push("--experimental".to_owned());
+ }
+
+ // Add all the clang arguments.
+ args.push("--".to_owned());
+
+ if !self.options.clang_args.is_empty() {
+ args.extend_from_slice(&self.options.clang_args);
+ }
+
+ // We need to pass all but the last header via the `-include` clang argument.
+ for header in headers {
+ args.push("-include".to_owned());
+ args.push(header.clone());
+ }
+
+ args
+ }
+
+ $($($methods_tokens)*)*
+ }
+ };
+}
+
+options! {
+ /// Types that have been blocklisted and should not appear anywhere in the generated code.
+ blocklisted_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not generate any bindings for the given type.
+ pub fn blocklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.blocklisted_types.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--blocklist-type",
+ },
+ /// Functions that have been blocklisted and should not appear in the generated code.
+ blocklisted_functions: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not generate any bindings for the given function.
+ pub fn blocklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.blocklisted_functions.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--blocklist-function",
+ },
+ /// Items that have been blocklisted and should not appear in the generated code.
+ blocklisted_items: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not generate any bindings for the given item, regardless of whether it is a
+ /// type, function, module, etc.
+ pub fn blocklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.blocklisted_items.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--blocklist-item",
+ },
+ /// Files whose contents should be blocklisted and should not appear in the generated code.
+ blocklisted_files: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not generate any bindings for the contents of the given file, regardless of
+ /// whether the contents of the file are types, functions, modules, etc.
+ pub fn blocklist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.blocklisted_files.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--blocklist-file",
+ },
+ /// Types that should be treated as opaque structures in the generated code.
+ opaque_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Treat the given type as opaque in the generated bindings.
+ ///
+ /// Opaque in this context means that none of the generated bindings will contain
+ /// information about the inner representation of the type and the type itself will
+ /// be represented as a chunk of bytes with the alignment and size of the type.
+ pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.opaque_types.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--opaque-type",
+ },
+ /// The explicit `rustfmt` path.
+ rustfmt_path: Option<PathBuf> {
+ methods: {
+ /// Set an explicit path to the `rustfmt` binary.
+ ///
+ /// This option only comes into effect if `rustfmt` is set to be the formatter used by
+ /// `bindgen`. Check the documentation of the [`Builder::formatter`] method for more
+ /// information.
+ pub fn with_rustfmt<P: Into<PathBuf>>(mut self, path: P) -> Self {
+ self.options.rustfmt_path = Some(path.into());
+ self
+ }
+ },
+ // This option cannot be set from the CLI.
+ as_args: ignore,
+ },
+ /// The path to which we should write a Makefile-syntax depfile (if any).
+ depfile: Option<DepfileSpec> {
+ methods: {
+ /// Add a depfile output which will be written alongside the generated bindings.
+ pub fn depfile<H: Into<String>, D: Into<PathBuf>>(
+ mut self,
+ output_module: H,
+ depfile: D,
+ ) -> Builder {
+ self.options.depfile = Some(DepfileSpec {
+ output_module: output_module.into(),
+ depfile_path: depfile.into(),
+ });
+ self
+ }
+ },
+ as_args: |depfile, args| {
+ if let Some(depfile) = depfile {
+ args.push("--depfile".into());
+ args.push(depfile.depfile_path.display().to_string());
+ }
+ },
+ },
+ /// Types that have been allowlisted and should appear in the generated code.
+ allowlisted_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Generate bindings for the given type.
+ ///
+ /// This option is transitive by default. Check the documentation of the
+ /// [`Builder::allowlist_recursively`] method for further information.
+ pub fn allowlist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.allowlisted_types.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--allowlist-type",
+ },
+ /// Functions that have been allowlisted and should appear in the generated code.
+ allowlisted_functions: RegexSet {
+ methods: {
+ regex_option! {
+ /// Generate bindings for the given function.
+ ///
+ /// This option is transitive by default. Check the documentation of the
+ /// [`Builder::allowlist_recursively`] method for further information.
+ pub fn allowlist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.allowlisted_functions.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--allowlist-function",
+ },
+ /// Variables that have been allowlisted and should appear in the generated code.
+ allowlisted_vars: RegexSet {
+ methods: {
+ regex_option! {
+ /// Generate bindings for the given variable.
+ ///
+ /// This option is transitive by default. Check the documentation of the
+ /// [`Builder::allowlist_recursively`] method for further information.
+ pub fn allowlist_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.allowlisted_vars.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--allowlist-var",
+ },
+ /// Files whose contents have been allowlisted and should appear in the generated code.
+ allowlisted_files: RegexSet {
+ methods: {
+ regex_option! {
+ /// Generate bindings for the content of the given file.
+ ///
+ /// This option is transitive by default. Check the documentation of the
+ /// [`Builder::allowlist_recursively`] method for further information.
+ pub fn allowlist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.allowlisted_files.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--allowlist-file",
+ },
+ /// The default style of for generated `enum`s.
+ default_enum_style: EnumVariation {
+ methods: {
+ /// Set the default style for generated `enum`s.
+ ///
+ /// If this method is not called, the [`EnumVariation::Consts`] style will be used by
+ /// default.
+ ///
+ /// To set the style for individual `enum`s, use [`Builder::bitfield_enum`],
+ /// [`Builder::newtype_enum`], [`Builder::newtype_global_enum`],
+ /// [`Builder::rustified_enum`], [`Builder::rustified_non_exhaustive_enum`],
+ /// [`Builder::constified_enum_module`] or [`Builder::constified_enum`].
+ pub fn default_enum_style(
+ mut self,
+ arg: EnumVariation,
+ ) -> Builder {
+ self.options.default_enum_style = arg;
+ self
+ }
+ },
+ as_args: |variation, args| {
+ if *variation != Default::default() {
+ args.push("--default-enum-style".to_owned());
+ args.push(variation.to_string());
+ }
+ },
+ },
+ /// `enum`s marked as bitfield-like. This is, newtypes with bitwise operations.
+ bitfield_enums: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `enum` as being bitfield-like.
+ ///
+ /// This is similar to the [`Builder::newtype_enum`] style, but with the bitwise
+ /// operators implemented.
+ pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.bitfield_enums.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--bitfield-enum",
+ },
+ /// `enum`s marked as newtypes.
+ newtype_enums: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `enum` as a newtype.
+ ///
+ /// This means that an integer newtype will be declared to represent the `enum`
+ /// type and its variants will be represented as constants inside of this type's
+ /// `impl` block.
+ pub fn newtype_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.newtype_enums.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--newtype-enum",
+ },
+ /// `enum`s marked as global newtypes .
+ newtype_global_enums: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `enum` as a global newtype.
+ ///
+ /// This is similar to the [`Builder::newtype_enum`] style, but the constants for
+ /// each variant are free constants instead of being declared inside an `impl`
+ /// block for the newtype.
+ pub fn newtype_global_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.newtype_global_enums.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--newtype-global-enum",
+ },
+ /// `enum`s marked as Rust `enum`s.
+ rustified_enums: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `enum` as a Rust `enum`.
+ ///
+ /// This means that each variant of the `enum` will be represented as a Rust `enum`
+ /// variant.
+ ///
+ /// **Use this with caution**, creating an instance of a Rust `enum` with an
+ /// invalid value will cause undefined behaviour. To avoid this, use the
+ /// [`Builder::newtype_enum`] style instead.
+ pub fn rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.rustified_enums.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--rustified-enum",
+ },
+ /// `enum`s marked as non-exhaustive Rust `enum`s.
+ rustified_non_exhaustive_enums: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `enum` as a non-exhaustive Rust `enum`.
+ ///
+ /// This is similar to the [`Builder::rustified_enum`] style, but the `enum` is
+ /// tagged with the `#[non_exhaustive]` attribute.
+ pub fn rustified_non_exhaustive_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.rustified_non_exhaustive_enums.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--rustified-non-exhaustive-enums",
+ },
+ /// `enum`s marked as modules of constants.
+ constified_enum_modules: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `enum` as a module with a set of integer constants.
+ pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.constified_enum_modules.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--constified-enum-module",
+ },
+ /// `enum`s marked as a set of constants.
+ constified_enums: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `enum` as a set o integer constants.
+ ///
+ /// This is similar to the [`Builder::constified_enum_module`] style, but the
+ /// constants are generated in the current module instead of in a new module.
+ pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.constified_enums.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--constified-enum",
+ },
+ /// The default type signedness for C macro constants.
+ default_macro_constant_type: MacroTypeVariation {
+ methods: {
+ /// Set the default type signedness to be used for macro constants.
+ ///
+ /// If this method is not called, [`MacroTypeVariation::Unsigned`] is used by default.
+ ///
+ /// To set the type for individual macro constants, use the
+ /// [`ParseCallbacks::int_macro`] method.
+ pub fn default_macro_constant_type(mut self, arg: MacroTypeVariation) -> Builder {
+ self.options.default_macro_constant_type = arg;
+ self
+ }
+
+ },
+ as_args: |variation, args| {
+ if *variation != Default::default() {
+ args.push("--default-macro-constant-type".to_owned());
+ args.push(variation.to_string());
+ }
+ },
+ },
+ /// The default style of code generation for `typedef`s.
+ default_alias_style: AliasVariation {
+ methods: {
+ /// Set the default style of code generation for `typedef`s.
+ ///
+ /// If this method is not called, the [`AliasVariation::TypeAlias`] style is used by
+ /// default.
+ ///
+ /// To set the style for individual `typedefs`s, use [`Builder::type_alias`],
+ /// [`Builder::new_type_alias`] or [`Builder::new_type_alias_deref`].
+ pub fn default_alias_style(
+ mut self,
+ arg: AliasVariation,
+ ) -> Builder {
+ self.options.default_alias_style = arg;
+ self
+ }
+ },
+ as_args: |variation, args| {
+ if *variation != Default::default() {
+ args.push("--default-alias-style".to_owned());
+ args.push(variation.to_string());
+ }
+ },
+ },
+ /// `typedef` patterns that will use regular type aliasing.
+ type_alias: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `typedef` as a regular Rust `type` alias.
+ ///
+ /// This is the default behavior, meaning that this method only comes into effect
+ /// if a style different from [`AliasVariation::TypeAlias`] was passed to the
+ /// [`Builder::default_alias_style`] method.
+ pub fn type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.type_alias.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--type-alias",
+ },
+ /// `typedef` patterns that will be aliased by creating a newtype.
+ new_type_alias: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `typedef` as a Rust newtype by having the aliased
+ /// type be wrapped in a `struct` with `#[repr(transparent)]`.
+ ///
+ /// This method can be used to enforce stricter type checking.
+ pub fn new_type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.new_type_alias.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--new-type-alias",
+ },
+ /// `typedef` patterns that will be wrapped in a newtype implementing `Deref` and `DerefMut`.
+ new_type_alias_deref: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `typedef` to be generated as a newtype that can be dereferenced.
+ ///
+ /// This is similar to the [`Builder::new_type_alias`] style, but the newtype
+ /// implements `Deref` and `DerefMut` with the aliased type as a target.
+ pub fn new_type_alias_deref<T: AsRef<str>>(mut self, arg: T) -> Builder {
+ self.options.new_type_alias_deref.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--new-type-alias-deref",
+ },
+ /// The default style of code to generate for `union`s containing non-`Copy` members.
+ default_non_copy_union_style: NonCopyUnionStyle {
+ methods: {
+ /// Set the default style of code to generate for `union`s with non-`Copy` members.
+ ///
+ /// If this method is not called, the [`NonCopyUnionStyle::BindgenWrapper`] style is
+ /// used by default.
+ ///
+ /// To set the style for individual `union`s, use [`Builder::bindgen_wrapper_union`] or
+ /// [`Builder::manually_drop_union`].
+ pub fn default_non_copy_union_style(mut self, arg: NonCopyUnionStyle) -> Self {
+ self.options.default_non_copy_union_style = arg;
+ self
+ }
+ },
+ as_args: |style, args| {
+ if *style != Default::default() {
+ args.push("--default-non-copy-union-style".to_owned());
+ args.push(style.to_string());
+ }
+ },
+ },
+ /// The patterns marking non-`Copy` `union`s as using the `bindgen` generated wrapper.
+ bindgen_wrapper_union: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `union` to use a `bindgen`-generated wrapper for its members if at
+ /// least one them is not `Copy`.
+ ///
+ /// This is the default behavior, meaning that this method only comes into effect
+ /// if a style different from [`NonCopyUnionStyle::BindgenWrapper`] was passed to
+ /// the [`Builder::default_non_copy_union_style`] method.
+ pub fn bindgen_wrapper_union<T: AsRef<str>>(mut self, arg: T) -> Self {
+ self.options.bindgen_wrapper_union.insert(arg);
+ self
+ }
+ }
+ },
+ as_args: "--bindgen-wrapper-union",
+ },
+ /// The patterns marking non-`Copy` `union`s as using the `ManuallyDrop` wrapper.
+ manually_drop_union: RegexSet {
+ methods: {
+ regex_option! {
+ /// Mark the given `union` to use [`::core::mem::ManuallyDrop`] for its members if
+ /// at least one of them is not `Copy`.
+ ///
+ /// The `ManuallyDrop` type was stabilized in Rust 1.20.0, do not use this option
+ /// if your target version is lower than this.
+ pub fn manually_drop_union<T: AsRef<str>>(mut self, arg: T) -> Self {
+ self.options.manually_drop_union.insert(arg);
+ self
+ }
+ }
+
+ },
+ as_args: "--manually-drop-union",
+ },
+
+
+ /// Whether we should generate built-in definitions.
+ builtins: bool {
+ methods: {
+ /// Generate Rust bindings for built-in definitions (for example `__builtin_va_list`).
+ ///
+ /// Bindings for built-in definitions are not emitted by default.
+ pub fn emit_builtins(mut self) -> Builder {
+ self.options.builtins = true;
+ self
+ }
+ },
+ as_args: "--builtins",
+ },
+ /// Whether we should dump the Clang AST for debugging purposes.
+ emit_ast: bool {
+ methods: {
+ /// Emit the Clang AST to `stdout` for debugging purposes.
+ ///
+ /// The Clang AST is not emitted by default.
+ pub fn emit_clang_ast(mut self) -> Builder {
+ self.options.emit_ast = true;
+ self
+ }
+ },
+ as_args: "--emit-clang-ast",
+ },
+ /// Whether we should dump our IR for debugging purposes.
+ emit_ir: bool {
+ methods: {
+ /// Emit the `bindgen` internal representation to `stdout` for debugging purposes.
+ ///
+ /// This internal representation is not emitted by default.
+ pub fn emit_ir(mut self) -> Builder {
+ self.options.emit_ir = true;
+ self
+ }
+ },
+ as_args: "--emit-ir",
+ },
+ /// Output path for the `graphviz` DOT file.
+ emit_ir_graphviz: Option<String> {
+ methods: {
+ /// Set the path for the file where the`bindgen` internal representation will be
+ /// emitted as a graph using the `graphviz` DOT language.
+ ///
+ /// This graph representation is not emitted by default.
+ pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
+ let path = path.into();
+ self.options.emit_ir_graphviz = Some(path);
+ self
+ }
+ },
+ as_args: "--emit-ir-graphviz",
+ },
+
+ /// Whether we should emulate C++ namespaces with Rust modules.
+ enable_cxx_namespaces: bool {
+ methods: {
+ /// Emulate C++ namespaces using Rust modules in the generated bindings.
+ ///
+ /// C++ namespaces are not emulated by default.
+ pub fn enable_cxx_namespaces(mut self) -> Builder {
+ self.options.enable_cxx_namespaces = true;
+ self
+ }
+ },
+ as_args: "--enable-cxx-namespaces",
+ },
+ /// Whether we should try to find unexposed attributes in functions.
+ enable_function_attribute_detection: bool {
+ methods: {
+ /// Enable detecting function attributes on C functions.
+ ///
+ /// This enables the following features:
+ /// - Add `#[must_use]` attributes to Rust items whose C counterparts are marked as so.
+ /// This feature also requires that the Rust target version supports the attribute.
+ /// - Set `!` as the return type for Rust functions whose C counterparts are marked as
+ /// diverging.
+ ///
+ /// This option can be quite slow in some cases (check [#1465]), so it is disabled by
+ /// default.
+ ///
+ /// [#1465]: https://github.com/rust-lang/rust-bindgen/issues/1465
+ pub fn enable_function_attribute_detection(mut self) -> Self {
+ self.options.enable_function_attribute_detection = true;
+ self
+ }
+
+ },
+ as_args: "--enable-function-attribute-detection",
+ },
+ /// Whether we should avoid mangling names with namespaces.
+ disable_name_namespacing: bool {
+ methods: {
+ /// Disable name auto-namespacing.
+ ///
+ /// By default, `bindgen` mangles names like `foo::bar::Baz` to look like `foo_bar_Baz`
+ /// instead of just `Baz`. This method disables that behavior.
+ ///
+ /// Note that this does not change the names used for allowlisting and blocklisting,
+ /// which should still be mangled with the namespaces. Additionally, this option may
+ /// cause `bindgen` to generate duplicate names.
+ pub fn disable_name_namespacing(mut self) -> Builder {
+ self.options.disable_name_namespacing = true;
+ self
+ }
+ },
+ as_args: "--disable-name-namespacing",
+ },
+ /// Whether we should avoid generating nested `struct` names.
+ disable_nested_struct_naming: bool {
+ methods: {
+ /// Disable nested `struct` naming.
+ ///
+ /// The following `struct`s have different names for C and C++. In C, they are visible
+ /// as `foo` and `bar`. In C++, they are visible as `foo` and `foo::bar`.
+ ///
+ /// ```c
+ /// struct foo {
+ /// struct bar {
+ /// } b;
+ /// };
+ /// ```
+ ///
+ /// `bindgen` tries to avoid duplicate names by default, so it follows the C++ naming
+ /// convention and it generates `foo` and `foo_bar` instead of just `foo` and `bar`.
+ ///
+ /// This method disables this behavior and it is indented to be used only for headers
+ /// that were written in C.
+ pub fn disable_nested_struct_naming(mut self) -> Builder {
+ self.options.disable_nested_struct_naming = true;
+ self
+ }
+ },
+ as_args: "--disable-nested-struct-naming",
+ },
+ /// Whether we should avoid embedding version identifiers into source code.
+ disable_header_comment: bool {
+ methods: {
+ /// Do not insert the `bindgen` version identifier into the generated bindings.
+ ///
+ /// This identifier is inserted by default.
+ pub fn disable_header_comment(mut self) -> Self {
+ self.options.disable_header_comment = true;
+ self
+ }
+
+ },
+ as_args: "--disable-header-comment",
+ },
+ /// Whether we should generate layout tests for generated `struct`s.
+ layout_tests: bool {
+ default: true,
+ methods: {
+ /// Set whether layout tests should be generated.
+ ///
+ /// Layout tests are generated by default.
+ pub fn layout_tests(mut self, doit: bool) -> Self {
+ self.options.layout_tests = doit;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-layout-tests"),
+ },
+ /// Whether we should implement `Debug` for types that cannot derive it.
+ impl_debug: bool {
+ methods: {
+ /// Set whether `Debug` should be implemented for types that cannot derive it.
+ ///
+ /// This option is disabled by default.
+ pub fn impl_debug(mut self, doit: bool) -> Self {
+ self.options.impl_debug = doit;
+ self
+ }
+
+ },
+ as_args: "--impl-debug",
+ },
+ /// Whether we should implement `PartialEq` types that cannot derive it.
+ impl_partialeq: bool {
+ methods: {
+ /// Set whether `PartialEq` should be implemented for types that cannot derive it.
+ ///
+ /// This option is disabled by default.
+ pub fn impl_partialeq(mut self, doit: bool) -> Self {
+ self.options.impl_partialeq = doit;
+ self
+ }
+ },
+ as_args: "--impl-partialeq",
+ },
+ /// Whether we should derive `Copy` when possible.
+ derive_copy: bool {
+ default: true,
+ methods: {
+ /// Set whether the `Copy` trait should be derived when possible.
+ ///
+ /// `Copy` is derived by default.
+ pub fn derive_copy(mut self, doit: bool) -> Self {
+ self.options.derive_copy = doit;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-derive-copy"),
+ },
+
+ /// Whether we should derive `Debug` when possible.
+ derive_debug: bool {
+ default: true,
+ methods: {
+ /// Set whether the `Debug` trait should be derived when possible.
+ ///
+ /// The [`Builder::impl_debug`] method can be used to implement `Debug` for types that
+ /// cannot derive it.
+ ///
+ /// `Debug` is derived by default.
+ pub fn derive_debug(mut self, doit: bool) -> Self {
+ self.options.derive_debug = doit;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-derive-debug"),
+ },
+
+ /// Whether we should derive `Default` when possible.
+ derive_default: bool {
+ methods: {
+ /// Set whether the `Default` trait should be derived when possible.
+ ///
+ /// `Default` is not derived by default.
+ pub fn derive_default(mut self, doit: bool) -> Self {
+ self.options.derive_default = doit;
+ self
+ }
+ },
+ as_args: |&value, args| {
+ let arg = if value {
+ "--with-derive-default"
+ } else {
+ "--no-derive-default"
+ };
+
+ args.push(arg.to_owned());
+ },
+ },
+ /// Whether we should derive `Hash` when possible.
+ derive_hash: bool {
+ methods: {
+ /// Set whether the `Hash` trait should be derived when possible.
+ ///
+ /// `Hash` is not derived by default.
+ pub fn derive_hash(mut self, doit: bool) -> Self {
+ self.options.derive_hash = doit;
+ self
+ }
+ },
+ as_args: "--with-derive-hash",
+ },
+ /// Whether we should derive `PartialOrd` when possible.
+ derive_partialord: bool {
+ methods: {
+ /// Set whether the `PartialOrd` trait should be derived when possible.
+ ///
+ /// Take into account that `Ord` cannot be derived for a type that does not implement
+ /// `PartialOrd`. For this reason, setting this method to `false` also sets
+ /// automatically [`Builder::derive_ord`] to `false`.
+ ///
+ /// `PartialOrd` is not derived by default.
+ pub fn derive_partialord(mut self, doit: bool) -> Self {
+ self.options.derive_partialord = doit;
+ if !doit {
+ self.options.derive_ord = false;
+ }
+ self
+ }
+ },
+ as_args: "--with-derive-partialord",
+ },
+ /// Whether we should derive `Ord` when possible.
+ derive_ord: bool {
+ methods: {
+ /// Set whether the `Ord` trait should be derived when possible.
+ ///
+ /// Take into account that `Ord` cannot be derived for a type that does not implement
+ /// `PartialOrd`. For this reason, the value set with this method will also be set
+ /// automatically for [`Builder::derive_partialord`].
+ ///
+ /// `Ord` is not derived by default.
+ pub fn derive_ord(mut self, doit: bool) -> Self {
+ self.options.derive_ord = doit;
+ self.options.derive_partialord = doit;
+ self
+ }
+ },
+ as_args: "--with-derive-ord",
+ },
+ /// Whether we should derive `PartialEq` when possible.
+ derive_partialeq: bool {
+ methods: {
+ /// Set whether the `PartialEq` trait should be derived when possible.
+ ///
+ /// Take into account that `Eq` cannot be derived for a type that does not implement
+ /// `PartialEq`. For this reason, setting this method to `false` also sets
+ /// automatically [`Builder::derive_eq`] to `false`.
+ ///
+ /// The [`Builder::impl_partialeq`] method can be used to implement `PartialEq` for
+ /// types that cannot derive it.
+ ///
+ /// `PartialEq` is not derived by default.
+ pub fn derive_partialeq(mut self, doit: bool) -> Self {
+ self.options.derive_partialeq = doit;
+ if !doit {
+ self.options.derive_eq = false;
+ }
+ self
+ }
+ },
+ as_args: "--with-derive-partialeq",
+ },
+ /// Whether we should derive `Eq` when possible.
+ derive_eq: bool {
+ methods: {
+ /// Set whether the `Eq` trait should be derived when possible.
+ ///
+ /// Take into account that `Eq` cannot be derived for a type that does not implement
+ /// `PartialEq`. For this reason, the value set with this method will also be set
+ /// automatically for [`Builder::derive_partialeq`].
+ ///
+ /// `Eq` is not derived by default.
+ pub fn derive_eq(mut self, doit: bool) -> Self {
+ self.options.derive_eq = doit;
+ if doit {
+ self.options.derive_partialeq = doit;
+ }
+ self
+ }
+ },
+ as_args: "--with-derive-eq",
+ },
+ /// Whether we should use `core` instead of `std`.
+ ///
+ /// If this option is enabled and the Rust target version is greater than 1.64, the prefix for
+ /// C platform-specific types will be `::core::ffi` instead of `::core::os::raw`.
+ use_core: bool {
+ methods: {
+ /// Use `core` instead of `std` in the generated bindings.
+ ///
+ /// `std` is used by default.
+ pub fn use_core(mut self) -> Builder {
+ self.options.use_core = true;
+ self
+ }
+
+ },
+ as_args: "--use-core",
+ },
+ /// An optional prefix for the C platform-specific types.
+ ctypes_prefix: Option<String> {
+ methods: {
+ /// Use the given prefix for the C platform-specific types instead of `::std::os::raw`.
+ ///
+ /// Alternatively, the [`Builder::use_core`] method can be used to set the prefix to
+ /// `::core::ffi` or `::core::os::raw`.
+ pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
+ self.options.ctypes_prefix = Some(prefix.into());
+ self
+ }
+ },
+ as_args: "--ctypes-prefix",
+ },
+ /// The prefix for anonymous fields.
+ anon_fields_prefix: String {
+ default: DEFAULT_ANON_FIELDS_PREFIX.into(),
+ methods: {
+ /// Use the given prefix for the anonymous fields.
+ ///
+ /// An anonymous field, is a field of a C/C++ type that does not have a name. For
+ /// example, in the following C code:
+ /// ```c
+ /// struct integer {
+ /// struct {
+ /// int inner;
+ /// };
+ /// }
+ /// ```
+ ///
+ /// The only field of the `integer` `struct` is an anonymous field and its Rust
+ /// representation will be named using this prefix followed by an integer identifier.
+ ///
+ /// The default prefix is `__bindgen_anon_`.
+ pub fn anon_fields_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
+ self.options.anon_fields_prefix = prefix.into();
+ self
+ }
+ },
+ as_args: |prefix, args| {
+ if prefix != DEFAULT_ANON_FIELDS_PREFIX {
+ args.push("--anon-fields-prefix".to_owned());
+ args.push(prefix.clone());
+ }
+ },
+ },
+ /// Whether to measure the time for each one of the `bindgen` phases.
+ time_phases: bool {
+ methods: {
+ /// Set whether to measure the elapsed time for each one of the `bindgen` phases. This
+ /// information is printed to `stderr`.
+ ///
+ /// The elapsed time is not measured by default.
+ pub fn time_phases(mut self, doit: bool) -> Self {
+ self.options.time_phases = doit;
+ self
+ }
+ },
+ as_args: "--time-phases",
+ },
+ /// Whether to convert C float types to `f32` and `f64`.
+ convert_floats: bool {
+ default: true,
+ methods: {
+ /// Avoid converting C float types to `f32` and `f64`.
+ pub fn no_convert_floats(mut self) -> Self {
+ self.options.convert_floats = false;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-convert-floats"),
+ },
+ /// The set of raw lines to be prepended to the top-level module of the generated Rust code.
+ raw_lines: Vec<String> {
+ methods: {
+ /// Add a line of Rust code at the beginning of the generated bindings. The string is
+ /// passed through without any modification.
+ pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
+ self.options.raw_lines.push(arg.into());
+ self
+ }
+ },
+ as_args: |raw_lines, args| {
+ for line in raw_lines {
+ args.push("--raw-line".to_owned());
+ args.push(line.clone());
+ }
+ },
+ },
+ /// The set of raw lines to prepend to different modules.
+ module_lines: HashMap<String, Vec<String>> {
+ methods: {
+ /// Add a given line to the beginning of a given module.
+ ///
+ /// This option only comes into effect if the [`Builder::enable_cxx_namespaces`] method
+ /// is also being called.
+ pub fn module_raw_line<T, U>(mut self, module: T, line: U) -> Self
+ where
+ T: Into<String>,
+ U: Into<String>,
+ {
+ self.options
+ .module_lines
+ .entry(module.into())
+ .or_insert_with(Vec::new)
+ .push(line.into());
+ self
+ }
+ },
+ as_args: |module_lines, args| {
+ for (module, lines) in module_lines {
+ for line in lines.iter() {
+ args.push("--module-raw-line".to_owned());
+ args.push(module.clone());
+ args.push(line.clone());
+ }
+ }
+ },
+ },
+ /// The input header files.
+ input_headers: Vec<String> {
+ methods: {
+ /// Add an input C/C++ header to generate bindings for.
+ ///
+ /// This can be used to generate bindings for a single header:
+ ///
+ /// ```ignore
+ /// let bindings = bindgen::Builder::default()
+ /// .header("input.h")
+ /// .generate()
+ /// .unwrap();
+ /// ```
+ ///
+ /// Or for multiple headers:
+ ///
+ /// ```ignore
+ /// let bindings = bindgen::Builder::default()
+ /// .header("first.h")
+ /// .header("second.h")
+ /// .header("third.h")
+ /// .generate()
+ /// .unwrap();
+ /// ```
+ pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
+ self.options.input_headers.push(header.into());
+ self
+ }
+ },
+ // This field is handled specially inside the macro.
+ as_args: ignore,
+ },
+ /// The set of arguments to be passed straight through to Clang.
+ clang_args: Vec<String> {
+ methods: {
+ /// Add an argument to be passed straight through to Clang.
+ pub fn clang_arg<T: Into<String>>(self, arg: T) -> Builder {
+ self.clang_args([arg.into()])
+ }
+
+ /// Add several arguments to be passed straight through to Clang.
+ pub fn clang_args<I: IntoIterator>(mut self, args: I) -> Builder
+ where
+ I::Item: AsRef<str>,
+ {
+ for arg in args {
+ self.options.clang_args.push(arg.as_ref().to_owned());
+ }
+ self
+ }
+ },
+ // This field is handled specially inside the macro.
+ as_args: ignore,
+ },
+ /// Tuples of unsaved file contents of the form (name, contents).
+ input_header_contents: Vec<(String, String)> {
+ methods: {
+ /// Add `contents` as an input C/C++ header named `name`.
+ ///
+ /// This can be used to inject additional C/C++ code as an input without having to
+ /// create additional header files.
+ pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
+ // Apparently clang relies on having virtual FS correspondent to
+ // the real one, so we need absolute paths here
+ let absolute_path = env::current_dir()
+ .expect("Cannot retrieve current directory")
+ .join(name)
+ .to_str()
+ .expect("Cannot convert current directory name to string")
+ .to_owned();
+ self.options
+ .input_header_contents
+ .push((absolute_path, contents.into()));
+ self
+ }
+ },
+ // Header contents cannot be added from the CLI.
+ as_args: ignore,
+ },
+ /// A user-provided visitor to allow customizing different kinds of situations.
+ parse_callbacks: Vec<Rc<dyn ParseCallbacks>> {
+ methods: {
+ /// Add a new [`ParseCallbacks`] instance to configure types in different situations.
+ pub fn parse_callbacks(mut self, cb: Box<dyn ParseCallbacks>) -> Self {
+ self.options.parse_callbacks.push(Rc::from(cb));
+ self
+ }
+ },
+ as_args: |_callbacks, _args| {
+ #[cfg(feature = "__cli")]
+ for cb in _callbacks {
+ _args.extend(cb.cli_args());
+ }
+ },
+ },
+ /// Which kind of items should we generate. We generate all of them by default.
+ codegen_config: CodegenConfig {
+ default: CodegenConfig::all(),
+ methods: {
+ /// Do not generate any functions.
+ ///
+ /// Functions are generated by default.
+ pub fn ignore_functions(mut self) -> Builder {
+ self.options.codegen_config.remove(CodegenConfig::FUNCTIONS);
+ self
+ }
+
+ /// Do not generate any methods.
+ ///
+ /// Methods are generated by default.
+ pub fn ignore_methods(mut self) -> Builder {
+ self.options.codegen_config.remove(CodegenConfig::METHODS);
+ self
+ }
+
+ /// Choose what to generate using a [`CodegenConfig`].
+ ///
+ /// This option overlaps with [`Builder::ignore_functions`] and
+ /// [`Builder::ignore_methods`].
+ ///
+ /// All the items in `CodegenConfig` are generated by default.
+ pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self {
+ self.options.codegen_config = config;
+ self
+ }
+ },
+ as_args: |codegen_config, args| {
+ if !codegen_config.functions() {
+ args.push("--ignore-functions".to_owned());
+ }
+
+ args.push("--generate".to_owned());
+
+ //Temporary placeholder for the 4 options below.
+ let mut options: Vec<String> = Vec::new();
+ if codegen_config.functions() {
+ options.push("functions".to_owned());
+ }
+
+ if codegen_config.types() {
+ options.push("types".to_owned());
+ }
+
+ if codegen_config.vars() {
+ options.push("vars".to_owned());
+ }
+
+ if codegen_config.methods() {
+ options.push("methods".to_owned());
+ }
+
+ if codegen_config.constructors() {
+ options.push("constructors".to_owned());
+ }
+
+ if codegen_config.destructors() {
+ options.push("destructors".to_owned());
+ }
+
+ args.push(options.join(","));
+
+ if !codegen_config.methods() {
+ args.push("--ignore-methods".to_owned());
+ }
+ },
+ },
+ /// Whether to treat inline namespaces conservatively.
+ conservative_inline_namespaces: bool {
+ methods: {
+ /// Treat inline namespaces conservatively.
+ ///
+ /// This is tricky, because in C++ is technically legal to override an item
+ /// defined in an inline namespace:
+ ///
+ /// ```cpp
+ /// inline namespace foo {
+ /// using Bar = int;
+ /// }
+ /// using Bar = long;
+ /// ```
+ ///
+ /// Even though referencing `Bar` is a compiler error.
+ ///
+ /// We want to support this (arguably esoteric) use case, but we do not want to make
+ /// the rest of `bindgen` users pay an usability penalty for that.
+ ///
+ /// To support this, we need to keep all the inline namespaces around, but then using
+ /// `bindgen` becomes a bit more difficult, because you cannot reference paths like
+ /// `std::string` (you'd need to use the proper inline namespace).
+ ///
+ /// We could complicate a lot of the logic to detect name collisions and, in the
+ /// absence of collisions, generate a `pub use inline_ns::*` or something like that.
+ ///
+ /// That is probably something we can do to improve the usability of this option if we
+ /// realize it is needed way more often. Our guess is that this extra logic is not
+ /// going to be very useful.
+ ///
+ /// This option is disabled by default.
+ pub fn conservative_inline_namespaces(mut self) -> Builder {
+ self.options.conservative_inline_namespaces = true;
+ self
+ }
+ },
+ as_args: "--conservative-inline-namespaces",
+ },
+ /// Whether to keep documentation comments in the generated output.
+ generate_comments: bool {
+ default: true,
+ methods: {
+ /// Set whether the generated bindings should contain documentation comments.
+ ///
+ /// Documentation comments are included by default.
+ ///
+ /// Note that clang excludes comments from system headers by default, pass
+ /// `"-fretain-comments-from-system-headers"` to the [`Builder::clang_arg`] method to
+ /// include them.
+ ///
+ /// It is also possible to process all comments and not just documentation using the
+ /// `"-fparse-all-comments"` flag. Check [these slides on clang comment parsing](
+ /// https://llvm.org/devmtg/2012-11/Gribenko_CommentParsing.pdf) for more information
+ /// and examples.
+ pub fn generate_comments(mut self, doit: bool) -> Self {
+ self.options.generate_comments = doit;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-doc-comments"),
+ },
+ /// Whether to generate inline functions.
+ generate_inline_functions: bool {
+ methods: {
+ /// Set whether to generate inline functions.
+ ///
+ /// This option is disabled by default.
+ ///
+ /// 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.
+ #[cfg_attr(
+ features = "experimental",
+ doc = "\nCheck the [`Builder::wrap_static_fns`] method for an alternative."
+ )]
+ pub fn generate_inline_functions(mut self, doit: bool) -> Self {
+ self.options.generate_inline_functions = doit;
+ self
+ }
+ },
+ as_args: "--generate-inline-functions",
+ },
+ /// Whether to allowlist types recursively.
+ allowlist_recursively: bool {
+ default: true,
+ methods: {
+ /// Set whether to recursively allowlist items.
+ ///
+ /// Items are allowlisted recursively by default.
+ ///
+ /// Given that we have explicitly allowlisted the `initiate_dance_party` function in
+ /// this C header:
+ ///
+ /// ```c
+ /// typedef struct MoonBoots {
+ /// int bouncy_level;
+ /// } MoonBoots;
+ ///
+ /// void initiate_dance_party(MoonBoots* boots);
+ /// ```
+ ///
+ /// We would normally generate bindings to both the `initiate_dance_party` function and
+ /// the `MoonBoots` type that it transitively references. If `false` is passed to this
+ /// method, `bindgen` will not emit bindings for anything except the explicitly
+ /// allowlisted items, meaning that the definition for `MoonBoots` would not be
+ /// generated. However, the `initiate_dance_party` function would still reference
+ /// `MoonBoots`!
+ ///
+ /// **Disabling this feature will almost certainly cause `bindgen` to emit bindings
+ /// that will not compile!** If you disable this feature, then it is *your*
+ /// responsibility to provide definitions for every type that is referenced from an
+ /// explicitly allowlisted item. One way to provide the missing definitions is by using
+ /// the [`Builder::raw_line`] method, another would be to define them in Rust and then
+ /// `include!(...)` the bindings immediately afterwards.
+ pub fn allowlist_recursively(mut self, doit: bool) -> Self {
+ self.options.allowlist_recursively = doit;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-recursive-allowlist"),
+ },
+ /// Whether to emit `#[macro_use] extern crate objc;` instead of `use objc;` in the prologue of
+ /// the files generated from objective-c files.
+ objc_extern_crate: bool {
+ methods: {
+ /// Emit `#[macro_use] extern crate objc;` instead of `use objc;` in the prologue of
+ /// the files generated from objective-c files.
+ ///
+ /// `use objc;` is emitted by default.
+ pub fn objc_extern_crate(mut self, doit: bool) -> Self {
+ self.options.objc_extern_crate = doit;
+ self
+ }
+ },
+ as_args: "--objc-extern-crate",
+ },
+ /// Whether to generate proper block signatures instead of `void` pointers.
+ generate_block: bool {
+ methods: {
+ /// Generate proper block signatures instead of `void` pointers.
+ ///
+ /// `void` pointers are used by default.
+ pub fn generate_block(mut self, doit: bool) -> Self {
+ self.options.generate_block = doit;
+ self
+ }
+ },
+ as_args: "--generate-block",
+ },
+ /// Whether to emit `#[macro_use] extern crate block;` instead of `use block;` in the prologue
+ /// of the files generated from apple block files.
+ block_extern_crate: bool {
+ methods: {
+ /// Emit `#[macro_use] extern crate block;` instead of `use block;` in the prologue of
+ /// the files generated from apple block files.
+ ///
+ /// `use block;` is emitted by default.
+ pub fn block_extern_crate(mut self, doit: bool) -> Self {
+ self.options.block_extern_crate = doit;
+ self
+ }
+ },
+ as_args: "--block-extern-crate",
+ },
+ /// Whether to use the clang-provided name mangling.
+ enable_mangling: bool {
+ default: true,
+ methods: {
+ /// Set whether to use the clang-provided name mangling. This is probably needed for
+ /// C++ features.
+ ///
+ /// The mangling provided by clang is used by default.
+ ///
+ /// We allow disabling this option because some old `libclang` versions seem to return
+ /// incorrect results in some cases for non-mangled functions, check [#528] for more
+ /// information.
+ ///
+ /// [#528]: https://github.com/rust-lang/rust-bindgen/issues/528
+ pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
+ self.options.enable_mangling = doit;
+ self
+ }
+
+ },
+ as_args: |value, args| (!value).as_args(args, "--distrust-clang-mangling"),
+ },
+ /// Whether to detect include paths using `clang_sys`.
+ detect_include_paths: bool {
+ default: true,
+ methods: {
+ /// Set whether to detect include paths using `clang_sys`.
+ ///
+ /// `clang_sys` is used to detect include paths by default.
+ pub fn detect_include_paths(mut self, doit: bool) -> Self {
+ self.options.detect_include_paths = doit;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-include-path-detection"),
+ },
+ /// Whether we should try to fit macro constants into types smaller than `u32` and `i32`.
+ fit_macro_constants: bool {
+ methods: {
+ /// Set whether `bindgen` should try to fit macro constants into types smaller than `u32`
+ /// and `i32`.
+ ///
+ /// This option is disabled by default.
+ pub fn fit_macro_constants(mut self, doit: bool) -> Self {
+ self.options.fit_macro_constants = doit;
+ self
+ }
+ },
+ as_args: "--fit-macro-constant-types",
+ },
+ /// Whether to prepend the `enum` name to constant or newtype variants.
+ prepend_enum_name: bool {
+ default: true,
+ methods: {
+ /// Set whether to prepend the `enum` name to constant or newtype variants.
+ ///
+ /// The `enum` name is prepended by default.
+ pub fn prepend_enum_name(mut self, doit: bool) -> Self {
+ self.options.prepend_enum_name = doit;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-prepend-enum-name"),
+ },
+ /// Version of the Rust compiler to target.
+ rust_target: RustTarget {
+ methods: {
+ /// Specify the Rust target version.
+ ///
+ /// The default target is the latest stable Rust version.
+ pub fn rust_target(mut self, rust_target: RustTarget) -> Self {
+ self.options.set_rust_target(rust_target);
+ self
+ }
+ },
+ as_args: |rust_target, args| {
+ args.push("--rust-target".to_owned());
+ args.push((*rust_target).into());
+ },
+ },
+ /// Features to be enabled. They are derived from `rust_target`.
+ rust_features: RustFeatures {
+ default: RustTarget::default().into(),
+ methods: {},
+ // This field cannot be set from the CLI,
+ as_args: ignore,
+ },
+ /// Enable support for native Rust unions if they are supported.
+ untagged_union: bool {
+ default: true,
+ methods: {
+ /// Disable support for native Rust unions, if supported.
+ ///
+ /// The default value of this option is set based on the value passed to
+ /// [`Builder::rust_target`].
+ pub fn disable_untagged_union(mut self) -> Self {
+ self.options.untagged_union = false;
+ self
+ }
+ }
+ as_args: |value, args| (!value).as_args(args, "--disable-untagged-union"),
+ },
+ /// Whether we should record which items in the regex sets did match any C items.
+ record_matches: bool {
+ default: true,
+ methods: {
+ /// Set whether we should record which items in our regex sets did match any C items.
+ ///
+ /// Matches are recorded by default.
+ pub fn record_matches(mut self, doit: bool) -> Self {
+ self.options.record_matches = doit;
+ self
+ }
+
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-record-matches"),
+ },
+ /// Whether `size_t` should be translated to `usize` automatically.
+ size_t_is_usize: bool {
+ default: true,
+ methods: {
+ /// Set whether `size_t` should be translated to `usize`.
+ ///
+ /// `size_t` is translated to `usize` by default.
+ pub fn size_t_is_usize(mut self, is: bool) -> Self {
+ self.options.size_t_is_usize = is;
+ self
+ }
+ },
+ as_args: |value, args| (!value).as_args(args, "--no-size_t-is-usize"),
+ },
+ /// The tool that should be used to format the generated bindings.
+ formatter: Formatter {
+ methods: {
+ /// Set whether `rustfmt` should be used to format the generated bindings.
+ ///
+ /// `rustfmt` is used by default.
+ ///
+ /// This method overlaps in functionality with the more general [`Builder::formatter`].
+ /// Thus, the latter should be preferred.
+ #[deprecated]
+ pub fn rustfmt_bindings(mut self, doit: bool) -> Self {
+ self.options.formatter = if doit {
+ Formatter::Rustfmt
+ } else {
+ Formatter::None
+ };
+ self
+ }
+
+ /// Set which tool should be used to format the generated bindings.
+ ///
+ /// The default formatter is [`Formatter::Rustfmt`].
+ ///
+ /// To be able to use `prettyplease` as a formatter, the `"prettyplease"` feature for
+ /// `bindgen` must be enabled in the Cargo manifest.
+ pub fn formatter(mut self, formatter: Formatter) -> Self {
+ self.options.formatter = formatter;
+ self
+ }
+ },
+ as_args: |formatter, args| {
+ if *formatter != Default::default() {
+ args.push("--formatter".to_owned());
+ args.push(formatter.to_string());
+ }
+ },
+ },
+ /// The absolute path to the `rustfmt` configuration file.
+ rustfmt_configuration_file: Option<PathBuf> {
+ methods: {
+ /// Set the absolute path to the `rustfmt` configuration file.
+ ///
+ /// The default `rustfmt` options are used if `None` is passed to this method or if
+ /// this method is not called at all.
+ ///
+ /// Calling this method will set the [`Builder::rustfmt_bindings`] option to `true`
+ /// and the [`Builder::formatter`] option to [`Formatter::Rustfmt`].
+ pub fn rustfmt_configuration_file(mut self, path: Option<PathBuf>) -> Self {
+ self = self.formatter(Formatter::Rustfmt);
+ self.options.rustfmt_configuration_file = path;
+ self
+ }
+ },
+ as_args: "--rustfmt-configuration-file",
+ },
+ /// Types that should not derive `PartialEq`.
+ no_partialeq_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not derive `PartialEq` for a given type.
+ pub fn no_partialeq<T: Into<String>>(mut self, arg: T) -> Builder {
+ self.options.no_partialeq_types.insert(arg.into());
+ self
+ }
+ }
+ },
+ as_args: "--no-partialeq",
+ },
+ /// Types that should not derive `Copy`.
+ no_copy_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not derive `Copy` and `Clone` for a given type.
+ pub fn no_copy<T: Into<String>>(mut self, arg: T) -> Self {
+ self.options.no_copy_types.insert(arg.into());
+ self
+ }
+ }
+ },
+ as_args: "--no-copy",
+ },
+ /// Types that should not derive `Debug`.
+ no_debug_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not derive `Debug` for a given type.
+ pub fn no_debug<T: Into<String>>(mut self, arg: T) -> Self {
+ self.options.no_debug_types.insert(arg.into());
+ self
+ }
+ }
+ },
+ as_args: "--no-debug",
+ },
+ /// Types that should not derive or implement `Default`.
+ no_default_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not derive or implement `Default` for a given type.
+ pub fn no_default<T: Into<String>>(mut self, arg: T) -> Self {
+ self.options.no_default_types.insert(arg.into());
+ self
+ }
+ }
+ },
+ as_args: "--no-default",
+ },
+ /// Types that should not derive `Hash`.
+ no_hash_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Do not derive `Hash` for a given type.
+ pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder {
+ self.options.no_hash_types.insert(arg.into());
+ self
+ }
+ }
+ },
+ as_args: "--no-hash",
+ },
+ /// Types that should be annotated with `#[must_use]`.
+ must_use_types: RegexSet {
+ methods: {
+ regex_option! {
+ /// Annotate the given type with the `#[must_use]` attribute.
+ pub fn must_use_type<T: Into<String>>(mut self, arg: T) -> Builder {
+ self.options.must_use_types.insert(arg.into());
+ self
+ }
+ }
+ },
+ as_args: "--must-use-type",
+ },
+ /// Whether C arrays should be regular pointers in rust or array pointers
+ array_pointers_in_arguments: bool {
+ methods: {
+ /// Translate arrays `T arr[size]` into array pointers `*mut [T; size]` instead of
+ /// translating them as `*mut T` which is the default.
+ ///
+ /// The same is done for `*const` pointers.
+ pub fn array_pointers_in_arguments(mut self, doit: bool) -> Self {
+ self.options.array_pointers_in_arguments = doit;
+ self
+ }
+
+ },
+ as_args: "--use-array-pointers-in-arguments",
+ },
+ /// The name of the `wasm_import_module`.
+ wasm_import_module_name: Option<String> {
+ methods: {
+ /// Adds the `#[link(wasm_import_module = import_name)]` attribute to all the `extern`
+ /// blocks generated by `bindgen`.
+ ///
+ /// This attribute is not added by default.
+ pub fn wasm_import_module_name<T: Into<String>>(
+ mut self,
+ import_name: T,
+ ) -> Self {
+ self.options.wasm_import_module_name = Some(import_name.into());
+ self
+ }
+ },
+ as_args: "--wasm-import-module-name",
+ },
+ /// The name of the dynamic library (if we are generating bindings for a shared library).
+ dynamic_library_name: Option<String> {
+ methods: {
+ /// Generate bindings for a shared library with the given name.
+ ///
+ /// This option is disabled by default.
+ pub fn dynamic_library_name<T: Into<String>>(
+ mut self,
+ dynamic_library_name: T,
+ ) -> Self {
+ self.options.dynamic_library_name = Some(dynamic_library_name.into());
+ self
+ }
+ },
+ as_args: "--dynamic-loading",
+ },
+ /// Whether to equire successful linkage for all routines in a shared library.
+ dynamic_link_require_all: bool {
+ methods: {
+ /// Set whether to require successful linkage for all routines in a shared library.
+ /// This allows us to optimize function calls by being able to safely assume function
+ /// pointers are valid.
+ ///
+ /// This option only comes into effect if the [`Builder::dynamic_library_name`] option
+ /// is set.
+ ///
+ /// This option is disabled by default.
+ pub fn dynamic_link_require_all(mut self, req: bool) -> Self {
+ self.options.dynamic_link_require_all = req;
+ self
+ }
+ },
+ as_args: "--dynamic-link-require-all",
+ },
+ /// Whether to only make generated bindings `pub` if the items would be publicly accessible by
+ /// C++.
+ respect_cxx_access_specs: bool {
+ methods: {
+ /// Set whether to respect the C++ access specifications.
+ ///
+ /// Passing `true` to this method will set the visibility of the generated Rust items
+ /// as `pub` only if the corresponding C++ items are publicly accessible instead of
+ /// marking all the items as public, which is the default.
+ pub fn respect_cxx_access_specs(mut self, doit: bool) -> Self {
+ self.options.respect_cxx_access_specs = doit;
+ self
+ }
+
+ },
+ as_args: "--respect-cxx-access-specs",
+ },
+ /// Whether to translate `enum` integer types to native Rust integer types.
+ translate_enum_integer_types: bool {
+ methods: {
+ /// Set whether to always translate `enum` integer types to native Rust integer types.
+ ///
+ /// Passing `true` to this method will result in `enum`s having types such as `u32` and
+ /// `i16` instead of `c_uint` and `c_short` which is the default. The `#[repr]` types
+ /// of Rust `enum`s are always translated to Rust integer types.
+ pub fn translate_enum_integer_types(mut self, doit: bool) -> Self {
+ self.options.translate_enum_integer_types = doit;
+ self
+ }
+ },
+ as_args: "--translate-enum-integer-types",
+ },
+ /// Whether to generate types with C style naming.
+ c_naming: bool {
+ methods: {
+ /// Set whether to generate types with C style naming.
+ ///
+ /// Passing `true` to this method will add prefixes to the generated type names. For
+ /// example, instead of a `struct` with name `A` we will generate a `struct` with
+ /// `struct_A`. Currently applies to `struct`s, `union`s, and `enum`s.
+ pub fn c_naming(mut self, doit: bool) -> Self {
+ self.options.c_naming = doit;
+ self
+ }
+ },
+ as_args: "--c-naming",
+ },
+ /// Wether to always emit explicit padding fields.
+ force_explicit_padding: bool {
+ methods: {
+ /// Set whether to always emit explicit padding fields.
+ ///
+ /// This option should be enabled if a `struct` needs to be serialized in its native
+ /// format (padding bytes and all). This could be required if such `struct` will be
+ /// written to a file or sent over the network, as anything reading the padding bytes
+ /// of a struct may cause undefined behavior.
+ ///
+ /// Padding fields are not emitted by default.
+ pub fn explicit_padding(mut self, doit: bool) -> Self {
+ self.options.force_explicit_padding = doit;
+ self
+ }
+ },
+ as_args: "--explicit-padding",
+ },
+ /// Whether to emit vtable functions.
+ vtable_generation: bool {
+ methods: {
+ /// Set whether to enable experimental support to generate virtual table functions.
+ ///
+ /// This option should mostly work, though some edge cases are likely to be broken.
+ ///
+ /// Virtual table generation is disabled by default.
+ pub fn vtable_generation(mut self, doit: bool) -> Self {
+ self.options.vtable_generation = doit;
+ self
+ }
+ },
+ as_args: "--vtable-generation",
+ },
+ /// Whether to sort the generated Rust items.
+ sort_semantically: bool {
+ methods: {
+ /// Set whether to sort the generated Rust items in a predefined manner.
+ ///
+ /// Items are not ordered by default.
+ pub fn sort_semantically(mut self, doit: bool) -> Self {
+ self.options.sort_semantically = doit;
+ self
+ }
+ },
+ as_args: "--sort-semantically",
+ },
+ /// Whether to deduplicate `extern` blocks.
+ merge_extern_blocks: bool {
+ methods: {
+ /// Merge all extern blocks under the same module into a single one.
+ ///
+ /// Extern blocks are not merged by default.
+ pub fn merge_extern_blocks(mut self, doit: bool) -> Self {
+ self.options.merge_extern_blocks = doit;
+ self
+ }
+ },
+ as_args: "--merge-extern-blocks",
+ },
+ /// Whether to wrap unsafe operations in unsafe blocks.
+ wrap_unsafe_ops: bool {
+ methods: {
+ /// Wrap all unsafe operations in unsafe blocks.
+ ///
+ /// Unsafe operations are not wrapped by default.
+ pub fn wrap_unsafe_ops(mut self, doit: bool) -> Self {
+ self.options.wrap_unsafe_ops = doit;
+ self
+ }
+ },
+ as_args: "--wrap-unsafe-ops",
+ },
+ /// Patterns for functions whose ABI should be overriden.
+ abi_overrides: HashMap<Abi, RegexSet> {
+ methods: {
+ regex_option! {
+ /// Override the ABI of a given function.
+ pub fn override_abi<T: Into<String>>(mut self, abi: Abi, arg: T) -> Self {
+ self.options
+ .abi_overrides
+ .entry(abi)
+ .or_default()
+ .insert(arg.into());
+ self
+ }
+ }
+ },
+ as_args: |overrides, args| {
+ for (abi, set) in overrides {
+ for item in set.get_items() {
+ args.push("--override-abi".to_owned());
+ args.push(format!("{}={}", item, abi));
+ }
+ }
+ },
+ },
+ /// Whether to generate wrappers for `static` functions.
+ wrap_static_fns: bool {
+ methods: {
+ #[cfg(feature = "experimental")]
+ /// Set whether to generate wrappers for `static`` functions.
+ ///
+ /// Passing `true` to this method will generate a C source file with non-`static`
+ /// functions that call the `static` functions found in the input headers and can be
+ /// called from Rust once the source file is compiled.
+ ///
+ /// The path of this source file can be set using the [`Builder::wrap_static_fns_path`]
+ /// method.
+ pub fn wrap_static_fns(mut self, doit: bool) -> Self {
+ self.options.wrap_static_fns = doit;
+ self
+ }
+ },
+ as_args: "--wrap-static-fns",
+ },
+ /// The suffix to be added to the function wrappers for `static` functions.
+ wrap_static_fns_suffix: Option<String> {
+ methods: {
+ #[cfg(feature = "experimental")]
+ /// Set the suffix added to the wrappers for `static` functions.
+ ///
+ /// This option only comes into effect if `true` is passed to the
+ /// [`Builder::wrap_static_fns`] method.
+ ///
+ /// The default suffix is `__extern`.
+ pub fn wrap_static_fns_suffix<T: AsRef<str>>(mut self, suffix: T) -> Self {
+ self.options.wrap_static_fns_suffix = Some(suffix.as_ref().to_owned());
+ self
+ }
+ },
+ as_args: "--wrap-static-fns-suffix",
+ },
+ /// The path of the file where the wrappers for `static` functions will be emitted.
+ wrap_static_fns_path: Option<PathBuf> {
+ methods: {
+ #[cfg(feature = "experimental")]
+ /// Set the path for the source code file that would be created if any wrapper
+ /// functions must be generated due to the presence of `static` functions.
+ ///
+ /// `bindgen` will automatically add the right extension to the header and source code
+ /// files.
+ ///
+ /// This option only comes into effect if `true` is passed to the
+ /// [`Builder::wrap_static_fns`] method.
+ ///
+ /// The default path is `temp_dir/bindgen/extern`, where `temp_dir` is the path
+ /// returned by [`std::env::temp_dir`] .
+ pub fn wrap_static_fns_path<T: AsRef<Path>>(mut self, path: T) -> Self {
+ self.options.wrap_static_fns_path = Some(path.as_ref().to_owned());
+ self
+ }
+ },
+ as_args: "--wrap-static-fns-path",
+ },
+ /// Default visibility of fields.
+ default_visibility: FieldVisibilityKind {
+ methods: {
+ /// Set the default visibility of fields, including bitfields and accessor methods for
+ /// bitfields.
+ ///
+ /// This option only comes into effect if the [`Builder::respect_cxx_access_specs`]
+ /// option is disabled.
+ pub fn default_visibility(
+ mut self,
+ visibility: FieldVisibilityKind,
+ ) -> Self {
+ self.options.default_visibility = visibility;
+ self
+ }
+ },
+ as_args: |visibility, args| {
+ if *visibility != Default::default() {
+ args.push("--default-visibility".to_owned());
+ args.push(visibility.to_string());
+ }
+ },
+ },
+ /// Whether to emit diagnostics or not.
+ emit_diagnostics: bool {
+ methods: {
+ #[cfg(feature = "experimental")]
+ /// Emit diagnostics.
+ ///
+ /// These diagnostics are emitted to `stderr` if you are using `bindgen-cli` or printed
+ /// using `cargo:warning=` if you are using `bindgen` as a `build-dependency`.
+ ///
+ /// Diagnostics are not emitted by default.
+ ///
+ /// The layout and contents of these diagnostic messages are not covered by versioning
+ /// and can change without notice.
+ pub fn emit_diagnostics(mut self) -> Self {
+ self.options.emit_diagnostics = true;
+ self
+ }
+ },
+ as_args: "--emit-diagnostics",
+ }
+}
diff --git a/parse.rs b/parse.rs
index 1fd83cd..d29b090 100644
--- a/parse.rs
+++ b/parse.rs
@@ -1,4 +1,5 @@
//! Common traits and types related to parsing our IR from Clang cursors.
+#![deny(clippy::missing_docs_in_private_items)]
use crate::clang;
use crate::ir::context::{BindgenContext, ItemId};
@@ -6,7 +7,7 @@ use crate::ir::context::{BindgenContext, ItemId};
/// Not so much an error in the traditional sense, but a control flow message
/// when walking over Clang's AST with a cursor.
#[derive(Debug)]
-pub enum ParseError {
+pub(crate) enum ParseError {
/// Recurse down the current AST node's children.
Recurse,
/// Continue on to the next sibling AST node, or back up to the parent's
@@ -16,7 +17,7 @@ pub enum ParseError {
/// The result of parsing a Clang AST node.
#[derive(Debug)]
-pub enum ParseResult<T> {
+pub(crate) enum ParseResult<T> {
/// We've already resolved this item before, here is the extant `ItemId` for
/// it.
AlreadyResolved(ItemId),
@@ -28,7 +29,7 @@ pub enum ParseResult<T> {
/// An intermediate representation "sub-item" (i.e. one of the types contained
/// inside an `ItemKind` variant) that can be parsed from a Clang cursor.
-pub trait ClangSubItemParser: Sized {
+pub(crate) trait ClangSubItemParser: Sized {
/// Attempt to parse this type from the given cursor.
///
/// The fact that is a reference guarantees it's held by the context, and
diff --git a/regex_set.rs b/regex_set.rs
index 6246dd2..1d5cad2 100644
--- a/regex_set.rs
+++ b/regex_set.rs
@@ -1,4 +1,5 @@
//! A type that represents the union of a set of regular expressions.
+#![deny(clippy::missing_docs_in_private_items)]
use regex::RegexSet as RxSet;
use std::cell::Cell;
@@ -18,9 +19,7 @@ pub struct RegexSet {
impl RegexSet {
/// Create a new RegexSet
pub fn new() -> RegexSet {
- RegexSet {
- ..Default::default()
- }
+ RegexSet::default()
}
/// Is this set empty?
@@ -33,11 +32,7 @@ impl RegexSet {
where
S: AsRef<str>,
{
- let string = string.as_ref().to_owned();
- if string == "*" {
- warn!("using wildcard patterns (`*`) is no longer considered valid. Use `.*` instead");
- }
- self.items.push(string);
+ self.items.push(string.as_ref().to_owned());
self.matched.push(Cell::new(false));
self.set = None;
}
@@ -63,13 +58,56 @@ impl RegexSet {
///
/// Must be called before calling `matches()`, or it will always return
/// false.
+ #[inline]
pub fn build(&mut self, record_matches: bool) {
+ self.build_inner(record_matches, None)
+ }
+
+ #[cfg(all(feature = "__cli", feature = "experimental"))]
+ /// Construct a RegexSet from the set of entries we've accumulated and emit diagnostics if the
+ /// name of the regex set is passed to it.
+ ///
+ /// Must be called before calling `matches()`, or it will always return
+ /// false.
+ #[inline]
+ pub fn build_with_diagnostics(
+ &mut self,
+ record_matches: bool,
+ name: Option<&'static str>,
+ ) {
+ self.build_inner(record_matches, name)
+ }
+
+ #[cfg(all(not(feature = "__cli"), feature = "experimental"))]
+ /// Construct a RegexSet from the set of entries we've accumulated and emit diagnostics if the
+ /// name of the regex set is passed to it.
+ ///
+ /// Must be called before calling `matches()`, or it will always return
+ /// false.
+ #[inline]
+ pub(crate) fn build_with_diagnostics(
+ &mut self,
+ record_matches: bool,
+ name: Option<&'static str>,
+ ) {
+ self.build_inner(record_matches, name)
+ }
+
+ fn build_inner(
+ &mut self,
+ record_matches: bool,
+ _name: Option<&'static str>,
+ ) {
let items = self.items.iter().map(|item| format!("^({})$", item));
self.record_matches = record_matches;
self.set = match RxSet::new(items) {
Ok(x) => Some(x),
Err(e) => {
warn!("Invalid regex in {:?}: {:?}", self.items, e);
+ #[cfg(feature = "experimental")]
+ if let Some(name) = _name {
+ invalid_regex_warning(self, e, name);
+ }
None
}
}
@@ -101,3 +139,66 @@ impl RegexSet {
true
}
}
+
+#[cfg(feature = "experimental")]
+fn invalid_regex_warning(
+ set: &RegexSet,
+ err: regex::Error,
+ name: &'static str,
+) {
+ use crate::diagnostics::{Diagnostic, Level, Slice};
+
+ let mut diagnostic = Diagnostic::default();
+
+ match err {
+ regex::Error::Syntax(string) => {
+ if string.starts_with("regex parse error:\n") {
+ let mut source = String::new();
+
+ let mut parsing_source = true;
+
+ for line in string.lines().skip(1) {
+ if parsing_source {
+ if line.starts_with(' ') {
+ source.push_str(line);
+ source.push('\n');
+ continue;
+ }
+ parsing_source = false;
+ }
+ let error = "error: ";
+ if line.starts_with(error) {
+ let (_, msg) = line.split_at(error.len());
+ diagnostic.add_annotation(msg.to_owned(), Level::Error);
+ } else {
+ diagnostic.add_annotation(line.to_owned(), Level::Info);
+ }
+ }
+ let mut slice = Slice::default();
+ slice.with_source(source);
+ diagnostic.add_slice(slice);
+
+ diagnostic.with_title(
+ "Error while parsing a regular expression.",
+ Level::Warn,
+ );
+ } else {
+ diagnostic.with_title(string, Level::Warn);
+ }
+ }
+ err => {
+ let err = err.to_string();
+ diagnostic.with_title(err, Level::Warn);
+ }
+ }
+
+ diagnostic.add_annotation(
+ format!("This regular expression was passed via `{}`.", name),
+ Level::Note,
+ );
+
+ if set.items.iter().any(|item| item == "*") {
+ diagnostic.add_annotation("Wildcard patterns \"*\" are no longer considered valid. Use \".*\" instead.", Level::Help);
+ }
+ diagnostic.display();
+}