diff options
Diffstat (limited to 'patches/autocxx.patch')
-rw-r--r-- | patches/autocxx.patch | 2190 |
1 files changed, 2190 insertions, 0 deletions
diff --git a/patches/autocxx.patch b/patches/autocxx.patch new file mode 100644 index 0000000..256b928 --- /dev/null +++ b/patches/autocxx.patch @@ -0,0 +1,2190 @@ +diff --git a/Android.bp b/Android.bp +index 0f0d867..af0cb35 100644 +--- a/Android.bp ++++ b/Android.bp +@@ -66,6 +66,7 @@ rust_library_host { + "libpeeking_take_while", + "libprettyplease", + "libproc_macro2", ++ "libitertools", + "libquote", + "libregex", + "librustc_hash", +diff --git a/clang.rs b/clang.rs +index 0060213..4f8de24 100644 +--- a/clang.rs ++++ b/clang.rs +@@ -833,6 +833,21 @@ impl Cursor { + unsafe { clang_isVirtualBase(self.x) != 0 } + } + ++ // Is this cursor's referent a default constructor? ++ pub fn is_default_constructor(&self) -> bool { ++ unsafe { clang_CXXConstructor_isDefaultConstructor(self.x) != 0 } ++ } ++ ++ // Is this cursor's referent a copy constructor? ++ pub fn is_copy_constructor(&self) -> bool { ++ unsafe { clang_CXXConstructor_isCopyConstructor(self.x) != 0 } ++ } ++ ++ // Is this cursor's referent a move constructor? ++ pub fn is_move_constructor(&self) -> bool { ++ unsafe { clang_CXXConstructor_isMoveConstructor(self.x) != 0 } ++ } ++ + /// Try to evaluate this cursor. + pub(crate) fn evaluate(&self) -> Option<EvalResult> { + EvalResult::new(*self) +diff --git a/codegen/error.rs b/codegen/error.rs +index ead3496..f38a1c6 100644 +--- a/codegen/error.rs ++++ b/codegen/error.rs +@@ -11,6 +11,9 @@ pub(crate) enum Error { + /// definition that is too difficult for us to understand (like a partial + /// template specialization). + InstantiationOfOpaqueType, ++ ++ /// Type was a reference not a pointer, but we had nowhere to record that fact. ++ ReferenceButCouldNotRecord, + } + + impl fmt::Display for Error { +@@ -23,6 +26,9 @@ impl fmt::Display for Error { + "Instantiation of opaque template type or partial template \ + specialization" + } ++ Error::ReferenceButCouldNotRecord => { ++ "Type was a reference in a context where we only expected other types" ++ } + }) + } + } +diff --git a/codegen/helpers.rs b/codegen/helpers.rs +index 726fe75..113e93d 100644 +--- a/codegen/helpers.rs ++++ b/codegen/helpers.rs +@@ -1,7 +1,9 @@ + //! Helpers for code generation that don't need macro expansion. + +-use crate::ir::context::BindgenContext; ++use crate::ir::comp::SpecialMemberKind; ++use crate::ir::function::Visibility; + use crate::ir::layout::Layout; ++use crate::{ir::context::BindgenContext, BindgenOptions}; + use proc_macro2::{Ident, Span, TokenStream}; + use quote::TokenStreamExt; + +@@ -77,6 +79,173 @@ pub(crate) mod attributes { + } + } + ++pub trait CppSemanticAttributeCreator { ++ fn do_add(&mut self, ts: TokenStream); ++ fn is_enabled(&self) -> bool; ++ ++ fn add(&mut self, tokens: TokenStream) { ++ if self.is_enabled() { ++ self.do_add(quote! { ++ #[cpp_semantics(#tokens)] ++ }) ++ } ++ } ++ ++ fn add_ident(&mut self, desc: &str) { ++ if self.is_enabled() { ++ let id = Ident::new(desc, Span::call_site()); ++ self.add(quote! { #id }) ++ } ++ } ++ ++ fn special_member(&mut self, kind: SpecialMemberKind) { ++ let kind_str = match kind { ++ SpecialMemberKind::DefaultConstructor => "default_ctor", ++ SpecialMemberKind::CopyConstructor => "copy_ctor", ++ SpecialMemberKind::MoveConstructor => "move_ctor", ++ SpecialMemberKind::Destructor => "dtor", ++ SpecialMemberKind::AssignmentOperator => "assignment_operator", ++ }; ++ self.add(quote! { ++ special_member(#kind_str) ++ }) ++ } ++ ++ fn original_name(&mut self, name: &str) { ++ self.add(quote! { ++ original_name(#name) ++ }) ++ } ++ ++ fn ret_type_reference(&mut self) { ++ self.add_ident("ret_type_reference") ++ } ++ ++ fn ret_type_rvalue_reference(&mut self) { ++ self.add_ident("ret_type_rvalue_reference") ++ } ++ ++ fn arg_type_reference(&mut self, arg_name: &Ident) { ++ self.add(quote! { ++ arg_type_reference(#arg_name) ++ }) ++ } ++ ++ fn field_type_reference(&mut self) { ++ self.add_ident("reference") ++ } ++ ++ fn field_type_rvalue_reference(&mut self) { ++ self.add_ident("rvalue_reference") ++ } ++ ++ fn is_virtual(&mut self) { ++ self.add_ident("bindgen_virtual") ++ } ++ ++ fn arg_type_rvalue_reference(&mut self, arg_name: &Ident) { ++ self.add(quote! { ++ arg_type_rvalue_reference(#arg_name) ++ }) ++ } ++ ++ fn is_pure_virtual(&mut self) { ++ self.add_ident("pure_virtual") ++ } ++ ++ fn visibility(&mut self, visibility: Visibility) { ++ match visibility { ++ Visibility::Protected => self.add_ident("visibility_protected"), ++ Visibility::Private => self.add_ident("visibility_private"), ++ _ => {} ++ } ++ } ++ ++ fn incomprehensible_param_in_arg_or_return(&mut self) { ++ self.add_ident("incomprehensible_param_in_arg_or_return") ++ } ++ ++ fn discards_template_param(&mut self) { ++ self.add_ident("unused_template_param") ++ } ++ ++ fn deleted_fn(&mut self) { ++ self.add_ident("deleted") ++ } ++ ++ fn defaulted_fn(&mut self) { ++ self.add_ident("defaulted") ++ } ++ ++ fn layout(&mut self, layout: &Layout) { ++ let sz = ast_ty::int_expr(layout.size as i64); ++ let align = ast_ty::int_expr(layout.align as i64); ++ let packed = if layout.packed { ++ quote! { true } ++ } else { ++ quote! { false } ++ }; ++ self.add(quote! { ++ layout(#sz, #align, #packed) ++ }) ++ } ++} ++ ++pub struct CppSemanticAttributeAdder<'a> { ++ enabled: bool, ++ attrs: &'a mut Vec<TokenStream>, ++} ++ ++impl<'a> CppSemanticAttributeAdder<'a> { ++ pub(crate) fn new( ++ opts: &BindgenOptions, ++ attrs: &'a mut Vec<TokenStream>, ++ ) -> Self { ++ Self { ++ enabled: opts.cpp_semantic_attributes, ++ attrs, ++ } ++ } ++} ++ ++impl<'a> CppSemanticAttributeCreator for CppSemanticAttributeAdder<'a> { ++ fn do_add(&mut self, ts: TokenStream) { ++ self.attrs.push(ts) ++ } ++ ++ fn is_enabled(&self) -> bool { ++ self.enabled ++ } ++} ++ ++pub struct CppSemanticAttributeSingle { ++ enabled: bool, ++ attr: TokenStream, ++} ++ ++impl CppSemanticAttributeSingle { ++ pub(crate) fn new(opts: &BindgenOptions) -> Self { ++ Self { ++ enabled: opts.cpp_semantic_attributes, ++ attr: quote! {}, ++ } ++ } ++ ++ pub(crate) fn result(self) -> TokenStream { ++ self.attr ++ } ++} ++ ++impl CppSemanticAttributeCreator for CppSemanticAttributeSingle { ++ fn do_add(&mut self, ts: TokenStream) { ++ self.attr = ts; ++ } ++ ++ fn is_enabled(&self) -> bool { ++ self.enabled ++ } ++} ++ + /// 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(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream { +diff --git a/codegen/mod.rs b/codegen/mod.rs +index 0dd3228..41f6e3a 100644 +--- a/codegen/mod.rs ++++ b/codegen/mod.rs +@@ -20,6 +20,10 @@ use self::struct_layout::StructLayoutTracker; + use super::BindgenOptions; + + use crate::callbacks::{DeriveInfo, TypeKind as DeriveTypeKind}; ++use crate::codegen::helpers::{ ++ CppSemanticAttributeAdder, CppSemanticAttributeCreator, ++ CppSemanticAttributeSingle, ++}; + use crate::ir::analysis::{HasVtable, Sizedness}; + use crate::ir::annotations::{ + Annotations, FieldAccessorKind, FieldVisibilityKind, +@@ -441,12 +445,13 @@ impl AppendImplicitTemplateParams for proc_macro2::TokenStream { + _ => {} + } + +- let params: Vec<_> = item +- .used_template_params(ctx) ++ let (used_template_params, _) = item.used_template_params(ctx); ++ let params: Vec<_> = used_template_params + .iter() + .map(|p| { + p.try_to_rust_ty(ctx, &()) + .expect("template params cannot fail to be a rust type") ++ .ignore_annotations() + }) + .collect(); + if !params.is_empty() { +@@ -662,7 +667,10 @@ impl CodeGenerator for Var { + attrs.push(attributes::doc(comment)); + } + +- let ty = self.ty().to_rust_ty_or_opaque(ctx, &()); ++ let ty = self ++ .ty() ++ .to_rust_ty_or_opaque(ctx, &()) ++ .ignore_annotations(); + + if let Some(val) = self.val() { + match *val { +@@ -904,7 +912,8 @@ impl CodeGenerator for Type { + return; + } + +- let mut outer_params = item.used_template_params(ctx); ++ let (mut outer_params, has_unused_template_args) = ++ item.used_template_params(ctx); + + let is_opaque = item.is_opaque(ctx, &()); + let inner_rust_type = if is_opaque { +@@ -914,9 +923,12 @@ impl CodeGenerator for Type { + // Its possible that we have better layout information than + // the inner type does, so fall back to an opaque blob based + // on our layout if converting the inner item fails. +- let mut inner_ty = inner_item ++ let (mut inner_ty, _) = inner_item + .try_to_rust_ty_or_opaque(ctx, &()) +- .unwrap_or_else(|_| self.to_opaque(ctx, item)); ++ .map(|ty| ty.into_outer_type()) ++ .unwrap_or_else(|_| { ++ (self.to_opaque(ctx, item), RustTyAnnotation::None) ++ }); + inner_ty.append_implicit_template_params(ctx, inner_item); + inner_ty + }; +@@ -951,6 +963,18 @@ impl CodeGenerator for Type { + } else { + quote! {} + }; ++ let mut semantic_annotations = ++ CppSemanticAttributeSingle::new(ctx.options()); ++ // We are handling (essentially) type X = Y; ++ // We want to denote only if X has unused template params, e.g. ++ // type X<A> = Y; ++ // We don't want to note whether Y has unused template params, e.g. ++ // type X = Y<B> ++ // because that information will be recorded against the definition of Y. ++ if has_unused_template_args { ++ semantic_annotations.discards_template_param(); ++ } ++ tokens.append_all(semantic_annotations.result()); + + let alias_style = if ctx.options().type_alias.matches(&name) { + AliasVariation::TypeAlias +@@ -983,8 +1007,21 @@ impl CodeGenerator for Type { + return; + } + ++ let mut attributes = Vec::new(); ++ if let Some(original_name) = item.original_name(ctx) { ++ if name != original_name { ++ let mut semantic_annotations = ++ CppSemanticAttributeAdder::new( ++ ctx.options(), ++ &mut attributes, ++ ); ++ semantic_annotations.original_name(&original_name); ++ } ++ } ++ + tokens.append_all(match alias_style { + AliasVariation::TypeAlias => quote! { ++ #( #attributes )* + pub type #rust_name + }, + AliasVariation::NewType | AliasVariation::NewTypeDeref => { +@@ -1031,7 +1068,7 @@ impl CodeGenerator for Type { + .map(|p| { + p.try_to_rust_ty(ctx, &()).expect( + "type parameters can always convert to rust ty OK", +- ) ++ ).ignore_annotations() + }) + .collect(); + +@@ -1147,8 +1184,8 @@ impl<'a> CodeGenerator for Vtable<'a> { + + // FIXME: Need to account for overloading with times_seen (separately from regular function path). + let function_name = ctx.rust_ident(function_name); +- let mut args = utils::fnsig_arguments(ctx, signature); +- let ret = utils::fnsig_return_ty(ctx, signature); ++ let (mut args, _) = utils::fnsig_arguments(ctx, signature); ++ let (ret, _) = utils::fnsig_return_ty(ctx, signature); + + args[0] = if m.is_const() { + quote! { this: *const #class_ident } +@@ -1193,11 +1230,12 @@ impl<'a> TryToRustTy for Vtable<'a> { + &self, + ctx: &BindgenContext, + _: &(), +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + let name = ctx.rust_ident(self.canonical_name(ctx)); + Ok(quote! { + #name +- }) ++ } ++ .into()) + } + } + +@@ -1247,7 +1285,8 @@ impl CodeGenerator for TemplateInstantiation { + let fn_name = ctx.rust_ident_raw(fn_name); + + let prefix = ctx.trait_prefix(); +- let ident = item.to_rust_ty_or_opaque(ctx, &()); ++ let ident = ++ item.to_rust_ty_or_opaque(ctx, &()).ignore_annotations(); + let size_of_expr = quote! { + ::#prefix::mem::size_of::<#ident>() + }; +@@ -1396,7 +1435,8 @@ impl<'a> FieldCodegen<'a> for FieldData { + let field_item = + self.ty().into_resolver().through_type_refs().resolve(ctx); + let field_ty = field_item.expect_type(); +- let mut ty = self.ty().to_rust_ty_or_opaque(ctx, &()); ++ let ty = self.ty().to_rust_ty_or_opaque(ctx, &()); ++ let (mut ty, ty_annotations) = ty.into_outer_type(); + ty.append_implicit_template_params(ctx, field_item); + + // NB: If supported, we use proper `union` types. +@@ -1405,7 +1445,8 @@ impl<'a> FieldCodegen<'a> for FieldData { + } else if let Some(item) = field_ty.is_incomplete_array(ctx) { + result.saw_incomplete_array(); + +- let inner = item.to_rust_ty_or_opaque(ctx, &()); ++ let inner = ++ item.to_rust_ty_or_opaque(ctx, &()).ignore_annotations(); + + if ctx.options().enable_cxx_namespaces { + quote! { +@@ -1449,19 +1490,33 @@ impl<'a> FieldCodegen<'a> for FieldData { + let accessor_kind = + self.annotations().accessor_kind().unwrap_or(accessor_kind); + ++ let mut attributes = Vec::new(); ++ let mut csaa = ++ CppSemanticAttributeAdder::new(ctx.options(), &mut attributes); ++ match ty_annotations { ++ RustTyAnnotation::Reference => csaa.field_type_reference(), ++ RustTyAnnotation::RValueReference => { ++ csaa.field_type_rvalue_reference() ++ } ++ _ => {} ++ }; ++ + match visibility { + FieldVisibilityKind::Private => { + field.append_all(quote! { ++ #(#attributes),* + #field_ident : #ty , + }); + } + FieldVisibilityKind::PublicCrate => { + field.append_all(quote! { ++ #(#attributes),* + pub(crate) #field_ident : #ty , + }); + } + FieldVisibilityKind::Public => { + field.append_all(quote! { ++ #(#attributes),* + pub #field_ident : #ty , + }); + } +@@ -1723,8 +1778,9 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { + let param_name = bitfield_getter_name(ctx, bf); + let bitfield_ty_item = ctx.resolve_item(bf.ty()); + let bitfield_ty = bitfield_ty_item.expect_type(); +- let bitfield_ty = +- bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); ++ let bitfield_ty = bitfield_ty ++ .to_rust_ty_or_opaque(ctx, bitfield_ty_item) ++ .ignore_annotations(); + + ctor_params.push(quote! { + #param_name : #bitfield_ty +@@ -1819,8 +1875,9 @@ impl<'a> FieldCodegen<'a> for Bitfield { + } + }; + +- let bitfield_ty = +- bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); ++ let bitfield_ty = bitfield_ty ++ .to_rust_ty_or_opaque(ctx, bitfield_ty_item) ++ .ignore_annotations(); + + let offset = self.offset_into_unit(); + let width = self.width() as u8; +@@ -1936,6 +1993,7 @@ impl CodeGenerator for CompInfo { + let vtable_type = vtable + .try_to_rust_ty(ctx, &()) + .expect("vtable to Rust type conversion is infallible") ++ .ignore_annotations() + .to_ptr(true); + + fields.push(quote! { +@@ -1951,7 +2009,9 @@ impl CodeGenerator for CompInfo { + } + + let inner_item = ctx.resolve_item(base.ty); +- let mut inner = inner_item.to_rust_ty_or_opaque(ctx, &()); ++ let mut inner = inner_item ++ .to_rust_ty_or_opaque(ctx, &()) ++ .ignore_annotations(); + inner.append_implicit_template_params(ctx, inner_item); + let field_name = ctx.rust_ident(&base.field_name); + +@@ -2115,7 +2175,9 @@ impl CodeGenerator for CompInfo { + + let mut generic_param_names = vec![]; + +- for (idx, ty) in item.used_template_params(ctx).iter().enumerate() { ++ let (used_template_params, unused_template_params) = ++ item.used_template_params(ctx); ++ for (idx, ty) in used_template_params.iter().enumerate() { + let param = ctx.resolve_type(*ty); + let name = param.name().unwrap(); + let ident = ctx.rust_ident(name); +@@ -2159,6 +2221,15 @@ impl CodeGenerator for CompInfo { + } else { + attributes.push(attributes::repr("C")); + } ++ let mut semantic_annotations = ++ CppSemanticAttributeAdder::new(ctx.options(), &mut attributes); ++ if unused_template_params { ++ semantic_annotations.discards_template_param(); ++ } ++ semantic_annotations.visibility(self.visibility()); ++ if let Some(layout) = layout { ++ semantic_annotations.layout(&layout); ++ } + + if ctx.options().rust_features().repr_align { + if let Some(explicit) = explicit_align { +@@ -2225,6 +2296,16 @@ impl CodeGenerator for CompInfo { + attributes.push(attributes::derives(&derives)) + } + ++ if let Some(original_name) = item.original_name(ctx) { ++ if canonical_name != original_name { ++ let mut semantic_annotations = CppSemanticAttributeAdder::new( ++ ctx.options(), ++ &mut attributes, ++ ); ++ semantic_annotations.original_name(&original_name); ++ } ++ } ++ + if item.must_use(ctx) { + attributes.push(attributes::must_use()); + } +@@ -2604,8 +2685,9 @@ impl Method { + write!(&mut function_name, "{}", times_seen).unwrap(); + } + let function_name = ctx.rust_ident(function_name); +- let mut args = utils::fnsig_arguments(ctx, signature); +- let mut ret = utils::fnsig_return_ty(ctx, signature); ++ let (mut args, args_attributes) = ++ utils::fnsig_arguments(ctx, signature); ++ let (mut ret, ret_attr) = utils::fnsig_return_ty(ctx, signature); + + if !self.is_static() && !self.is_constructor() { + args[0] = if self.is_const() { +@@ -2681,7 +2763,9 @@ impl Method { + + let block = ctx.wrap_unsafe_ops(quote! ( #( #stmts );*)); + +- let mut attrs = vec![attributes::inline()]; ++ let mut attrs = args_attributes; ++ attrs.push(ret_attr); ++ attrs.push(attributes::inline()); + + if signature.must_use() && + ctx.options().rust_features().must_use_function +@@ -3202,6 +3286,15 @@ impl CodeGenerator for Enum { + + let mut attrs = vec![]; + ++ let mut semantic_annotations = ++ CppSemanticAttributeAdder::new(ctx.options(), &mut attrs); ++ if let Some(original_name) = item.original_name(ctx) { ++ if name != original_name { ++ semantic_annotations.original_name(&original_name); ++ } ++ } ++ semantic_annotations.visibility(self.visibility); ++ + // TODO(emilio): Delegate this to the builders? + match variation { + EnumVariation::Rust { non_exhaustive } => { +@@ -3296,7 +3389,7 @@ impl CodeGenerator for Enum { + }); + } + +- let repr = repr.to_rust_ty_or_opaque(ctx, item); ++ let repr = repr.to_rust_ty_or_opaque(ctx, item).ignore_annotations(); + let has_typedef = ctx.is_enum_typedef_combo(item.id()); + + let mut builder = +@@ -3304,7 +3397,8 @@ impl CodeGenerator for Enum { + + // A map where we keep a value -> variant relation. + let mut seen_values = HashMap::<_, Ident>::default(); +- let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &()); ++ let enum_rust_ty = ++ item.to_rust_ty_or_opaque(ctx, &()).ignore_annotations(); + let is_toplevel = item.is_toplevel(ctx); + + // Used to mangle the constants we generate in the unnamed-enum case. +@@ -3606,9 +3700,9 @@ trait TryToOpaque { + &self, + ctx: &BindgenContext, + extra: &Self::Extra, +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + self.try_get_layout(ctx, extra) +- .map(|layout| helpers::blob(ctx, layout)) ++ .map(|layout| helpers::blob(ctx, layout).into()) + } + } + +@@ -3654,7 +3748,7 @@ trait TryToRustTy { + &self, + ctx: &BindgenContext, + extra: &Self::Extra, +- ) -> error::Result<proc_macro2::TokenStream>; ++ ) -> error::Result<RustTy>; + } + + /// Fallible conversion to a Rust type or an opaque blob with the correct size +@@ -3669,7 +3763,7 @@ trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque { + &self, + ctx: &BindgenContext, + extra: &<Self as TryToRustTyOrOpaque>::Extra, +- ) -> error::Result<proc_macro2::TokenStream>; ++ ) -> error::Result<RustTy>; + } + + impl<E, T> TryToRustTyOrOpaque for T +@@ -3682,10 +3776,10 @@ where + &self, + ctx: &BindgenContext, + extra: &E, +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + self.try_to_rust_ty(ctx, extra).or_else(|_| { + if let Ok(layout) = self.try_get_layout(ctx, extra) { +- Ok(helpers::blob(ctx, layout)) ++ Ok(helpers::blob(ctx, layout).into()) + } else { + Err(error::Error::NoLayoutForOpaqueBlob) + } +@@ -3717,7 +3811,7 @@ trait ToRustTyOrOpaque: TryToRustTy + ToOpaque { + &self, + ctx: &BindgenContext, + extra: &<Self as ToRustTyOrOpaque>::Extra, +- ) -> proc_macro2::TokenStream; ++ ) -> RustTy; + } + + impl<E, T> ToRustTyOrOpaque for T +@@ -3726,13 +3820,9 @@ where + { + type Extra = E; + +- fn to_rust_ty_or_opaque( +- &self, +- ctx: &BindgenContext, +- extra: &E, +- ) -> proc_macro2::TokenStream { ++ fn to_rust_ty_or_opaque(&self, ctx: &BindgenContext, extra: &E) -> RustTy { + self.try_to_rust_ty(ctx, extra) +- .unwrap_or_else(|_| self.to_opaque(ctx, extra)) ++ .unwrap_or_else(|_| RustTy::new_opaque(self.to_opaque(ctx, extra))) + } + } + +@@ -3761,7 +3851,7 @@ where + &self, + ctx: &BindgenContext, + _: &(), +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + ctx.resolve_item((*self).into()).try_to_rust_ty(ctx, &()) + } + } +@@ -3785,7 +3875,7 @@ impl TryToRustTy for Item { + &self, + ctx: &BindgenContext, + _: &(), +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + self.kind().expect_type().try_to_rust_ty(ctx, self) + } + } +@@ -3802,6 +3892,111 @@ impl TryToOpaque for Type { + } + } + ++enum RustTyAnnotation { ++ None, ++ Reference, ++ RValueReference, ++ HasUnusedTemplateArgs, ++ Opaque, ++} ++ ++struct RustTy { ++ ts: proc_macro2::TokenStream, ++ annotation: RustTyAnnotation, ++} ++ ++impl From<proc_macro2::TokenStream> for RustTy { ++ fn from(ts: proc_macro2::TokenStream) -> Self { ++ RustTy::new(ts) ++ } ++} ++ ++impl RustTy { ++ fn new(ts: proc_macro2::TokenStream) -> Self { ++ Self { ++ ts, ++ annotation: RustTyAnnotation::None, ++ } ++ } ++ ++ fn new_opaque(ts: proc_macro2::TokenStream) -> Self { ++ Self { ++ ts, ++ annotation: RustTyAnnotation::Opaque, ++ } ++ } ++ ++ fn new_reference( ++ ts: proc_macro2::TokenStream, ++ inner: RustTyAnnotation, ++ ) -> Self { ++ let annotation = match inner { ++ RustTyAnnotation::HasUnusedTemplateArgs | ++ RustTyAnnotation::Opaque => inner, ++ _ => RustTyAnnotation::Reference, ++ }; ++ Self { ts, annotation } ++ } ++ ++ fn new_rvalue_reference( ++ ts: proc_macro2::TokenStream, ++ inner: RustTyAnnotation, ++ ) -> Self { ++ let annotation = match inner { ++ RustTyAnnotation::HasUnusedTemplateArgs | ++ RustTyAnnotation::Opaque => inner, ++ _ => RustTyAnnotation::RValueReference, ++ }; ++ Self { ts, annotation } ++ } ++ ++ // We're constructing some outer type composed of an inner type, ++ // e.g. a reference to a T - the inner type is T ++ fn wraps(ts: proc_macro2::TokenStream, inner: RustTyAnnotation) -> Self { ++ let annotation = match inner { ++ RustTyAnnotation::HasUnusedTemplateArgs => { ++ RustTyAnnotation::HasUnusedTemplateArgs ++ } ++ _ => RustTyAnnotation::None, ++ }; ++ Self { ts, annotation } ++ } ++ ++ fn with_unused_template_args( ++ ts: proc_macro2::TokenStream, ++ has_unused_args: bool, ++ ) -> Self { ++ Self { ++ ts, ++ annotation: if has_unused_args { ++ RustTyAnnotation::HasUnusedTemplateArgs ++ } else { ++ RustTyAnnotation::None ++ }, ++ } ++ } ++ ++ // Where this is called, we're discarding information about whether ++ // a type is a reference or a pointer. This is not desirable. ++ fn ignore_annotations(self) -> proc_macro2::TokenStream { ++ self.ts ++ } ++ ++ // Use when this is an inner type and will become part of an outer type. ++ // Pass the annotation into [wraps] ++ fn into_outer_type(self) -> (proc_macro2::TokenStream, RustTyAnnotation) { ++ (self.ts, self.annotation) ++ } ++ ++ fn into_unannotated_ts(self) -> error::Result<proc_macro2::TokenStream> { ++ if matches!(self.annotation, RustTyAnnotation::None) { ++ Ok(self.ts) ++ } else { ++ Err(error::Error::ReferenceButCouldNotRecord) ++ } ++ } ++} ++ + impl TryToRustTy for Type { + type Extra = Item; + +@@ -3809,28 +4004,30 @@ impl TryToRustTy for Type { + &self, + ctx: &BindgenContext, + item: &Item, +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + use self::helpers::ast_ty::*; + + match *self.kind() { +- TypeKind::Void => Ok(c_void(ctx)), ++ TypeKind::Void => Ok(c_void(ctx).into()), + // TODO: we should do something smart with nullptr, or maybe *const + // c_void is enough? +- TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true)), ++ TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true).into()), + TypeKind::Int(ik) => { + match ik { +- IntKind::Bool => Ok(quote! { bool }), +- IntKind::Char { .. } => Ok(raw_type(ctx, "c_char")), +- IntKind::SChar => Ok(raw_type(ctx, "c_schar")), +- IntKind::UChar => Ok(raw_type(ctx, "c_uchar")), +- IntKind::Short => Ok(raw_type(ctx, "c_short")), +- IntKind::UShort => Ok(raw_type(ctx, "c_ushort")), +- IntKind::Int => Ok(raw_type(ctx, "c_int")), +- IntKind::UInt => Ok(raw_type(ctx, "c_uint")), +- IntKind::Long => Ok(raw_type(ctx, "c_long")), +- IntKind::ULong => Ok(raw_type(ctx, "c_ulong")), +- IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")), +- IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")), ++ IntKind::Bool => Ok(quote! { bool }.into()), ++ IntKind::Char { .. } => Ok(raw_type(ctx, "c_char").into()), ++ IntKind::SChar => Ok(raw_type(ctx, "c_schar").into()), ++ IntKind::UChar => Ok(raw_type(ctx, "c_uchar").into()), ++ IntKind::Short => Ok(raw_type(ctx, "c_short").into()), ++ IntKind::UShort => Ok(raw_type(ctx, "c_ushort").into()), ++ IntKind::Int => Ok(raw_type(ctx, "c_int").into()), ++ IntKind::UInt => Ok(raw_type(ctx, "c_uint").into()), ++ IntKind::Long => Ok(raw_type(ctx, "c_long").into()), ++ IntKind::ULong => Ok(raw_type(ctx, "c_ulong").into()), ++ IntKind::LongLong => Ok(raw_type(ctx, "c_longlong").into()), ++ IntKind::ULongLong => { ++ Ok(raw_type(ctx, "c_ulonglong").into()) ++ } + IntKind::WChar => { + let layout = self + .layout(ctx) +@@ -3838,19 +4035,22 @@ impl TryToRustTy for Type { + let ty = Layout::known_type_for_size(ctx, layout.size) + .expect("Non-representable wchar_t?"); + let ident = ctx.rust_ident_raw(ty); +- Ok(quote! { #ident }) ++ Ok(quote! { #ident }.into()) + } + +- IntKind::I8 => Ok(quote! { i8 }), +- IntKind::U8 => Ok(quote! { u8 }), +- IntKind::I16 => Ok(quote! { i16 }), +- IntKind::U16 => Ok(quote! { u16 }), +- IntKind::I32 => Ok(quote! { i32 }), +- IntKind::U32 => Ok(quote! { u32 }), +- IntKind::I64 => Ok(quote! { i64 }), +- IntKind::U64 => Ok(quote! { u64 }), ++ IntKind::I8 => Ok(quote! { i8 }.into()), ++ IntKind::U8 => Ok(quote! { u8 }.into()), ++ IntKind::I16 => Ok(quote! { i16 }.into()), ++ IntKind::Char16 => Ok(quote! { c_char16_t }.into()), ++ IntKind::U16 => Ok(quote! { u16 }.into()), ++ IntKind::I32 => Ok(quote! { i32 }.into()), ++ IntKind::U32 => Ok(quote! { u32 }.into()), ++ IntKind::I64 => Ok(quote! { i64 }.into()), ++ IntKind::U64 => Ok(quote! { u64 }.into()), + IntKind::Custom { name, .. } => { +- Ok(proc_macro2::TokenStream::from_str(name).unwrap()) ++ Ok(proc_macro2::TokenStream::from_str(name) ++ .unwrap() ++ .into()) + } + IntKind::U128 => { + Ok(if ctx.options().rust_features.i128_and_u128 { +@@ -3859,19 +4059,21 @@ impl TryToRustTy for Type { + // Best effort thing, but wrong alignment + // unfortunately. + quote! { [u64; 2] } +- }) ++ } ++ .into()) + } + IntKind::I128 => { + Ok(if ctx.options().rust_features.i128_and_u128 { + quote! { i128 } + } else { + quote! { [u64; 2] } +- }) ++ } ++ .into()) + } + } + } + TypeKind::Float(fk) => { +- Ok(float_kind_rust_type(ctx, fk, self.layout(ctx))) ++ Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)).into()) + } + TypeKind::Complex(fk) => { + let float_path = +@@ -3886,31 +4088,35 @@ impl TryToRustTy for Type { + quote! { + __BindgenComplex<#float_path> + } +- }) ++ } ++ .into()) + } + TypeKind::Function(ref fs) => { + // We can't rely on the sizeof(Option<NonZero<_>>) == + // sizeof(NonZero<_>) optimization with opaque blobs (because + // they aren't NonZero), so don't *ever* use an or_opaque + // variant here. +- let ty = fs.try_to_rust_ty(ctx, &())?; ++ let ty = fs.try_to_rust_ty(ctx, &())?.into_unannotated_ts()?; + + let prefix = ctx.trait_prefix(); + Ok(quote! { + ::#prefix::option::Option<#ty> +- }) ++ } ++ .into()) + } + TypeKind::Array(item, len) | TypeKind::Vector(item, len) => { +- let ty = item.try_to_rust_ty(ctx, &())?; ++ let ty = ++ item.try_to_rust_ty(ctx, &())?.into_unannotated_ts()?; + Ok(quote! { + [ #ty ; #len ] +- }) ++ } ++ .into()) + } + TypeKind::Enum(..) => { + let path = item.namespace_aware_canonical_path(ctx); + let path = proc_macro2::TokenStream::from_str(&path.join("::")) + .unwrap(); +- Ok(quote!(#path)) ++ Ok(quote!(#path).into()) + } + TypeKind::TemplateInstantiation(ref inst) => { + inst.try_to_rust_ty(ctx, item) +@@ -3921,22 +4127,22 @@ impl TryToRustTy for Type { + TypeKind::BlockPointer(..) => { + if self.is_block_pointer() && !ctx.options().generate_block { + let void = c_void(ctx); +- return Ok(void.to_ptr(/* is_const = */ false)); ++ return Ok(void.to_ptr(/* is_const = */ false).into()); + } + +- if item.is_opaque(ctx, &()) && +- item.used_template_params(ctx) +- .into_iter() +- .any(|param| param.is_template_param(ctx, &())) +- { ++ let (used_template_params, _) = item.used_template_params(ctx); ++ let has_used_template_params = used_template_params ++ .into_iter() ++ .any(|param| param.is_template_param(ctx, &())); ++ if item.is_opaque(ctx, &()) && has_used_template_params { + self.try_to_opaque(ctx, item) + } else if let Some(ty) = self + .name() + .and_then(|name| utils::type_from_named(ctx, name)) + { +- Ok(ty) ++ Ok(ty.into()) + } else { +- utils::build_path(item, ctx) ++ Ok(utils::build_path(item, ctx)?.into()) + } + } + TypeKind::Comp(ref info) => { +@@ -3947,11 +4153,15 @@ impl TryToRustTy for Type { + return self.try_to_opaque(ctx, item); + } + +- utils::build_path(item, ctx) ++ Ok(utils::build_path(item, ctx)?.into()) + } + TypeKind::Opaque => self.try_to_opaque(ctx, item), +- TypeKind::Pointer(inner) | TypeKind::Reference(inner) => { ++ TypeKind::Pointer(inner) | TypeKind::Reference(inner, _) => { + let is_const = ctx.resolve_type(inner).is_const(); ++ let is_reference = ++ matches!(self.kind(), TypeKind::Reference(_, false)); ++ let is_rvalue_reference = ++ matches!(self.kind(), TypeKind::Reference(_, true)); + + let inner = + inner.into_resolver().through_type_refs().resolve(ctx); +@@ -3963,16 +4173,24 @@ impl TryToRustTy for Type { + // Regardless if we can properly represent the inner type, we + // should always generate a proper pointer here, so use + // infallible conversion of the inner type. +- let mut ty = inner.to_rust_ty_or_opaque(ctx, &()); ++ let (mut ty, inner_annotations) = ++ inner.to_rust_ty_or_opaque(ctx, &()).into_outer_type(); + ty.append_implicit_template_params(ctx, inner); + + // Avoid the first function pointer level, since it's already + // represented in Rust. + if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer + { +- Ok(ty) ++ Ok(RustTy::wraps(ty, inner_annotations)) + } else { +- Ok(ty.to_ptr(is_const)) ++ let ty_ptr = ty.to_ptr(is_const); ++ Ok(if is_rvalue_reference { ++ RustTy::new_rvalue_reference(ty_ptr, inner_annotations) ++ } else if is_reference { ++ RustTy::new_reference(ty_ptr, inner_annotations) ++ } else { ++ RustTy::wraps(ty_ptr, inner_annotations) ++ }) + } + } + TypeKind::TypeParam => { +@@ -3980,19 +4198,23 @@ impl TryToRustTy for Type { + let ident = ctx.rust_ident(name); + Ok(quote! { + #ident +- }) ++ } ++ .into()) + } + TypeKind::ObjCSel => Ok(quote! { + objc::runtime::Sel +- }), ++ } ++ .into()), + TypeKind::ObjCId => Ok(quote! { + id +- }), ++ } ++ .into()), + TypeKind::ObjCInterface(ref interface) => { + let name = ctx.rust_ident(interface.name()); + Ok(quote! { + #name +- }) ++ } ++ .into()) + } + ref u @ TypeKind::UnresolvedTypeRef(..) => { + unreachable!("Should have been resolved after parsing {:?}!", u) +@@ -4022,7 +4244,7 @@ impl TryToRustTy for TemplateInstantiation { + &self, + ctx: &BindgenContext, + item: &Item, +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + if self.is_opaque(ctx, item) { + return Err(error::Error::InstantiationOfOpaqueType); + } +@@ -4066,19 +4288,32 @@ impl TryToRustTy for TemplateInstantiation { + .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param)) + .map(|(arg, _)| { + let arg = arg.into_resolver().through_type_refs().resolve(ctx); +- let mut ty = arg.try_to_rust_ty(ctx, &())?; ++ let mut ty = ++ arg.try_to_rust_ty(ctx, &())?.into_unannotated_ts()?; + ty.append_implicit_template_params(ctx, arg); + Ok(ty) + }) + .collect::<error::Result<Vec<_>>>()?; + ++ let has_unused_template_args = def_params ++ .iter() ++ // Only pass type arguments for the type parameters that ++ // the def uses. ++ .any(|param| !ctx.uses_template_parameter(def.id(), *param)); ++ + if template_args.is_empty() { +- return Ok(ty); ++ return Ok(RustTy::with_unused_template_args( ++ ty, ++ has_unused_template_args, ++ )); + } + +- Ok(quote! { +- #ty < #( #template_args ),* > +- }) ++ Ok(RustTy::with_unused_template_args( ++ quote! { ++ #ty < #( #template_args ),* > ++ }, ++ has_unused_template_args, ++ )) + } + } + +@@ -4089,39 +4324,40 @@ impl TryToRustTy for FunctionSig { + &self, + ctx: &BindgenContext, + _: &(), +- ) -> error::Result<proc_macro2::TokenStream> { ++ ) -> error::Result<RustTy> { + // 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 (ret, _) = utils::fnsig_return_ty(ctx, self); ++ let (arguments, _) = utils::fnsig_arguments(ctx, self); + + match self.abi(ctx, None) { + 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"); +- Ok(proc_macro2::TokenStream::new()) ++ Ok(proc_macro2::TokenStream::new().into()) + } + 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"); +- Ok(proc_macro2::TokenStream::new()) ++ Ok(proc_macro2::TokenStream::new().into()) + } + 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"); +- Ok(proc_macro2::TokenStream::new()) ++ Ok(proc_macro2::TokenStream::new().into()) + } + 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()) ++ Ok(proc_macro2::TokenStream::new().into()) + } + abi => Ok(quote! { + unsafe extern #abi fn ( #( #arguments ),* ) #ret +- }), ++ } ++ .into()), + } + } + } +@@ -4150,14 +4386,19 @@ impl CodeGenerator for Function { + return None; + } + +- // Pure virtual methods have no actual symbol, so we can't generate +- // something meaningful for them. +- let is_dynamic_function = match self.kind() { +- FunctionKind::Method(ref method_kind) +- if method_kind.is_pure_virtual() => +- { +- return None; ++ let is_pure_virtual = match self.kind() { ++ FunctionKind::Method(ref method_kind) => { ++ method_kind.is_pure_virtual() + } ++ _ => false, ++ }; ++ ++ let is_virtual = matches!( ++ self.kind(), ++ FunctionKind::Method(MethodKind::Virtual { .. }) ++ ); ++ ++ let is_dynamic_function = match self.kind() { + FunctionKind::Function => { + ctx.options().dynamic_library_name.is_some() + } +@@ -4194,10 +4435,11 @@ impl CodeGenerator for Function { + _ => panic!("Signature kind is not a Function: {:?}", signature), + }; + +- let args = utils::fnsig_arguments(ctx, signature); +- let ret = utils::fnsig_return_ty(ctx, signature); ++ let (args, args_attrs) = utils::fnsig_arguments(ctx, signature); ++ let (ret, ret_attr) = utils::fnsig_return_ty(ctx, signature); + +- let mut attributes = vec![]; ++ let mut attributes = args_attrs; ++ attributes.push(ret_attr); + + if ctx.options().rust_features().must_use_function { + let must_use = signature.must_use() || { +@@ -4218,6 +4460,19 @@ impl CodeGenerator for Function { + attributes.push(attributes::doc(comment)); + } + ++ let mut semantic_annotations = ++ CppSemanticAttributeAdder::new(ctx.options(), &mut attributes); ++ ++ if is_pure_virtual { ++ semantic_annotations.is_pure_virtual(); ++ } ++ ++ if is_virtual { ++ semantic_annotations.is_virtual(); ++ } ++ ++ semantic_annotations.visibility(self.visibility()); ++ + let abi = match signature.abi(ctx, Some(name)) { + ClangAbi::Known(Abi::ThisCall) + if !ctx.options().rust_features().thiscall_abi => +@@ -4291,6 +4546,19 @@ impl CodeGenerator for Function { + if times_seen > 0 { + write!(&mut canonical_name, "{}", times_seen).unwrap(); + } ++ if canonical_name != self.name() { ++ semantic_annotations.original_name(self.name()); ++ } ++ ++ if let Some(special_member_kind) = self.special_member() { ++ semantic_annotations.special_member(special_member_kind); ++ } ++ if self.deleted_fn() { ++ semantic_annotations.deleted_fn(); ++ } ++ if self.defaulted_fn() { ++ semantic_annotations.defaulted_fn(); ++ } + + let mut has_link_name_attr = false; + if let Some(link_name) = self.link_name() { +@@ -4345,7 +4613,7 @@ impl CodeGenerator for Function { + args, + args_identifiers, + ret, +- ret_ty, ++ ret_ty.0, + attributes, + ctx, + ); +@@ -4418,8 +4686,9 @@ fn objc_method_codegen( + } + + let signature = method.signature(); +- let fn_args = utils::fnsig_arguments(ctx, signature); +- let fn_ret = utils::fnsig_return_ty(ctx, signature); ++ let (fn_args, _) = utils::fnsig_arguments(ctx, signature); ++ let (fn_ret, _) = utils::fnsig_return_ty(ctx, signature); ++ // We disregard reference vs pointer attributes for objc methods for now. + + let sig = if method.is_class_method() { + quote! { +@@ -4732,7 +5001,13 @@ pub(crate) fn codegen( + + pub(crate) mod utils { + use super::serialize::CSerialize; +- use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque}; ++ use super::{ ++ error, CodegenError, CodegenResult, RustTy, RustTyAnnotation, ++ ToRustTyOrOpaque, ++ }; ++ use crate::codegen::helpers::{ ++ CppSemanticAttributeCreator, CppSemanticAttributeSingle, ++ }; + use crate::ir::context::BindgenContext; + use crate::ir::function::{Abi, ClangAbi, FunctionSig}; + use crate::ir::item::{Item, ItemCanonicalPath}; +@@ -5128,12 +5403,12 @@ pub(crate) mod utils { + ctx: &BindgenContext, + sig: &FunctionSig, + include_arrow: bool, +- ) -> proc_macro2::TokenStream { ++ ) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { + if sig.is_divergent() { + return if include_arrow { +- quote! { -> ! } ++ (quote! { -> ! }, quote! {}) + } else { +- quote! { ! } ++ (quote! { ! }, quote! {}) + }; + } + +@@ -5149,35 +5424,54 @@ pub(crate) mod utils { + + if let TypeKind::Void = canonical_type_kind { + return if include_arrow { +- quote! {} ++ (quote! {}, quote! {}) + } else { +- quote! { () } ++ (quote! { () }, quote! {}) + }; + } + + let ret_ty = sig.return_type().to_rust_ty_or_opaque(ctx, &()); +- if include_arrow { ++ let annotations = ret_ty.annotation; ++ let ret_ty = ret_ty.ts; ++ let ts = if include_arrow { + quote! { -> #ret_ty } + } else { + ret_ty +- } ++ }; ++ ++ let mut semantic_annotation = ++ CppSemanticAttributeSingle::new(ctx.options()); ++ match annotations { ++ super::RustTyAnnotation::None => {} ++ super::RustTyAnnotation::Reference => { ++ semantic_annotation.ret_type_reference() ++ } ++ super::RustTyAnnotation::RValueReference => { ++ semantic_annotation.ret_type_rvalue_reference() ++ } ++ super::RustTyAnnotation::HasUnusedTemplateArgs | ++ super::RustTyAnnotation::Opaque => { ++ semantic_annotation.incomprehensible_param_in_arg_or_return() ++ } ++ }; ++ (ts, semantic_annotation.result()) + } + + pub(crate) fn fnsig_return_ty( + ctx: &BindgenContext, + sig: &FunctionSig, +- ) -> proc_macro2::TokenStream { ++ ) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { + fnsig_return_ty_internal(ctx, sig, /* include_arrow = */ true) + } + + pub(crate) fn fnsig_arguments( + ctx: &BindgenContext, + sig: &FunctionSig, +- ) -> Vec<proc_macro2::TokenStream> { ++ ) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>) { + use super::ToPtr; + + let mut unnamed_arguments = 0; +- let mut args = sig ++ let mut args: (Vec<_>, Vec<_>) = sig + .argument_types() + .iter() + .map(|&(ref name, ty)| { +@@ -5192,15 +5486,19 @@ pub(crate) mod utils { + // the array type derivation. + // + // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html +- let arg_ty = match *arg_ty.canonical_type(ctx).kind() { ++ let arg_details = match *arg_ty.canonical_type(ctx).kind() { + TypeKind::Array(t, _) => { +- let stream = ++ let rust_ty = + if ctx.options().array_pointers_in_arguments { + arg_ty.to_rust_ty_or_opaque(ctx, arg_item) + } else { + t.to_rust_ty_or_opaque(ctx, &()) + }; +- stream.to_ptr(ctx.resolve_type(t).is_const()) ++ let (inner_ty, annotations) = rust_ty.into_outer_type(); ++ RustTy::wraps( ++ inner_ty.to_ptr(ctx.resolve_type(t).is_const()), ++ annotations, ++ ) + } + TypeKind::Pointer(inner) => { + let inner = ctx.resolve_item(inner); +@@ -5209,15 +5507,16 @@ pub(crate) mod utils { + *inner_ty.canonical_type(ctx).kind() + { + let name = ctx.rust_ident(interface.name()); +- quote! { ++ RustTy::new(quote! { + #name +- } ++ }) + } else { + arg_item.to_rust_ty_or_opaque(ctx, &()) + } + } + _ => arg_item.to_rust_ty_or_opaque(ctx, &()), + }; ++ let arg_ty = arg_details.ts; + + let arg_name = match *name { + Some(ref name) => ctx.rust_mangle(name).into_owned(), +@@ -5229,15 +5528,33 @@ pub(crate) mod utils { + + assert!(!arg_name.is_empty()); + let arg_name = ctx.rust_ident(arg_name); ++ let mut semantic_annotation = ++ CppSemanticAttributeSingle::new(ctx.options()); ++ match arg_details.annotation { ++ RustTyAnnotation::None => {} ++ RustTyAnnotation::Reference => { ++ semantic_annotation.arg_type_reference(&arg_name) ++ } ++ RustTyAnnotation::RValueReference => { ++ semantic_annotation.arg_type_rvalue_reference(&arg_name) ++ } ++ RustTyAnnotation::HasUnusedTemplateArgs | ++ RustTyAnnotation::Opaque => semantic_annotation ++ .incomprehensible_param_in_arg_or_return(), ++ }; + +- quote! { +- #arg_name : #arg_ty +- } ++ ( ++ quote! { ++ #arg_name : #arg_ty ++ }, ++ semantic_annotation.result(), ++ ) + }) +- .collect::<Vec<_>>(); ++ .unzip(); + + if sig.is_variadic() { +- args.push(quote! { ... }) ++ args.0.push(quote! { ... }); ++ args.1.push(quote! {}); + } + + args +@@ -5279,12 +5596,13 @@ pub(crate) mod utils { + let args = sig.argument_types().iter().map(|&(_, ty)| { + let arg_item = ctx.resolve_item(ty); + +- arg_item.to_rust_ty_or_opaque(ctx, &()) ++ arg_item.to_rust_ty_or_opaque(ctx, &()).ignore_annotations() + }); + + let ret_ty = fnsig_return_ty_internal( + ctx, sig, /* include_arrow = */ false, +- ); ++ ) ++ .0; + quote! { + *const ::block::Block<(#(#args,)*), #ret_ty> + } +diff --git a/ir/analysis/has_vtable.rs b/ir/analysis/has_vtable.rs +index 980a551..12b1fe0 100644 +--- a/ir/analysis/has_vtable.rs ++++ b/ir/analysis/has_vtable.rs +@@ -164,7 +164,7 @@ impl<'ctx> MonotoneFramework for HasVtableAnalysis<'ctx> { + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) | + TypeKind::ResolvedTypeRef(t) | +- TypeKind::Reference(t) => { ++ TypeKind::Reference(t, _) => { + trace!( + " aliases and references forward to their inner type" + ); +diff --git a/ir/comp.rs b/ir/comp.rs +index 89e77e1..1ff8961 100644 +--- a/ir/comp.rs ++++ b/ir/comp.rs +@@ -4,6 +4,7 @@ use super::analysis::Sizedness; + use super::annotations::Annotations; + use super::context::{BindgenContext, FunctionId, ItemId, TypeId, VarId}; + use super::dot::DotAttributes; ++use super::function::Visibility; + use super::item::{IsOpaque, Item}; + use super::layout::Layout; + use super::template::TemplateParameters; +@@ -72,6 +73,18 @@ impl MethodKind { + } + } + ++// The kind of C++ special member. ++// TODO: We don't currently cover copy assignment or move assignment operator ++// because libclang doesn't provide a way to query for them. ++#[derive(Debug, Copy, Clone, PartialEq)] ++pub enum SpecialMemberKind { ++ DefaultConstructor, ++ CopyConstructor, ++ MoveConstructor, ++ Destructor, ++ AssignmentOperator, ++} ++ + /// A struct representing a C++ method, either static, normal, or virtual. + #[derive(Debug)] + pub(crate) struct Method { +@@ -976,6 +989,10 @@ pub(crate) struct CompInfo { + /// Whether this is a struct or a union. + kind: CompKind, + ++ /// The visibility of this struct or union if it was declared inside of ++ /// another type. Top-level types always have public visibility. ++ visibility: Visibility, ++ + /// The members of this struct or union. + fields: CompFields, + +@@ -1055,6 +1072,7 @@ impl CompInfo { + pub(crate) fn new(kind: CompKind) -> Self { + CompInfo { + kind, ++ visibility: Visibility::Public, + fields: CompFields::default(), + template_params: vec![], + methods: vec![], +@@ -1166,6 +1184,11 @@ impl CompInfo { + } + } + ++ /// Returns the visibility of the type. ++ pub fn visibility(&self) -> Visibility { ++ self.visibility ++ } ++ + /// 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. +@@ -1255,6 +1278,7 @@ impl CompInfo { + debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor); + + let mut ci = CompInfo::new(kind); ++ ci.visibility = Visibility::from(cursor.access_specifier()); + ci.is_forward_declaration = + location.map_or(true, |cur| match cur.kind() { + CXCursor_ParmDecl => true, +diff --git a/ir/context.rs b/ir/context.rs +index a5c14a8..80e7f8d 100644 +--- a/ir/context.rs ++++ b/ir/context.rs +@@ -1971,6 +1971,9 @@ If you encounter an error missing from this list, please file an issue or a PR!" + CXType_Short => TypeKind::Int(IntKind::Short), + CXType_UShort => TypeKind::Int(IntKind::UShort), + CXType_WChar => TypeKind::Int(IntKind::WChar), ++ CXType_Char16 if self.options().use_distinct_char16_t => { ++ TypeKind::Int(IntKind::Char16) ++ } + CXType_Char16 => TypeKind::Int(IntKind::U16), + CXType_Char32 => TypeKind::Int(IntKind::U32), + CXType_Long => TypeKind::Int(IntKind::Long), +diff --git a/ir/enum_ty.rs b/ir/enum_ty.rs +index 70cf0ea..a863340 100644 +--- a/ir/enum_ty.rs ++++ b/ir/enum_ty.rs +@@ -2,6 +2,7 @@ + + use super::super::codegen::EnumVariation; + use super::context::{BindgenContext, TypeId}; ++use super::function::Visibility; + use super::item::Item; + use super::ty::{Type, TypeKind}; + use crate::clang; +@@ -32,6 +33,10 @@ pub(crate) struct Enum { + + /// The different variants, with explicit values. + variants: Vec<EnumVariant>, ++ ++ /// The visibility of this enum if it was declared inside of ++ /// another type. Top-level types always have public visibility. ++ pub(crate) visibility: Visibility, + } + + impl Enum { +@@ -39,8 +44,13 @@ impl Enum { + pub(crate) fn new( + repr: Option<TypeId>, + variants: Vec<EnumVariant>, ++ visibility: Visibility, + ) -> Self { +- Enum { repr, variants } ++ Enum { ++ repr, ++ variants, ++ visibility, ++ } + } + + /// Get this enumeration's representation. +@@ -56,6 +66,7 @@ impl Enum { + /// Construct an enumeration from the given Clang type. + pub(crate) fn from_ty( + ty: &clang::Type, ++ visibility: Visibility, + ctx: &mut BindgenContext, + ) -> Result<Self, ParseError> { + use clang_sys::*; +@@ -147,7 +158,7 @@ impl Enum { + } + CXChildVisit_Continue + }); +- Ok(Enum::new(repr, variants)) ++ Ok(Enum::new(repr, variants, visibility)) + } + + fn is_matching_enum( +diff --git a/ir/function.rs b/ir/function.rs +index fab380e..d38c60e 100644 +--- a/ir/function.rs ++++ b/ir/function.rs +@@ -1,6 +1,6 @@ + //! Intermediate representation for C/C++ functions and methods. + +-use super::comp::MethodKind; ++use super::comp::{MethodKind, SpecialMemberKind}; + use super::context::{BindgenContext, TypeId}; + use super::dot::DotAttributes; + use super::item::Item; +@@ -9,7 +9,9 @@ use super::ty::TypeKind; + use crate::callbacks::{ItemInfo, ItemKind}; + use crate::clang::{self, Attribute}; + use crate::parse::{ClangSubItemParser, ParseError, ParseResult}; +-use clang_sys::{self, CXCallingConv}; ++use clang_sys::{ ++ self, CXCallingConv, CX_CXXAccessSpecifier, CX_CXXPrivate, CX_CXXProtected, ++}; + + use quote::TokenStreamExt; + use std::io; +@@ -70,6 +72,75 @@ pub(crate) enum Linkage { + Internal, + } + ++/// Visibility ++#[derive(Debug, Clone, Copy)] ++pub enum Visibility { ++ Public, ++ Protected, ++ Private, ++} ++ ++impl From<CX_CXXAccessSpecifier> for Visibility { ++ fn from(access_specifier: CX_CXXAccessSpecifier) -> Self { ++ if access_specifier == CX_CXXPrivate { ++ Visibility::Private ++ } else if access_specifier == CX_CXXProtected { ++ Visibility::Protected ++ } else { ++ Visibility::Public ++ } ++ } ++} ++ ++/// Autocxx specialized function information ++#[derive(Debug)] ++pub(crate) struct AutocxxFuncInfo { ++ /// C++ Special member kind, if applicable ++ special_member: Option<SpecialMemberKind>, ++ /// Whether it is private ++ visibility: Visibility, ++ /// =delete ++ is_deleted: bool, ++ /// =default ++ is_defaulted: bool, ++} ++ ++impl AutocxxFuncInfo { ++ fn new( ++ special_member: Option<SpecialMemberKind>, ++ visibility: Visibility, ++ is_deleted: bool, ++ is_defaulted: bool, ++ ) -> Self { ++ Self { ++ special_member, ++ visibility, ++ is_deleted, ++ is_defaulted, ++ } ++ } ++ ++ /// Get this function's C++ special member kind. ++ pub fn special_member(&self) -> Option<SpecialMemberKind> { ++ self.special_member ++ } ++ ++ /// Whether it is private ++ pub fn visibility(&self) -> Visibility { ++ self.visibility ++ } ++ ++ /// Whether this is a function that's been deleted (=delete) ++ pub fn deleted_fn(&self) -> bool { ++ self.is_deleted ++ } ++ ++ /// Whether this is a function that's been deleted (=default) ++ pub fn defaulted_fn(&self) -> bool { ++ self.is_defaulted ++ } ++} ++ + /// A function declaration, with a signature, arguments, and argument names. + /// + /// The argument names vector must be the same length as the ones in the +@@ -93,6 +164,9 @@ pub(crate) struct Function { + + /// The linkage of the function. + linkage: Linkage, ++ ++ /// Autocxx extension information ++ autocxx: AutocxxFuncInfo, + } + + impl Function { +@@ -104,6 +178,7 @@ impl Function { + signature: TypeId, + kind: FunctionKind, + linkage: Linkage, ++ autocxx: AutocxxFuncInfo, + ) -> Self { + Function { + name, +@@ -112,6 +187,7 @@ impl Function { + signature, + kind, + linkage, ++ autocxx, + } + } + +@@ -144,6 +220,26 @@ impl Function { + pub(crate) fn linkage(&self) -> Linkage { + self.linkage + } ++ ++ /// Get this function's C++ special member kind. ++ pub fn special_member(&self) -> Option<SpecialMemberKind> { ++ self.autocxx.special_member() ++ } ++ ++ /// Whether it is private ++ pub fn visibility(&self) -> Visibility { ++ self.autocxx.visibility() ++ } ++ ++ /// Whether this is a function that's been deleted (=delete) ++ pub fn deleted_fn(&self) -> bool { ++ self.autocxx.deleted_fn() ++ } ++ ++ /// Whether this is a function that's been deleted (=default) ++ pub fn defaulted_fn(&self) -> bool { ++ self.autocxx.defaulted_fn() ++ } + } + + impl DotAttributes for Function { +@@ -422,15 +518,6 @@ impl FunctionSig { + + let spelling = cursor.spelling(); + +- // Don't parse operatorxx functions in C++ +- let is_operator = |spelling: &str| { +- spelling.starts_with("operator") && +- !clang::is_valid_identifier(spelling) +- }; +- if is_operator(&spelling) { +- return Err(ParseError::Continue); +- } +- + // Constructors of non-type template parameter classes for some reason + // include the template parameter in their name. Just skip them, since + // we don't handle well non-type template parameters anyway. +@@ -513,7 +600,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"); +@@ -537,7 +627,7 @@ impl FunctionSig { + Item::builtin_type(TypeKind::Pointer(class), false, ctx); + args.insert(0, (Some("this".into()), ptr)); + } else if is_virtual { +- let void = Item::builtin_type(TypeKind::Void, false, ctx); ++ let void = Item::builtin_type(TypeKind::Void, is_const, ctx); + let ptr = + Item::builtin_type(TypeKind::Pointer(void), false, ctx); + args.insert(0, (Some("this".into()), ptr)); +@@ -685,9 +775,7 @@ impl ClangSubItemParser for Function { + return Err(ParseError::Continue); + } + +- if cursor.access_specifier() == CX_CXXPrivate { +- return Err(ParseError::Continue); +- } ++ let visibility = Visibility::from(cursor.access_specifier()); + + let linkage = cursor.linkage(); + let linkage = match linkage { +@@ -707,10 +795,6 @@ impl ClangSubItemParser for Function { + return Err(ParseError::Continue); + } + +- if cursor.is_deleted_function() { +- return Err(ParseError::Continue); +- } +- + // We cannot handle `inline` functions that are not `static`. + if context.options().wrap_static_fns && + cursor.is_inlined_function() && +@@ -749,7 +833,23 @@ impl ClangSubItemParser for Function { + } + assert!(!name.is_empty(), "Empty function name."); + +- let mangled_name = cursor_mangling(context, &cursor); ++ let operator_suffix = name.strip_prefix("operator"); ++ let special_member = if let Some(operator_suffix) = operator_suffix { ++ // We can't represent operatorxx functions as-is because ++ // they are not valid identifiers ++ if context.options().represent_cxx_operators { ++ let (new_suffix, special_member) = match operator_suffix { ++ "=" => ("equals", SpecialMemberKind::AssignmentOperator), ++ _ => return Err(ParseError::Continue), ++ }; ++ name = format!("operator_{}", new_suffix); ++ Some(special_member) ++ } else { ++ return Err(ParseError::Continue); ++ } ++ } else { ++ None ++ }; + + let link_name = context.options().last_callback(|callbacks| { + callbacks.generated_link_name_override(ItemInfo { +@@ -758,13 +858,36 @@ impl ClangSubItemParser for Function { + }) + }); + ++ let mangled_name = cursor_mangling(context, &cursor); ++ ++ let special_member = special_member.or_else(|| { ++ if cursor.is_default_constructor() { ++ Some(SpecialMemberKind::DefaultConstructor) ++ } else if cursor.is_copy_constructor() { ++ Some(SpecialMemberKind::CopyConstructor) ++ } else if cursor.is_move_constructor() { ++ Some(SpecialMemberKind::MoveConstructor) ++ } else if cursor.kind() == clang_sys::CXCursor_Destructor { ++ Some(SpecialMemberKind::Destructor) ++ } else { ++ None ++ } ++ }); ++ ++ let autocxx_info = AutocxxFuncInfo::new( ++ special_member, ++ visibility, ++ cursor.is_deleted_function(), ++ cursor.is_defaulted_function(), ++ ); + let function = Self::new( +- name.clone(), ++ name, + mangled_name, + link_name, + sig, + kind, + linkage, ++ autocxx_info, + ); + + Ok(ParseResult::New(function, Some(cursor))) +diff --git a/ir/int.rs b/ir/int.rs +index 4251b37..ea2456e 100644 +--- a/ir/int.rs ++++ b/ir/int.rs +@@ -54,9 +54,12 @@ pub enum IntKind { + /// A 16-bit signed integer. + I16, + +- /// Either a `char16_t` or a `wchar_t`. ++ /// A 16-bit integer, used only for enum size representation. + U16, + ++ /// Either a `char16_t` or a `wchar_t`. ++ Char16, ++ + /// A 32-bit signed integer. + I32, + +@@ -94,7 +97,7 @@ impl IntKind { + // to know whether it is or not right now (unlike char, there's no + // WChar_S / WChar_U). + Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 | +- WChar | U32 | U64 | U128 => false, ++ Char16 | WChar | U32 | U64 | U128 => false, + + SChar | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 | + I128 => true, +@@ -112,7 +115,7 @@ impl IntKind { + use self::IntKind::*; + Some(match *self { + Bool | UChar | SChar | U8 | I8 | Char { .. } => 1, +- U16 | I16 => 2, ++ U16 | I16 | Char16 => 2, + U32 | I32 => 4, + U64 | I64 => 8, + I128 | U128 => 16, +diff --git a/ir/item.rs b/ir/item.rs +index a50d267..c35b2ac 100644 +--- a/ir/item.rs ++++ b/ir/item.rs +@@ -823,6 +823,38 @@ impl Item { + } + } + ++ /// Get this item's original C++ name, including any containing types, but without ++ /// the namespace name. For nested types, the C++ name differs from the Rust name, e.g. ++ /// a nested C++ type `A::B` would correspond to the Rust type `A_B`. ++ /// If the item or any of its containing types is anonymous, returns None. ++ pub fn original_name(&self, ctx: &BindgenContext) -> Option<String> { ++ let target = ctx.resolve_item(self.name_target(ctx)); ++ ++ // Get item and all ancestors until the first enclosing namespace. ++ let ancestors: Vec<_> = target ++ .ancestors(ctx) ++ .map(|id| ctx.resolve_item(id)) ++ .take_while(|item| !item.is_module()) ++ .collect(); ++ ++ if ancestors.iter().any(|item| item.is_anon()) { ++ return None; ++ } ++ ++ let mut names: Vec<_> = ancestors ++ .iter() ++ .map(|item| { ++ let target = ctx.resolve_item(item.name_target(ctx)); ++ target.base_name(ctx) ++ }) ++ .filter(|name| !name.is_empty()) ++ .collect(); ++ ++ names.reverse(); ++ ++ Some(names.join("::")) ++ } ++ + /// Get the canonical name without taking into account the replaces + /// annotation. + /// +diff --git a/ir/layout.rs b/ir/layout.rs +index ba944b0..17ca66e 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(crate) struct Layout { ++pub struct Layout { + /// The size (in bytes) of this layout. +- pub(crate) size: usize, ++ pub size: usize, + /// The alignment (in bytes) of this layout. +- pub(crate) align: usize, ++ pub align: usize, + /// Whether this layout's members are packed or not. +- pub(crate) packed: bool, ++ pub packed: bool, + } + + #[test] +diff --git a/ir/template.rs b/ir/template.rs +index 4dd8442..a1f8f5f 100644 +--- a/ir/template.rs ++++ b/ir/template.rs +@@ -31,6 +31,7 @@ use super::context::{BindgenContext, ItemId, TypeId}; + use super::item::{IsOpaque, Item, ItemAncestors}; + use super::traversal::{EdgeKind, Trace, Tracer}; + use crate::clang; ++use itertools::{Either, Itertools}; + + /// Template declaration (and such declaration's template parameters) related + /// methods. +@@ -143,8 +144,9 @@ pub(crate) trait TemplateParameters: Sized { + + /// Get only the set of template parameters that this item uses. This is a + /// subset of `all_template_params` and does not necessarily contain any of +- /// `self_template_params`. +- fn used_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> ++ /// `self_template_params`. If any are unused, true will be returned ++ /// in the second tuple element ++ fn used_template_params(&self, ctx: &BindgenContext) -> (Vec<TypeId>, bool) + where + Self: AsRef<ItemId>, + { +@@ -154,11 +156,18 @@ pub(crate) trait TemplateParameters: Sized { + ); + + let id = *self.as_ref(); +- ctx.resolve_item(id) ++ let (used, unused): (Vec<_>, Vec<_>) = ctx ++ .resolve_item(id) + .all_template_params(ctx) + .into_iter() +- .filter(|p| ctx.uses_template_parameter(id, *p)) +- .collect() ++ .partition_map(|p| { ++ if ctx.uses_template_parameter(id, p) { ++ Either::Left(p) ++ } else { ++ Either::Right(true) ++ } ++ }); ++ (used, !unused.is_empty()) + } + } + +diff --git a/ir/ty.rs b/ir/ty.rs +index 8c505aa..5bf3841 100644 +--- a/ir/ty.rs ++++ b/ir/ty.rs +@@ -14,6 +14,7 @@ use super::template::{ + }; + use super::traversal::{EdgeKind, Trace, Tracer}; + use crate::clang::{self, Cursor}; ++use crate::ir::function::Visibility; + use crate::parse::{ParseError, ParseResult}; + use std::borrow::Cow; + use std::io; +@@ -253,7 +254,9 @@ impl Type { + ) -> Option<Cow<'a, str>> { + let name_info = match *self.kind() { + TypeKind::Pointer(inner) => Some((inner, Cow::Borrowed("ptr"))), +- TypeKind::Reference(inner) => Some((inner, Cow::Borrowed("ref"))), ++ TypeKind::Reference(inner, _) => { ++ Some((inner, Cow::Borrowed("ref"))) ++ } + TypeKind::Array(inner, length) => { + Some((inner, format!("array{}", length).into())) + } +@@ -538,7 +541,7 @@ impl TemplateParameters for TypeKind { + TypeKind::Enum(_) | + TypeKind::Pointer(_) | + TypeKind::BlockPointer(_) | +- TypeKind::Reference(_) | ++ TypeKind::Reference(..) | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::TypeParam | + TypeKind::Alias(_) | +@@ -616,7 +619,8 @@ pub(crate) enum TypeKind { + BlockPointer(TypeId), + + /// A reference to a type, as in: int& foo(). +- Reference(TypeId), ++ /// The bool represents whether it's rvalue. ++ Reference(TypeId, bool), + + /// An instantiation of an abstract template definition with a set of + /// concrete template arguments. +@@ -1044,14 +1048,23 @@ impl Type { + } + // XXX: RValueReference is most likely wrong, but I don't think we + // can even add bindings for that, so huh. +- CXType_RValueReference | CXType_LValueReference => { ++ CXType_LValueReference => { ++ let inner = Item::from_ty_or_ref( ++ ty.pointee_type().unwrap(), ++ location, ++ None, ++ ctx, ++ ); ++ TypeKind::Reference(inner, false) ++ } ++ CXType_RValueReference => { + let inner = Item::from_ty_or_ref( + ty.pointee_type().unwrap(), + location, + None, + ctx, + ); +- TypeKind::Reference(inner) ++ TypeKind::Reference(inner, true) + } + // XXX DependentSizedArray is wrong + CXType_VariableArray | CXType_DependentSizedArray => { +@@ -1109,7 +1122,10 @@ impl Type { + } + } + CXType_Enum => { +- let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?"); ++ let visibility = ++ Visibility::from(cursor.access_specifier()); ++ let enum_ = Enum::from_ty(ty, visibility, ctx) ++ .expect("Not an enum?"); + + if !is_anonymous { + let pretty_name = ty.spelling(); +@@ -1222,7 +1238,7 @@ impl Trace for Type { + } + match *self.kind() { + TypeKind::Pointer(inner) | +- TypeKind::Reference(inner) | ++ TypeKind::Reference(inner, _) | + TypeKind::Array(inner, _) | + TypeKind::Vector(inner, _) | + TypeKind::BlockPointer(inner) | +diff --git a/lib.rs b/lib.rs +index 482c1a3..e800136 100644 +--- a/lib.rs ++++ b/lib.rs +@@ -1,5 +1,7 @@ + //! Generate Rust bindings for C and C++ libraries. + //! ++//! This is a slightly forked version for use by `autocxx`. ++//! + //! Provide a C/C++ header file, receive Rust FFI code to call into C/C++ + //! functions and use types defined in the header. + //! +@@ -1211,6 +1213,7 @@ fn get_target_dependent_env_var( + /// 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: + /// ``` ++/// use autocxx_bindgen as bindgen; + /// use bindgen::builder; + /// let bindings = builder() + /// .header("path/to/input/header") +diff --git a/options/mod.rs b/options/mod.rs +index c60da71..54b44eb 100644 +--- a/options/mod.rs ++++ b/options/mod.rs +@@ -153,6 +153,61 @@ 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 emit C++ semantics attributes. ++ cpp_semantic_attributes: bool { ++ methods: { ++ /// If this is true, add attributes with details of underlying C++ semantics. ++ /// Disabled by default. ++ pub fn cpp_semantic_attributes(mut self, doit: bool) -> Builder { ++ self.options.cpp_semantic_attributes = doit; ++ self ++ } ++ }, ++ as_args: "--cpp-semantic-attributes", ++ }, ++ ++ /// Whether we should output information about C++ overloaded operators. ++ represent_cxx_operators: bool { ++ methods: { ++ /// If this is true, output existence of C++ overloaded operators. ++ /// At present, only operator= is noted. ++ /// Disabled by default. ++ pub fn represent_cxx_operators(mut self, doit: bool) -> Builder { ++ self.options.represent_cxx_operators = doit; ++ self ++ } ++ }, ++ as_args: "--represent-cxx-operators", ++ }, ++ ++ /// Whether we should distinguish between 'char16_t' and 'u16' ++ use_distinct_char16_t: bool { ++ methods: { ++ /// If this is true, denote 'char16_t' as a separate type from 'u16' ++ /// Disabled by default. ++ pub fn use_distinct_char16_t(mut self, doit: bool) -> Builder { ++ self.options.use_distinct_char16_t = doit; ++ self ++ } ++ }, ++ as_args: "--use-distinct-char16-t", ++ }, ++ + /// Types that have been blocklisted and should not appear anywhere in the generated code. + blocklisted_types: RegexSet { + methods: { |