Skip to content

Commit 9dbc2ca

Browse files
author
bors-servo
authored
Auto merge of #827 - fitzgen:issue-826-generating-methods-when-asked-not-to, r=emilio
Only whitelist items for which we intend to generate bindings This means that we only need to check in one place, rather than at ever call site. This makes it so that we don't generate methods for the test case, but if I add the `--target` flag like in the original #826 test case, then I get a panic about an unknown ABI. I figure this change is worth landing now, and we can land the fix for the panic as a follow up. r? @upsuper
2 parents 8f43c93 + 0b720a3 commit 9dbc2ca

12 files changed

+188
-39
lines changed

src/codegen/mod.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ impl CodeGenerator for Item {
294294
result: &mut CodegenResult<'a>,
295295
whitelisted_items: &ItemSet,
296296
_extra: &()) {
297+
if !self.is_enabled_for_codegen(ctx) {
298+
return;
299+
}
300+
297301
if self.is_hidden(ctx) || result.seen(self.id()) {
298302
debug!("<Item as CodeGenerator>::codegen: Ignoring hidden or seen: \
299303
self = {:?}",
@@ -316,19 +320,13 @@ impl CodeGenerator for Item {
316320
module.codegen(ctx, result, whitelisted_items, self);
317321
}
318322
ItemKind::Function(ref fun) => {
319-
if ctx.options().codegen_config.functions {
320-
fun.codegen(ctx, result, whitelisted_items, self);
321-
}
323+
fun.codegen(ctx, result, whitelisted_items, self);
322324
}
323325
ItemKind::Var(ref var) => {
324-
if ctx.options().codegen_config.vars {
325-
var.codegen(ctx, result, whitelisted_items, self);
326-
}
326+
var.codegen(ctx, result, whitelisted_items, self);
327327
}
328328
ItemKind::Type(ref ty) => {
329-
if ctx.options().codegen_config.types {
330-
ty.codegen(ctx, result, whitelisted_items, self);
331-
}
329+
ty.codegen(ctx, result, whitelisted_items, self);
332330
}
333331
}
334332
}
@@ -419,6 +417,7 @@ impl CodeGenerator for Var {
419417
item: &Item) {
420418
use ir::var::VarType;
421419
debug!("<Var as CodeGenerator>::codegen: item = {:?}", item);
420+
debug_assert!(item.is_enabled_for_codegen(ctx));
422421

423422
let canonical_name = item.canonical_name(ctx);
424423

@@ -522,6 +521,7 @@ impl CodeGenerator for Type {
522521
whitelisted_items: &ItemSet,
523522
item: &Item) {
524523
debug!("<Type as CodeGenerator>::codegen: item = {:?}", item);
524+
debug_assert!(item.is_enabled_for_codegen(ctx));
525525

526526
match *self.kind() {
527527
TypeKind::Void |
@@ -705,6 +705,8 @@ impl<'a> CodeGenerator for Vtable<'a> {
705705
_whitelisted_items: &ItemSet,
706706
item: &Item) {
707707
assert_eq!(item.id(), self.item_id);
708+
debug_assert!(item.is_enabled_for_codegen(ctx));
709+
708710
// For now, generate an empty struct, later we should generate function
709711
// pointers and whatnot.
710712
let attributes = vec![attributes::repr("C")];
@@ -745,6 +747,8 @@ impl CodeGenerator for TemplateInstantiation {
745747
result: &mut CodegenResult<'a>,
746748
_whitelisted_items: &ItemSet,
747749
item: &Item) {
750+
debug_assert!(item.is_enabled_for_codegen(ctx));
751+
748752
// Although uses of instantiations don't need code generation, and are
749753
// just converted to rust types in fields, vars, etc, we take this
750754
// opportunity to generate tests for their layout here. If the
@@ -1376,6 +1380,7 @@ impl CodeGenerator for CompInfo {
13761380
whitelisted_items: &ItemSet,
13771381
item: &Item) {
13781382
debug!("<CompInfo as CodeGenerator>::codegen: item = {:?}", item);
1383+
debug_assert!(item.is_enabled_for_codegen(ctx));
13791384

13801385
// Don't output classes with template parameters that aren't types, and
13811386
// also don't output template specializations, neither total or partial.
@@ -1897,6 +1902,18 @@ impl MethodCodegen for Method {
18971902
result: &mut CodegenResult<'a>,
18981903
whitelisted_items: &ItemSet,
18991904
_parent: &CompInfo) {
1905+
assert!({
1906+
let cc = &ctx.options().codegen_config;
1907+
match self.kind() {
1908+
MethodKind::Constructor => cc.constructors,
1909+
MethodKind::Destructor => cc.destructors,
1910+
MethodKind::VirtualDestructor => cc.destructors,
1911+
MethodKind::Static |
1912+
MethodKind::Normal |
1913+
MethodKind::Virtual => cc.methods,
1914+
}
1915+
});
1916+
19001917
if self.is_virtual() {
19011918
return; // FIXME
19021919
}
@@ -2287,6 +2304,7 @@ impl CodeGenerator for Enum {
22872304
_whitelisted_items: &ItemSet,
22882305
item: &Item) {
22892306
debug!("<Enum as CodeGenerator>::codegen: item = {:?}", item);
2307+
debug_assert!(item.is_enabled_for_codegen(ctx));
22902308

22912309
let name = item.canonical_name(ctx);
22922310
let enum_ty = item.expect_type();
@@ -3026,6 +3044,7 @@ impl CodeGenerator for Function {
30263044
_whitelisted_items: &ItemSet,
30273045
item: &Item) {
30283046
debug!("<Function as CodeGenerator>::codegen: item = {:?}", item);
3047+
debug_assert!(item.is_enabled_for_codegen(ctx));
30293048

30303049
// Similar to static member variables in a class template, we can't
30313050
// generate bindings to template functions, because the set of
@@ -3202,7 +3221,9 @@ impl CodeGenerator for ObjCInterface {
32023221
ctx: &BindgenContext,
32033222
result: &mut CodegenResult<'a>,
32043223
_whitelisted_items: &ItemSet,
3205-
_: &Item) {
3224+
item: &Item) {
3225+
debug_assert!(item.is_enabled_for_codegen(ctx));
3226+
32063227
let mut impl_items = vec![];
32073228
let mut trait_items = vec![];
32083229

src/ir/cant_derive_debug.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ impl<'ctx, 'gen> CantDeriveDebugAnalysis<'ctx, 'gen> {
6767
EdgeKind::TemplateParameterDefinition => true,
6868

6969
EdgeKind::Constructor |
70+
EdgeKind::Destructor |
7071
EdgeKind::FunctionReturn |
7172
EdgeKind::FunctionParameter |
7273
EdgeKind::InnerType |

src/ir/comp.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1534,7 +1534,11 @@ impl Trace for CompInfo {
15341534
}
15351535

15361536
for method in self.methods() {
1537-
tracer.visit_kind(method.signature, EdgeKind::Method);
1537+
if method.is_destructor() {
1538+
tracer.visit_kind(method.signature, EdgeKind::Destructor);
1539+
} else {
1540+
tracer.visit_kind(method.signature, EdgeKind::Method);
1541+
}
15381542
}
15391543

15401544
for &ctor in self.constructors() {

src/ir/context.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ pub struct WhitelistedItems<'ctx, 'gen>
186186
'gen,
187187
ItemSet,
188188
Vec<ItemId>,
189-
fn(Edge) -> bool>,
189+
for<'a> fn(&'a BindgenContext, Edge) -> bool>,
190190
}
191191

192192
impl<'ctx, 'gen> Iterator for WhitelistedItems<'ctx, 'gen>
@@ -215,7 +215,7 @@ impl<'ctx, 'gen> WhitelistedItems<'ctx, 'gen>
215215
where R: IntoIterator<Item = ItemId>,
216216
{
217217
let predicate = if ctx.options().whitelist_recursively {
218-
traversal::all_edges
218+
traversal::codegen_edges
219219
} else {
220220
traversal::no_edges
221221
};
@@ -1573,6 +1573,8 @@ impl<'ctx> BindgenContext<'ctx> {
15731573
assert!(self.current_module == self.root_module);
15741574

15751575
let roots = self.items()
1576+
// Only consider items that are enabled for codegen.
1577+
.filter(|&(_, item)| item.is_enabled_for_codegen(self))
15761578
.filter(|&(_, item)| {
15771579
// If nothing is explicitly whitelisted, then everything is fair
15781580
// game.

src/ir/function.rs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,47 @@
11
//! Intermediate representation for C/C++ functions and methods.
22
3+
use super::comp::MethodKind;
34
use super::context::{BindgenContext, ItemId};
45
use super::dot::DotAttributes;
56
use super::item::Item;
67
use super::traversal::{EdgeKind, Trace, Tracer};
78
use super::ty::TypeKind;
89
use clang;
9-
use clang_sys::CXCallingConv;
10+
use clang_sys::{self, CXCallingConv};
1011
use ir::derive::CanTriviallyDeriveDebug;
1112
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
1213
use std::io;
1314
use syntax::abi;
1415

16+
/// What kind of a function are we looking at?
17+
#[derive(Debug, Copy, Clone, PartialEq)]
18+
pub enum FunctionKind {
19+
/// A plain, free function.
20+
Function,
21+
/// A method of some kind.
22+
Method(MethodKind),
23+
}
24+
25+
impl FunctionKind {
26+
fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
27+
Some(match cursor.kind() {
28+
clang_sys::CXCursor_FunctionDecl => FunctionKind::Function,
29+
clang_sys::CXCursor_Constructor => FunctionKind::Method(MethodKind::Constructor),
30+
clang_sys::CXCursor_Destructor => FunctionKind::Method(MethodKind::Destructor),
31+
clang_sys::CXCursor_CXXMethod => {
32+
if cursor.method_is_virtual() {
33+
FunctionKind::Method(MethodKind::Virtual)
34+
} else if cursor.method_is_static() {
35+
FunctionKind::Method(MethodKind::Static)
36+
} else {
37+
FunctionKind::Method(MethodKind::Normal)
38+
}
39+
}
40+
_ => return None,
41+
})
42+
}
43+
}
44+
1545
/// A function declaration, with a signature, arguments, and argument names.
1646
///
1747
/// The argument names vector must be the same length as the ones in the
@@ -29,20 +59,25 @@ pub struct Function {
2959

3060
/// The doc comment on the function, if any.
3161
comment: Option<String>,
62+
63+
/// The kind of function this is.
64+
kind: FunctionKind,
3265
}
3366

3467
impl Function {
3568
/// Construct a new function.
3669
pub fn new(name: String,
3770
mangled_name: Option<String>,
3871
sig: ItemId,
39-
comment: Option<String>)
72+
comment: Option<String>,
73+
kind: FunctionKind)
4074
-> Self {
4175
Function {
4276
name: name,
4377
mangled_name: mangled_name,
4478
signature: sig,
4579
comment: comment,
80+
kind: kind,
4681
}
4782
}
4883

@@ -60,6 +95,11 @@ impl Function {
6095
pub fn signature(&self) -> ItemId {
6196
self.signature
6297
}
98+
99+
/// Get this function's kind.
100+
pub fn kind(&self) -> FunctionKind {
101+
self.kind
102+
}
63103
}
64104

65105
impl DotAttributes for Function {
@@ -70,6 +110,7 @@ impl DotAttributes for Function {
70110
where W: io::Write,
71111
{
72112
if let Some(ref mangled) = self.mangled_name {
113+
let mangled: String = mangled.chars().flat_map(|c| c.escape_default()).collect();
73114
try!(writeln!(out,
74115
"<tr><td>mangled name</td><td>{}</td></tr>",
75116
mangled));
@@ -356,12 +397,10 @@ impl ClangSubItemParser for Function {
356397
context: &mut BindgenContext)
357398
-> Result<ParseResult<Self>, ParseError> {
358399
use clang_sys::*;
359-
match cursor.kind() {
360-
CXCursor_FunctionDecl |
361-
CXCursor_Constructor |
362-
CXCursor_Destructor |
363-
CXCursor_CXXMethod => {}
364-
_ => return Err(ParseError::Continue),
400+
401+
let kind = match FunctionKind::from_cursor(&cursor) {
402+
None => return Err(ParseError::Continue),
403+
Some(k) => k,
365404
};
366405

367406
debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
@@ -414,7 +453,7 @@ impl ClangSubItemParser for Function {
414453

415454
let comment = cursor.raw_comment();
416455

417-
let function = Self::new(name, mangled_name, sig, comment);
456+
let function = Self::new(name, mangled_name, sig, comment, kind);
418457
Ok(ParseResult::New(function, Some(cursor)))
419458
}
420459
}

src/ir/item.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
use super::super::codegen::CONSTIFIED_ENUM_MODULE_REPR_NAME;
44
use super::annotations::Annotations;
55
use super::comment;
6+
use super::comp::MethodKind;
67
use super::context::{BindgenContext, ItemId, PartialType};
78
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
89
use super::dot::DotAttributes;
9-
use super::function::Function;
10+
use super::function::{Function, FunctionKind};
1011
use super::item_kind::ItemKind;
1112
use super::layout::Opaque;
1213
use super::module::Module;
@@ -874,6 +875,27 @@ impl Item {
874875
_ => false,
875876
}
876877
}
878+
879+
/// Is this item of a kind that is enabled for code generation?
880+
pub fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
881+
let cc = &ctx.options().codegen_config;
882+
match *self.kind() {
883+
ItemKind::Module(..) => true,
884+
ItemKind::Var(_) => cc.vars,
885+
ItemKind::Type(_) => cc.types,
886+
ItemKind::Function(ref f) => {
887+
match f.kind() {
888+
FunctionKind::Function => cc.functions,
889+
FunctionKind::Method(MethodKind::Constructor) => cc.constructors,
890+
FunctionKind::Method(MethodKind::Destructor) |
891+
FunctionKind::Method(MethodKind::VirtualDestructor) => cc.destructors,
892+
FunctionKind::Method(MethodKind::Static) |
893+
FunctionKind::Method(MethodKind::Normal) |
894+
FunctionKind::Method(MethodKind::Virtual) => cc.methods,
895+
}
896+
}
897+
}
898+
}
877899
}
878900

879901
impl IsOpaque for ItemId {

src/ir/named.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
211211
EdgeKind::BaseMember |
212212
EdgeKind::Field |
213213
EdgeKind::Constructor |
214+
EdgeKind::Destructor |
214215
EdgeKind::VarType |
215216
EdgeKind::FunctionReturn |
216217
EdgeKind::FunctionParameter |

0 commit comments

Comments
 (0)