diff --git a/bindgen-tests/tests/expectations/tests/specific_receiver.rs b/bindgen-tests/tests/expectations/tests/specific_receiver.rs new file mode 100644 index 0000000000..ec001b12ad --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/specific_receiver.rs @@ -0,0 +1,28 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +pub struct Fish__bindgen_vtable { + pub Fish_swim: unsafe extern "C" fn(this: *mut Fish), +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Fish { + pub vtable_: *const Fish__bindgen_vtable, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Fish"][::std::mem::size_of::() - 8usize]; + ["Alignment of Fish"][::std::mem::align_of::() - 8usize]; +}; +impl Default for Fish { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN4Fish4swimEv"] + pub fn Fish_swim(this: *mut Fish); +} diff --git a/bindgen-tests/tests/headers/specific_receiver.hpp b/bindgen-tests/tests/headers/specific_receiver.hpp new file mode 100644 index 0000000000..a521f9f0b2 --- /dev/null +++ b/bindgen-tests/tests/headers/specific_receiver.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --use-specific-virtual-function-receiver --generate-inline-functions -- -x c++ -std=c++14 + +class Fish { +public: + virtual void swim() { + } +}; diff --git a/bindgen/ir/function.rs b/bindgen/ir/function.rs index 83b748a5f4..52fc94d974 100644 --- a/bindgen/ir/function.rs +++ b/bindgen/ir/function.rs @@ -533,7 +533,10 @@ impl FunctionSig { let is_const = is_method && cursor.method_is_const(); let is_virtual = is_method && cursor.method_is_virtual(); let is_static = is_method && cursor.method_is_static(); - if !is_static && !is_virtual { + if !is_static && + (!is_virtual || + ctx.options().use_specific_virtual_function_receiver) + { let parent = cursor.semantic_parent(); let class = Item::parse(parent, None, ctx) .expect("Expected to parse the class"); diff --git a/bindgen/options/cli.rs b/bindgen/options/cli.rs index 1efddb02f3..f9a8572976 100644 --- a/bindgen/options/cli.rs +++ b/bindgen/options/cli.rs @@ -441,6 +441,9 @@ struct BindgenCommand { /// Always output explicit padding fields. #[arg(long)] explicit_padding: bool, + /// Always be specific about the 'receiver' of a virtual function. + #[arg(long)] + use_specific_virtual_function_receiver: bool, /// Use distinct char16_t #[arg(long)] use_distinct_char16_t: bool, @@ -632,6 +635,7 @@ where translate_enum_integer_types, c_naming, explicit_padding, + use_specific_virtual_function_receiver, use_distinct_char16_t, vtable_generation, sort_semantically, @@ -930,6 +934,7 @@ where translate_enum_integer_types, c_naming, explicit_padding, + use_specific_virtual_function_receiver, use_distinct_char16_t, vtable_generation, sort_semantically, diff --git a/bindgen/options/mod.rs b/bindgen/options/mod.rs index 74dd5c0b1d..ab6b232ec3 100644 --- a/bindgen/options/mod.rs +++ b/bindgen/options/mod.rs @@ -153,6 +153,21 @@ macro_rules! options { } options! { + /// Whether to specify the type of a virtual function receiver + use_specific_virtual_function_receiver: bool { + methods: { + /// Normally, virtual functions have void* as their 'this' type. + /// If this flag is enabled, override that behavior to indicate a + /// pointer of the specific type. + /// Disabled by default. + pub fn use_specific_virtual_function_receiver(mut self, doit: bool) -> Builder { + self.options.use_specific_virtual_function_receiver = doit; + self + } + }, + as_args: "--use-specific-virtual-function-receiver", + }, + /// Whether we should distinguish between C++'s 'char16_t' and 'u16'. /// The C++ type `char16_t` is its own special type; it's not a typedef /// of some other integer (this differs from C).