diff options
-rw-r--r-- | bindgen-integration/cpp/Test.h | 4 | ||||
-rw-r--r-- | src/clang.rs | 7 | ||||
-rw-r--r-- | src/codegen/mod.rs | 24 | ||||
-rw-r--r-- | src/ir/comp.rs | 71 | ||||
-rw-r--r-- | src/ir/function.rs | 13 | ||||
-rw-r--r-- | src/ir/item.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/issue-1197-pure-virtual-stuff.rs | 29 | ||||
-rw-r--r-- | tests/headers/issue-1197-pure-virtual-stuff.hpp | 6 | ||||
-rw-r--r-- | tests/headers/ref_argument_array.hpp | 2 |
9 files changed, 125 insertions, 35 deletions
diff --git a/bindgen-integration/cpp/Test.h b/bindgen-integration/cpp/Test.h index 7ddb98bd..4ab8373e 100644 --- a/bindgen-integration/cpp/Test.h +++ b/bindgen-integration/cpp/Test.h @@ -15,6 +15,10 @@ public: static const int* countdown(); }; +class ITest { + virtual void foo() = 0; +}; + namespace testing { typedef Test TypeAlias; diff --git a/src/clang.rs b/src/clang.rs index 223bfc46..c0c96e5e 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -606,11 +606,16 @@ impl Cursor { unsafe { clang_CXXMethod_isConst(self.x) != 0 } } - /// Is this cursor's referent a member function that is declared `const`? + /// Is this cursor's referent a member function that is virtual? pub fn method_is_virtual(&self) -> bool { unsafe { clang_CXXMethod_isVirtual(self.x) != 0 } } + /// Is this cursor's referent a member function that is pure virtual? + pub fn method_is_pure_virtual(&self) -> bool { + unsafe { clang_CXXMethod_isPureVirtual(self.x) != 0 } + } + /// Is this cursor's referent a struct or class with virtual members? pub fn is_virtual_base(&self) -> bool { unsafe { clang_isVirtualBase(self.x) != 0 } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index b8893f9c..15885d57 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -26,7 +26,7 @@ use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDerivePartialEq, CanDeriveEq, CanDerive}; use ir::dot; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; -use ir::function::{Abi, Function, FunctionSig, Linkage}; +use ir::function::{Abi, Function, FunctionKind, FunctionSig, Linkage}; use ir::int::IntKind; use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath}; use ir::item_kind::ItemKind; @@ -1878,13 +1878,8 @@ impl CodeGenerator for CompInfo { } if ctx.options().codegen_config.destructors { - if let Some((is_virtual, destructor)) = self.destructor() { - let kind = if is_virtual { - MethodKind::VirtualDestructor - } else { - MethodKind::Destructor - }; - + if let Some((kind, destructor)) = self.destructor() { + debug_assert!(kind.is_destructor()); Method::new(kind, destructor, false).codegen_method( ctx, &mut methods, @@ -1990,9 +1985,9 @@ impl MethodCodegen for Method { match self.kind() { MethodKind::Constructor => cc.constructors, MethodKind::Destructor => cc.destructors, - MethodKind::VirtualDestructor => cc.destructors, + MethodKind::VirtualDestructor { .. } => cc.destructors, MethodKind::Static | MethodKind::Normal | - MethodKind::Virtual => cc.methods, + MethodKind::Virtual { .. } => cc.methods, } }); @@ -3174,6 +3169,15 @@ impl CodeGenerator for Function { Linkage::External => {} } + // Pure virtual methods have no actual symbol, so we can't generate + // something meaningful for them. + match self.kind() { + FunctionKind::Method(ref method_kind) if method_kind.is_pure_virtual() => { + return; + } + _ => {}, + } + // Similar to static member variables in a class template, we can't // generate bindings to template functions, because the set of // instantiations is open ended and we have no way of knowing which diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 58bd3d3c..5008dcfd 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -37,13 +37,40 @@ pub enum MethodKind { /// A destructor. Destructor, /// A virtual destructor. - VirtualDestructor, + VirtualDestructor { + /// Whether it's pure virtual. + pure_virtual: bool, + }, /// A static method. Static, /// A normal method. Normal, /// A virtual method. - Virtual, + Virtual { + /// Whether it's pure virtual. + pure_virtual: bool, + }, +} + + +impl MethodKind { + /// Is this a destructor method? + pub fn is_destructor(&self) -> bool { + match *self { + MethodKind::Destructor | + MethodKind::VirtualDestructor { .. } => true, + _ => false, + } + } + + /// Is this a pure virtual method? + pub fn is_pure_virtual(&self) -> bool { + match *self { + MethodKind::Virtual { pure_virtual } | + MethodKind::VirtualDestructor { pure_virtual } => pure_virtual, + _ => false, + } + } } /// A struct representing a C++ method, either static, normal, or virtual. @@ -73,12 +100,6 @@ impl Method { self.kind } - /// Is this a destructor method? - pub fn is_destructor(&self) -> bool { - self.kind == MethodKind::Destructor || - self.kind == MethodKind::VirtualDestructor - } - /// Is this a constructor? pub fn is_constructor(&self) -> bool { self.kind == MethodKind::Constructor @@ -86,8 +107,11 @@ impl Method { /// Is this a virtual method? pub fn is_virtual(&self) -> bool { - self.kind == MethodKind::Virtual || - self.kind == MethodKind::VirtualDestructor + match self.kind { + MethodKind::Virtual { .. } | + MethodKind::VirtualDestructor { .. } => true, + _ => false, + } } /// Is this a static method? @@ -960,7 +984,7 @@ pub struct CompInfo { /// The destructor of this type. The bool represents whether this destructor /// is virtual. - destructor: Option<(bool, FunctionId)>, + destructor: Option<(MethodKind, FunctionId)>, /// Vector of classes this one inherits from. base_members: Vec<Base>, @@ -1104,7 +1128,7 @@ impl CompInfo { } /// Get this type's destructor. - pub fn destructor(&self) -> Option<(bool, FunctionId)> { + pub fn destructor(&self) -> Option<(MethodKind, FunctionId)> { self.destructor } @@ -1355,14 +1379,23 @@ impl CompInfo { ci.constructors.push(signature); } CXCursor_Destructor => { - ci.destructor = Some((is_virtual, signature)); + let kind = if is_virtual { + MethodKind::VirtualDestructor { + pure_virtual: cur.method_is_pure_virtual(), + } + } else { + MethodKind::Destructor + }; + ci.destructor = Some((kind, signature)); } CXCursor_CXXMethod => { let is_const = cur.method_is_const(); let method_kind = if is_static { MethodKind::Static } else if is_virtual { - MethodKind::Virtual + MethodKind::Virtual { + pure_virtual: cur.method_is_pure_virtual(), + } } else { MethodKind::Normal }; @@ -1658,11 +1691,11 @@ impl Trace for CompInfo { } for method in self.methods() { - if method.is_destructor() { - tracer.visit_kind(method.signature.into(), EdgeKind::Destructor); - } else { - tracer.visit_kind(method.signature.into(), EdgeKind::Method); - } + tracer.visit_kind(method.signature.into(), EdgeKind::Method); + } + + if let Some((_kind, signature)) = self.destructor() { + tracer.visit_kind(signature.into(), EdgeKind::Destructor); } for ctor in self.constructors() { diff --git a/src/ir/function.rs b/src/ir/function.rs index 62792484..7b8349a2 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -27,17 +27,26 @@ pub enum FunctionKind { impl FunctionKind { fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> { + // FIXME(emilio): Deduplicate logic with `ir::comp`. Some(match cursor.kind() { clang_sys::CXCursor_FunctionDecl => FunctionKind::Function, clang_sys::CXCursor_Constructor => FunctionKind::Method( MethodKind::Constructor, ), clang_sys::CXCursor_Destructor => FunctionKind::Method( - MethodKind::Destructor, + if cursor.method_is_virtual() { + MethodKind::VirtualDestructor { + pure_virtual: cursor.method_is_pure_virtual(), + } + } else { + MethodKind::Destructor + } ), clang_sys::CXCursor_CXXMethod => { if cursor.method_is_virtual() { - FunctionKind::Method(MethodKind::Virtual) + FunctionKind::Method(MethodKind::Virtual { + pure_virtual: cursor.method_is_pure_virtual(), + }) } else if cursor.method_is_static() { FunctionKind::Method(MethodKind::Static) } else { diff --git a/src/ir/item.rs b/src/ir/item.rs index a9203639..89ab2569 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -944,12 +944,12 @@ impl Item { cc.constructors } FunctionKind::Method(MethodKind::Destructor) | - FunctionKind::Method(MethodKind::VirtualDestructor) => { + FunctionKind::Method(MethodKind::VirtualDestructor { .. }) => { cc.destructors } FunctionKind::Method(MethodKind::Static) | FunctionKind::Method(MethodKind::Normal) | - FunctionKind::Method(MethodKind::Virtual) => cc.methods, + FunctionKind::Method(MethodKind::Virtual { .. }) => cc.methods, } } } diff --git a/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs b/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs new file mode 100644 index 00000000..a3c5f4f6 --- /dev/null +++ b/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs @@ -0,0 +1,29 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +#[repr(C)] +pub struct Foo__bindgen_vtable(::std::os::raw::c_void); +#[repr(C)] +#[derive(Debug)] +pub struct Foo { + pub vtable_: *const Foo__bindgen_vtable, +} +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!( + ::std::mem::size_of::<Foo>(), + 8usize, + concat!("Size of: ", stringify!(Foo)) + ); + assert_eq!( + ::std::mem::align_of::<Foo>(), + 8usize, + concat!("Alignment of ", stringify!(Foo)) + ); +} +impl Default for Foo { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} diff --git a/tests/headers/issue-1197-pure-virtual-stuff.hpp b/tests/headers/issue-1197-pure-virtual-stuff.hpp new file mode 100644 index 00000000..a0da90c9 --- /dev/null +++ b/tests/headers/issue-1197-pure-virtual-stuff.hpp @@ -0,0 +1,6 @@ +class Foo +{ +public: + virtual void Bar() = 0; + virtual ~Foo() = 0; +}; diff --git a/tests/headers/ref_argument_array.hpp b/tests/headers/ref_argument_array.hpp index dc73fd62..53f66950 100644 --- a/tests/headers/ref_argument_array.hpp +++ b/tests/headers/ref_argument_array.hpp @@ -2,5 +2,5 @@ #define NSID_LENGTH 10 class nsID { public: - virtual void ToProvidedString(char (&aDest)[NSID_LENGTH]) = 0; + virtual void ToProvidedString(char (&aDest)[NSID_LENGTH]); }; |