summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-12-29 10:34:39 -0600
committerGitHub <noreply@github.com>2017-12-29 10:34:39 -0600
commit04591f01d96a5c05e690dcf49d19d8e003eac7bf (patch)
treeac0f94fc51674a72e0cab06fdff032a19e3b9a47 /src
parent39d07787a3409b7753a9600bbbfe43d757ce28c2 (diff)
parentf4d2d6a478413d04930659929c6307af63d32cf0 (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.rs7
-rw-r--r--src/codegen/mod.rs24
-rw-r--r--src/ir/comp.rs71
-rw-r--r--src/ir/function.rs13
-rw-r--r--src/ir/item.rs4
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,
}
}
}