diff options
Diffstat (limited to 'ir/function.rs')
-rw-r--r-- | ir/function.rs | 167 |
1 files changed, 145 insertions, 22 deletions
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))) |