aboutsummaryrefslogtreecommitdiff
path: root/ir/function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ir/function.rs')
-rw-r--r--ir/function.rs167
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)))