From 70115a08631f6928efbe5d685043676bf68e3123 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Tue, 27 Sep 2022 21:17:41 +0000 Subject: [PATCH] Don't traverse through special-cased types. --- src/ir/context.rs | 34 ++++++++++-------- src/ir/ty.rs | 7 ++++ tests/expectations/tests/stdint_typedef.rs | 41 ++++++++++++++++++++++ tests/headers/stdint_typedef.h | 10 ++++++ 4 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 tests/expectations/tests/stdint_typedef.rs create mode 100644 tests/headers/stdint_typedef.h 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 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 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 = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(Struct)) + ); + assert_eq!( + ::std::mem::align_of::(), + 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; +};