diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-12-29 10:34:39 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-29 10:34:39 -0600 |
commit | 04591f01d96a5c05e690dcf49d19d8e003eac7bf (patch) | |
tree | ac0f94fc51674a72e0cab06fdff032a19e3b9a47 /src | |
parent | 39d07787a3409b7753a9600bbbfe43d757ce28c2 (diff) | |
parent | f4d2d6a478413d04930659929c6307af63d32cf0 (diff) |
Auto merge of #1199 - emilio:pure-virtual, r=pepyakin
Don't generate symbols for pure virtual functions.
Fixes #1197.
Diffstat (limited to 'src')
-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 |
5 files changed, 85 insertions, 34 deletions
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, } } } |