diff options
Diffstat (limited to 'libbindgen/src/ir')
-rw-r--r-- | libbindgen/src/ir/comp.rs | 70 | ||||
-rw-r--r-- | libbindgen/src/ir/function.rs | 13 | ||||
-rw-r--r-- | libbindgen/src/ir/item.rs | 23 |
3 files changed, 69 insertions, 37 deletions
diff --git a/libbindgen/src/ir/comp.rs b/libbindgen/src/ir/comp.rs index d2ace023..c351a152 100644 --- a/libbindgen/src/ir/comp.rs +++ b/libbindgen/src/ir/comp.rs @@ -23,6 +23,9 @@ pub enum CompKind { /// The kind of C++ method. #[derive(Debug, Copy, Clone, PartialEq)] pub enum MethodKind { + /// A constructor. We represent it as method for convenience, to avoid code + /// duplication. + Constructor, /// A static method. Static, /// A normal method. @@ -45,7 +48,7 @@ pub struct Method { impl Method { /// Construct a new `Method`. - fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self { + pub fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self { Method { kind: kind, signature: signature, @@ -58,6 +61,11 @@ impl Method { self.kind } + /// Is this a constructor? + pub fn is_constructor(&self) -> bool { + self.kind == MethodKind::Constructor + } + /// Is this a virtual method? pub fn is_virtual(&self) -> bool { self.kind == MethodKind::Virtual @@ -167,6 +175,9 @@ pub struct CompInfo { /// The method declarations inside this class, if in C++ mode. methods: Vec<Method>, + /// The different constructors this struct or class contains. + constructors: Vec<ItemId>, + /// Vector of classes this one inherits from. base_members: Vec<ItemId>, @@ -235,6 +246,7 @@ impl CompInfo { fields: vec![], template_args: vec![], methods: vec![], + constructors: vec![], base_members: vec![], ref_template: None, inner_types: vec![], @@ -454,6 +466,10 @@ impl CompInfo { &self.methods } + pub fn constructors(&self) -> &[ItemId] { + &self.constructors + } + /// What kind of compound type is this? pub fn kind(&self) -> CompKind { self.kind @@ -651,14 +667,15 @@ impl CompInfo { .expect("BaseSpecifier"); ci.base_members.push(type_id); } + CXCursor_Constructor | + CXCursor_Destructor | CXCursor_CXXMethod => { let is_virtual = cur.method_is_virtual(); let is_static = cur.method_is_static(); debug_assert!(!(is_static && is_virtual), "How?"); - if !ci.has_vtable { - ci.has_vtable = is_virtual; - } + ci.has_destructor |= cur.kind() == CXCursor_Destructor; + ci.has_vtable |= is_virtual; let linkage = cur.linkage(); if linkage != CXLinkage_External { @@ -699,30 +716,34 @@ impl CompInfo { // NB: This gets us an owned `Function`, not a // `FunctionSig`. - let method_signature = + let signature = Item::parse(cur, Some(potential_id), ctx) .expect("CXXMethod"); - let is_const = cur.method_is_const(); - let method_kind = if is_static { - MethodKind::Static - } else if is_virtual { - MethodKind::Virtual - } else { - MethodKind::Normal - }; - - let method = - Method::new(method_kind, method_signature, is_const); - - ci.methods.push(method); - } - CXCursor_Destructor => { - if cur.method_is_virtual() { - // FIXME: Push to the method list? - ci.has_vtable = true; + match cur.kind() { + CXCursor_Constructor => { + ci.constructors.push(signature); + } + // TODO(emilio): Bind the destructor? + CXCursor_Destructor => {}, + CXCursor_CXXMethod => { + let is_const = cur.method_is_const(); + let method_kind = if is_static { + MethodKind::Static + } else if is_virtual { + MethodKind::Virtual + } else { + MethodKind::Normal + }; + + let method = Method::new(method_kind, + signature, + is_const); + + ci.methods.push(method); + } + _ => unreachable!("How can we see this here?"), } - ci.has_destructor = true; } CXCursor_NonTypeTemplateParameter => { ci.has_non_type_template_params = true; @@ -746,7 +767,6 @@ impl CompInfo { // Intentionally not handled CXCursor_CXXAccessSpecifier | CXCursor_CXXFinalAttr | - CXCursor_Constructor | CXCursor_FunctionTemplate | CXCursor_ConversionFunction => {} _ => { diff --git a/libbindgen/src/ir/function.rs b/libbindgen/src/ir/function.rs index 5a864cfc..c4c26c62 100644 --- a/libbindgen/src/ir/function.rs +++ b/libbindgen/src/ir/function.rs @@ -147,6 +147,7 @@ impl FunctionSig { }; let mut args: Vec<_> = match cursor.kind() { CXCursor_FunctionDecl | + CXCursor_Constructor | CXCursor_CXXMethod => { // For CXCursor_FunctionDecl, cursor.args() is the reliable way // to get parameter names and types. @@ -184,10 +185,12 @@ impl FunctionSig { } }; - if cursor.kind() == CXCursor_CXXMethod { - let is_const = cursor.method_is_const(); - let is_virtual = cursor.method_is_virtual(); - let is_static = cursor.method_is_static(); + let is_method = cursor.kind() == CXCursor_CXXMethod; + + if is_method || cursor.kind() == CXCursor_Constructor { + 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 { let class = Item::parse(cursor.semantic_parent(), None, ctx) .expect("Expected to parse the class"); @@ -240,6 +243,8 @@ impl ClangSubItemParser for Function { use clangll::*; match cursor.kind() { CXCursor_FunctionDecl | + CXCursor_Constructor | + CXCursor_Destructor | CXCursor_CXXMethod => {} _ => return Err(ParseError::Continue), }; diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs index 6601216e..11ec7d99 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -654,19 +654,26 @@ impl Item { /// Get the overload index for this method. If this is not a method, return /// `None`. - fn method_overload_index(&self, ctx: &BindgenContext) -> Option<usize> { + fn overload_index(&self, ctx: &BindgenContext) -> Option<usize> { self.func_name().and_then(|func_name| { let parent = ctx.resolve_item(self.parent_id()); if let ItemKind::Type(ref ty) = *parent.kind() { if let TypeKind::Comp(ref ci) = *ty.kind() { - return ci.methods() + // All the constructors have the same name, so no need to + // resolve and check. + return ci.constructors() .iter() - .filter(|method| { - let item = ctx.resolve_item(method.signature()); - let func = item.expect_function(); - func.name() == func_name + .position(|c| *c == self.id()) + .or_else(|| { + ci.methods() + .iter() + .filter(|m| { + let item = ctx.resolve_item(m.signature()); + let func = item.expect_function(); + func.name() == func_name + }) + .position(|m| m.signature() == self.id()) }) - .position(|method| method.signature() == self.id()); } } @@ -704,7 +711,7 @@ impl Item { ItemKind::Function(ref fun) => { let mut name = fun.name().to_owned(); - if let Some(idx) = self.method_overload_index(ctx) { + if let Some(idx) = self.overload_index(ctx) { if idx > 0 { write!(&mut name, "{}", idx).unwrap(); } |