summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/context.rs34
-rw-r--r--src/ir/ty.rs7
-rw-r--r--tests/expectations/tests/stdint_typedef.rs41
-rw-r--r--tests/headers/stdint_typedef.h10
4 files changed, 78 insertions, 14 deletions
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 7837e594..d470efa9 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -2250,24 +2250,27 @@ If you encounter an error missing from this list, please file an issue or a PR!"
// Sized integer types from <stdint.h> get mapped to Rust primitive
// types regardless of whether they are blocklisted, so ensure that
// standard traits are considered derivable for them too.
- None => match name {
- "int8_t" | "uint8_t" | "int16_t" | "uint16_t" |
- "int32_t" | "uint32_t" | "int64_t" |
- "uint64_t" | "uintptr_t" | "intptr_t" |
- "ptrdiff_t" => Some(CanDerive::Yes),
- "size_t" if self.options.size_t_is_usize => {
- Some(CanDerive::Yes)
- }
- "ssize_t" if self.options.size_t_is_usize => {
- Some(CanDerive::Yes)
- }
- _ => Some(CanDerive::No),
- },
+ None => Some(if self.is_stdint_type(name) {
+ CanDerive::Yes
+ } else {
+ CanDerive::No
+ }),
})
.unwrap_or(CanDerive::No)
})
}
+ /// 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 {
+ match name {
+ "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" |
+ "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" |
+ "intptr_t" | "ptrdiff_t" => true,
+ "size_t" | "ssize_t" => self.options.size_t_is_usize,
+ _ => false,
+ }
+ }
+
/// Get a reference to the set of items we should generate.
pub fn codegen_items(&self) -> &ItemSet {
assert!(self.in_codegen_phase());
@@ -2355,7 +2358,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
TypeKind::Opaque |
TypeKind::TypeParam => return true,
_ => {}
- };
+ }
+ if self.is_stdint_type(&name) {
+ return true;
+ }
}
// Unnamed top-level enums are special and we
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index c85bc687..6a3fd0e8 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -1206,6 +1206,13 @@ impl Trace for Type {
where
T: Tracer,
{
+ if self
+ .name()
+ .map_or(false, |name| context.is_stdint_type(name))
+ {
+ // These types are special-cased in codegen and don't need to be traversed.
+ return;
+ }
match *self.kind() {
TypeKind::Pointer(inner) |
TypeKind::Reference(inner) |
diff --git a/tests/expectations/tests/stdint_typedef.rs b/tests/expectations/tests/stdint_typedef.rs
new file mode 100644
index 00000000..a52db496
--- /dev/null
+++ b/tests/expectations/tests/stdint_typedef.rs
@@ -0,0 +1,41 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+extern "C" {
+ pub fn fun() -> u64;
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct Struct {
+ pub field: u64,
+}
+#[test]
+fn bindgen_test_layout_Struct() {
+ const UNINIT: ::std::mem::MaybeUninit<Struct> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Struct>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Struct))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Struct>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(Struct))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).field) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Struct),
+ "::",
+ stringify!(field)
+ )
+ );
+}
diff --git a/tests/headers/stdint_typedef.h b/tests/headers/stdint_typedef.h
new file mode 100644
index 00000000..f716a7f1
--- /dev/null
+++ b/tests/headers/stdint_typedef.h
@@ -0,0 +1,10 @@
+// bindgen-flags: --allowlist-type="Struct" --allowlist-function="fun"
+
+// no typedef should be emitted for `__uint64_t`
+typedef unsigned long long __uint64_t;
+typedef __uint64_t uint64_t;
+
+uint64_t fun();
+struct Struct {
+ uint64_t field;
+};