summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs64
-rw-r--r--src/ir/analysis/derive_debug.rs153
-rw-r--r--src/ir/analysis/has_vtable.rs168
-rw-r--r--src/ir/analysis/mod.rs30
-rw-r--r--src/ir/comp.rs47
-rw-r--r--src/ir/context.rs36
-rw-r--r--src/ir/derive.rs2
-rw-r--r--src/ir/function.rs4
-rw-r--r--src/ir/item.rs21
-rw-r--r--src/ir/layout.rs2
-rw-r--r--src/ir/template.rs5
-rw-r--r--src/ir/ty.rs33
-rw-r--r--src/lib.rs6
-rw-r--r--src/main.rs6
-rw-r--r--src/options.rs2
15 files changed, 390 insertions, 189 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index a089b070..05e16a5b 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -18,7 +18,7 @@ use ir::dot;
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
use ir::function::{Abi, Function, FunctionSig};
use ir::int::IntKind;
-use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath, ItemSet};
+use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath};
use ir::item_kind::ItemKind;
use ir::layout::Layout;
use ir::module::Module;
@@ -282,7 +282,6 @@ trait CodeGenerator {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- whitelisted_items: &ItemSet,
extra: &Self::Extra);
}
@@ -292,7 +291,6 @@ impl CodeGenerator for Item {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- whitelisted_items: &ItemSet,
_extra: &()) {
if !self.is_enabled_for_codegen(ctx) {
return;
@@ -306,7 +304,7 @@ impl CodeGenerator for Item {
}
debug!("<Item as CodeGenerator>::codegen: self = {:?}", self);
- if !whitelisted_items.contains(&self.id()) {
+ if !ctx.codegen_items().contains(&self.id()) {
// TODO(emilio, #453): Figure out what to do when this happens
// legitimately, we could track the opaque stuff and disable the
// assertion there I guess.
@@ -317,16 +315,16 @@ impl CodeGenerator for Item {
match *self.kind() {
ItemKind::Module(ref module) => {
- module.codegen(ctx, result, whitelisted_items, self);
+ module.codegen(ctx, result, self);
}
ItemKind::Function(ref fun) => {
- fun.codegen(ctx, result, whitelisted_items, self);
+ fun.codegen(ctx, result, self);
}
ItemKind::Var(ref var) => {
- var.codegen(ctx, result, whitelisted_items, self);
+ var.codegen(ctx, result, self);
}
ItemKind::Type(ref ty) => {
- ty.codegen(ctx, result, whitelisted_items, self);
+ ty.codegen(ctx, result, self);
}
}
}
@@ -338,17 +336,16 @@ impl CodeGenerator for Module {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- whitelisted_items: &ItemSet,
item: &Item) {
debug!("<Module as CodeGenerator>::codegen: item = {:?}", item);
let codegen_self = |result: &mut CodegenResult,
found_any: &mut bool| {
for child in self.children() {
- if whitelisted_items.contains(child) {
+ if ctx.codegen_items().contains(child) {
*found_any = true;
ctx.resolve_item(*child)
- .codegen(ctx, result, whitelisted_items, &());
+ .codegen(ctx, result, &());
}
}
@@ -413,7 +410,6 @@ impl CodeGenerator for Var {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- _whitelisted_items: &ItemSet,
item: &Item) {
use ir::var::VarType;
debug!("<Var as CodeGenerator>::codegen: item = {:?}", item);
@@ -518,7 +514,6 @@ impl CodeGenerator for Type {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- whitelisted_items: &ItemSet,
item: &Item) {
debug!("<Type as CodeGenerator>::codegen: item = {:?}", item);
debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -542,10 +537,10 @@ impl CodeGenerator for Type {
return;
}
TypeKind::TemplateInstantiation(ref inst) => {
- inst.codegen(ctx, result, whitelisted_items, item)
+ inst.codegen(ctx, result, item)
}
TypeKind::Comp(ref ci) => {
- ci.codegen(ctx, result, whitelisted_items, item)
+ ci.codegen(ctx, result, item)
}
TypeKind::TemplateAlias(inner, _) |
TypeKind::Alias(inner) => {
@@ -660,13 +655,13 @@ impl CodeGenerator for Type {
result.push(typedef)
}
TypeKind::Enum(ref ei) => {
- ei.codegen(ctx, result, whitelisted_items, item)
+ ei.codegen(ctx, result, item)
}
TypeKind::ObjCId | TypeKind::ObjCSel => {
result.saw_objc();
}
TypeKind::ObjCInterface(ref interface) => {
- interface.codegen(ctx, result, whitelisted_items, item)
+ interface.codegen(ctx, result, item)
}
ref u @ TypeKind::UnresolvedTypeRef(..) => {
unreachable!("Should have been resolved after parsing {:?}!", u)
@@ -702,7 +697,6 @@ impl<'a> CodeGenerator for Vtable<'a> {
fn codegen<'b>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'b>,
- _whitelisted_items: &ItemSet,
item: &Item) {
assert_eq!(item.id(), self.item_id);
debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -745,7 +739,6 @@ impl CodeGenerator for TemplateInstantiation {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- _whitelisted_items: &ItemSet,
item: &Item) {
debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -1377,7 +1370,6 @@ impl CodeGenerator for CompInfo {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- whitelisted_items: &ItemSet,
item: &Item) {
debug!("<CompInfo as CodeGenerator>::codegen: item = {:?}", item);
debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -1481,10 +1473,10 @@ impl CodeGenerator for CompInfo {
// the parent too.
let mut fields = vec![];
let mut struct_layout = StructLayoutTracker::new(ctx, self, &canonical_name);
- if self.needs_explicit_vtable(ctx) {
+ if self.needs_explicit_vtable(ctx, item) {
let vtable =
Vtable::new(item.id(), self.methods(), self.base_members());
- vtable.codegen(ctx, result, whitelisted_items, item);
+ vtable.codegen(ctx, result, item);
let vtable_type = vtable.try_to_rust_ty(ctx, &())
.expect("vtable to Rust type conversion is infallible")
@@ -1512,7 +1504,7 @@ impl CodeGenerator for CompInfo {
// NB: We won't include unsized types in our base chain because they
// would contribute to our size given the dummy field we insert for
// unsized types.
- if base_ty.is_unsized(ctx) {
+ if base_ty.is_unsized(ctx, &base.ty) {
continue;
}
@@ -1591,7 +1583,7 @@ impl CodeGenerator for CompInfo {
warn!("Opaque type without layout! Expect dragons!");
}
}
- } else if !is_union && !self.is_unsized(ctx) {
+ } else if !is_union && !self.is_unsized(ctx, &item.id()) {
if let Some(padding_field) =
layout.and_then(|layout| {
struct_layout.pad_struct(layout)
@@ -1609,13 +1601,13 @@ impl CodeGenerator for CompInfo {
// is making the struct 1-byte sized.
//
// This is apparently not the case for C, see:
- // https://github.com/servo/rust-bindgen/issues/551
+ // https://github.com/rust-lang-nursery/rust-bindgen/issues/551
//
// Just get the layout, and assume C++ if not.
//
// NOTE: This check is conveniently here to avoid the dummy fields we
// may add for unused template parameters.
- if self.is_unsized(ctx) {
+ if self.is_unsized(ctx, &item.id()) {
let has_address = if is_opaque {
// Generate the address field if it's an opaque type and
// couldn't determine the layout of the blob.
@@ -1668,7 +1660,7 @@ impl CodeGenerator for CompInfo {
for ty in self.inner_types() {
let child_item = ctx.resolve_item(*ty);
// assert_eq!(child_item.parent_id(), item.id());
- child_item.codegen(ctx, result, whitelisted_items, &());
+ child_item.codegen(ctx, result, &());
}
// NOTE: Some unexposed attributes (like alignment attributes) may
@@ -1683,7 +1675,7 @@ impl CodeGenerator for CompInfo {
if !is_opaque {
for var in self.inner_vars() {
ctx.resolve_item(*var)
- .codegen(ctx, result, whitelisted_items, &());
+ .codegen(ctx, result, &());
}
}
@@ -1711,11 +1703,11 @@ impl CodeGenerator for CompInfo {
)
};
- // FIXME when [issue #465](https://github.com/servo/rust-bindgen/issues/465) ready
+ // FIXME when [issue #465](https://github.com/rust-lang-nursery/rust-bindgen/issues/465) ready
let too_many_base_vtables = self.base_members()
.iter()
.filter(|base| {
- ctx.resolve_type(base.ty).has_vtable(ctx)
+ ctx.lookup_item_id_has_vtable(&base.ty)
})
.count() > 1;
@@ -1772,7 +1764,6 @@ impl CodeGenerator for CompInfo {
&mut methods,
&mut method_names,
result,
- whitelisted_items,
self);
}
}
@@ -1787,7 +1778,6 @@ impl CodeGenerator for CompInfo {
&mut methods,
&mut method_names,
result,
- whitelisted_items,
self);
}
}
@@ -1805,7 +1795,6 @@ impl CodeGenerator for CompInfo {
&mut methods,
&mut method_names,
result,
- whitelisted_items,
self);
}
}
@@ -1890,7 +1879,6 @@ trait MethodCodegen {
methods: &mut Vec<ast::ImplItem>,
method_names: &mut HashMap<String, usize>,
result: &mut CodegenResult<'a>,
- whitelisted_items: &ItemSet,
parent: &CompInfo);
}
@@ -1900,7 +1888,6 @@ impl MethodCodegen for Method {
methods: &mut Vec<ast::ImplItem>,
method_names: &mut HashMap<String, usize>,
result: &mut CodegenResult<'a>,
- whitelisted_items: &ItemSet,
_parent: &CompInfo) {
assert!({
let cc = &ctx.options().codegen_config;
@@ -1920,7 +1907,7 @@ impl MethodCodegen for Method {
// First of all, output the actual function.
let function_item = ctx.resolve_item(self.signature());
- function_item.codegen(ctx, result, whitelisted_items, &());
+ function_item.codegen(ctx, result, &());
let function = function_item.expect_function();
let signature_item = ctx.resolve_item(function.signature());
@@ -2301,7 +2288,6 @@ impl CodeGenerator for Enum {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- _whitelisted_items: &ItemSet,
item: &Item) {
debug!("<Enum as CodeGenerator>::codegen: item = {:?}", item);
debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -3041,7 +3027,6 @@ impl CodeGenerator for Function {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- _whitelisted_items: &ItemSet,
item: &Item) {
debug!("<Function as CodeGenerator>::codegen: item = {:?}", item);
debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -3220,7 +3205,6 @@ impl CodeGenerator for ObjCInterface {
fn codegen<'a>(&self,
ctx: &BindgenContext,
result: &mut CodegenResult<'a>,
- _whitelisted_items: &ItemSet,
item: &Item) {
debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -3298,7 +3282,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
}
context.resolve_item(context.root_module())
- .codegen(context, &mut result, codegen_items, &());
+ .codegen(context, &mut result, &());
result.items
})
diff --git a/src/ir/analysis/derive_debug.rs b/src/ir/analysis/derive_debug.rs
index b9b0be10..0dc1a0c5 100644
--- a/src/ir/analysis/derive_debug.rs
+++ b/src/ir/analysis/derive_debug.rs
@@ -1,6 +1,6 @@
//! Determining which types for which we can emit `#[derive(Debug)]`.
-use super::{ConstrainResult, MonotoneFramework};
+use super::{ConstrainResult, MonotoneFramework, generate_dependencies};
use std::collections::HashSet;
use std::collections::HashMap;
use ir::context::{BindgenContext, ItemId};
@@ -9,9 +9,7 @@ use ir::traversal::EdgeKind;
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use ir::ty::TypeKind;
use ir::comp::Field;
-use ir::traversal::Trace;
use ir::comp::FieldMethods;
-use ir::layout::Layout;
use ir::derive::CanTriviallyDeriveDebug;
use ir::comp::CompKind;
@@ -79,6 +77,8 @@ impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
}
fn insert(&mut self, id: ItemId) -> ConstrainResult {
+ trace!("inserting {:?} into the cannot_derive_debug set", id);
+
let was_not_already_in_set = self.cannot_derive_debug.insert(id);
assert!(
was_not_already_in_set,
@@ -86,6 +86,7 @@ impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
already in the set, `constrain` should have exited early.",
id
);
+
ConstrainResult::Changed
}
}
@@ -97,24 +98,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> {
let cannot_derive_debug = HashSet::new();
- let mut dependencies = HashMap::new();
-
- for &item in ctx.whitelisted_items() {
- dependencies.entry(item).or_insert(vec![]);
-
- {
- // We reverse our natural IR graph edges to find dependencies
- // between nodes.
- item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
- if ctx.whitelisted_items().contains(&sub_item) &&
- Self::consider_edge(edge_kind) {
- dependencies.entry(sub_item)
- .or_insert(vec![])
- .push(item);
- }
- }, &());
- }
- }
+ let dependencies = generate_dependencies(ctx, Self::consider_edge);
CannotDeriveDebug {
ctx,
@@ -128,16 +112,35 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
}
fn constrain(&mut self, id: ItemId) -> ConstrainResult {
+ trace!("constrain: {:?}", id);
+
if self.cannot_derive_debug.contains(&id) {
+ trace!(" already know it cannot derive Debug");
return ConstrainResult::Same;
}
let item = self.ctx.resolve_item(id);
let ty = match item.as_type() {
- None => return ConstrainResult::Same,
- Some(ty) => ty
+ Some(ty) => ty,
+ None => {
+ trace!(" not a type; ignoring");
+ return ConstrainResult::Same;
+ }
};
+ if ty.is_opaque(self.ctx, item) {
+ let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
+ l.opaque().can_trivially_derive_debug(self.ctx, ())
+ });
+ return if layout_can_derive {
+ trace!(" we can trivially derive Debug for the layout");
+ ConstrainResult::Same
+ } else {
+ trace!(" we cannot derive Debug for the layout");
+ self.insert(id)
+ };
+ }
+
match *ty.kind() {
// Handle the simple cases. These can derive debug without further
// information.
@@ -155,61 +158,59 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
TypeKind::ObjCSel => {
+ trace!(" simple type that can always derive Debug");
ConstrainResult::Same
- },
-
- TypeKind::Opaque => {
- if ty.layout(self.ctx)
- .map_or(true, |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
- ConstrainResult::Same
- } else {
- self.insert(id)
- }
- },
+ }
TypeKind::Array(t, len) => {
if self.cannot_derive_debug.contains(&t) {
+ trace!(" arrays of T for which we cannot derive Debug \
+ also cannot derive Debug");
return self.insert(id);
}
if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
+ trace!(" array is small enough to derive Debug");
ConstrainResult::Same
} else {
+ trace!(" array is too large to derive Debug");
self.insert(id)
}
- },
+ }
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
if self.cannot_derive_debug.contains(&t) {
+ trace!(" aliases and type refs to T which cannot derive \
+ Debug also cannot derive Debug");
self.insert(id)
} else {
+ trace!(" aliases and type refs to T which can derive \
+ Debug can also derive Debug");
ConstrainResult::Same
}
- },
+ }
TypeKind::Comp(ref info) => {
- if info.has_non_type_template_params() {
- if ty.layout(self.ctx)
- .map_or(true,
- |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
- return ConstrainResult::Same;
- } else {
- return self.insert(id);
- }
- }
+ assert!(
+ !info.has_non_type_template_params(),
+ "The early ty.is_opaque check should have handled this case"
+ );
if info.kind() == CompKind::Union {
if self.ctx.options().unstable_rust {
+ trace!(" cannot derive Debug for Rust unions");
return self.insert(id);
}
if ty.layout(self.ctx)
.map_or(true,
|l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
+ trace!(" union layout can trivially derive Debug");
return ConstrainResult::Same;
} else {
+ trace!(" union layout cannot derive Debug");
return self.insert(id);
}
}
@@ -218,6 +219,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
.iter()
.any(|base| self.cannot_derive_debug.contains(&base.ty));
if bases_cannot_derive {
+ trace!(" base members cannot derive Debug, so we can't \
+ either");
return self.insert(id);
}
@@ -237,69 +240,57 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
}
});
if fields_cannot_derive {
+ trace!(" fields cannot derive Debug, so we can't either");
return self.insert(id);
}
+ trace!(" comp can derive Debug");
ConstrainResult::Same
- },
+ }
TypeKind::Pointer(inner) => {
let inner_type = self.ctx.resolve_type(inner).canonical_type(self.ctx);
if let TypeKind::Function(ref sig) = *inner_type.kind() {
if !sig.can_trivially_derive_debug(&self.ctx, ()) {
+ trace!(" function pointer that can't trivially derive Debug");
return self.insert(id);
}
}
+ trace!(" pointers can derive Debug");
ConstrainResult::Same
- },
+ }
TypeKind::TemplateInstantiation(ref template) => {
let args_cannot_derive = template.template_arguments()
.iter()
.any(|arg| self.cannot_derive_debug.contains(&arg));
if args_cannot_derive {
+ trace!(" template args cannot derive Debug, so \
+ insantiation can't either");
return self.insert(id);
}
- let template_definition = template.template_definition()
- .into_resolver()
- .through_type_refs()
- .through_type_aliases()
- .resolve(self.ctx);
-
- let ty_cannot_derive = template_definition
- .as_type()
- .expect("Instantiations of a non-type?")
- .as_comp()
- .and_then(|c| {
- // For non-type template parameters, or opaque template
- // definitions, we generate an opaque blob, and in this
- // case the instantiation has a better idea of the
- // layout than the definition does.
- if template_definition.is_opaque(self.ctx, &()) ||
- c.has_non_type_template_params() {
- let opaque = ty.layout(self.ctx)
- .or_else(|| {
- self.ctx
- .resolve_type(template.template_definition())
- .layout(self.ctx)
- })
- .unwrap_or(Layout::zero())
- .opaque();
- Some(!opaque.can_trivially_derive_debug(&self.ctx, ()))
- } else {
- None
- }
- })
- .unwrap_or_else(|| {
- self.cannot_derive_debug.contains(&template.template_definition())
- });
- if ty_cannot_derive {
+ assert!(
+ !template.template_definition().is_opaque(self.ctx, &()),
+ "The early ty.is_opaque check should have handled this case"
+ );
+ let def_cannot_derive = self.cannot_derive_debug
+ .contains(&template.template_definition());
+ if def_cannot_derive {
+ trace!(" template definition cannot derive Debug, so \
+ insantiation can't either");
return self.insert(id);
}
+ trace!(" template instantiation can derive Debug");
ConstrainResult::Same
- },
+ }
+
+ TypeKind::Opaque => {
+ unreachable!(
+ "The early ty.is_opaque check should have handled this case"
+ )
+ }
}
}
diff --git a/src/ir/analysis/has_vtable.rs b/src/ir/analysis/has_vtable.rs
new file mode 100644
index 00000000..47c9ee15
--- /dev/null
+++ b/src/ir/analysis/has_vtable.rs
@@ -0,0 +1,168 @@
+//! Determining which types has vtable
+use super::{ConstrainResult, MonotoneFramework, generate_dependencies};
+use std::collections::HashSet;
+use std::collections::HashMap;
+use ir::context::{BindgenContext, ItemId};
+use ir::traversal::EdgeKind;
+use ir::ty::TypeKind;
+
+/// An analysis that finds for each IR item whether it has vtable or not
+///
+/// We use the monotone function `has vtable`, defined as follows:
+///
+/// * If T is a type alias, a templated alias, an indirection to another type,
+/// or a reference of a type, T has vtable if the type T refers to has vtable.
+/// * If T is a compound type, T has vtable if we saw a virtual function when
+/// parsing it or any of its base member has vtable.
+/// * If T is an instantiation of an abstract template definition, T has
+/// vtable if template definition has vtable
+#[derive(Debug, Clone)]
+pub struct HasVtableAnalysis<'ctx, 'gen>
+ where 'gen: 'ctx
+{
+ ctx: &'ctx BindgenContext<'gen>,
+
+ // The incremental result of this analysis's computation. Everything in this
+ // set definitely has a vtable.
+ have_vtable: HashSet<ItemId>,
+
+ // Dependencies saying that if a key ItemId has been inserted into the
+ // `have_vtable` set, then each of the ids in Vec<ItemId> need to be
+ // considered again.
+ //
+ // This is a subset of the natural IR graph with reversed edges, where we
+ // only include the edges from the IR graph that can affect whether a type
+ // has a vtable or not.
+ dependencies: HashMap<ItemId, Vec<ItemId>>,
+}
+
+impl<'ctx, 'gen> HasVtableAnalysis<'ctx, 'gen> {
+ fn consider_edge(kind: EdgeKind) -> bool {
+ match kind {
+ // These are the only edges that can affect whether a type has a
+ // vtable or not.
+ EdgeKind::TypeReference |
+ EdgeKind::BaseMember |
+ EdgeKind::TemplateDeclaration => true,
+ _ => false,
+ }
+ }
+
+ fn insert(&mut self, id: ItemId) -> ConstrainResult {
+ let was_not_already_in_set = self.have_vtable.insert(id);
+ assert!(
+ was_not_already_in_set,
+ "We shouldn't try and insert {:?} twice because if it was \
+ already in the set, `constrain` should have exited early.",
+ id
+ );
+ ConstrainResult::Changed
+ }
+}
+
+impl<'ctx, 'gen> MonotoneFramework for HasVtableAnalysis<'ctx, 'gen> {
+ type Node = ItemId;
+ type Extra = &'ctx BindgenContext<'gen>;
+ type Output = HashSet<ItemId>;
+
+ fn new(ctx: &'ctx BindgenContext<'gen>) -> HasVtableAnalysis<'ctx, 'gen> {
+ let have_vtable = HashSet::new();
+ let dependencies = generate_dependencies(ctx, Self::consider_edge);
+
+ HasVtableAnalysis {
+ ctx,
+ have_vtable,
+ dependencies,
+ }
+ }
+
+ fn initial_worklist(&self) -> Vec<ItemId> {
+ self.ctx.whitelisted_items().iter().cloned().collect()
+ }
+
+ fn constrain(&mut self, id: ItemId) -> ConstrainResult {
+ if self.have_vtable.contains(&id) {
+ // We've already computed that this type has a vtable and that can't
+ // change.
+ return ConstrainResult::Same;
+ }
+
+ let item = self.ctx.resolve_item(id);
+ let ty = match item.as_type() {
+ None => return ConstrainResult::Same,
+ Some(ty) => ty
+ };
+
+ // TODO #851: figure out a way to handle deriving from template type parameters.
+ match *ty.kind() {
+ TypeKind::TemplateAlias(t, _) |
+ TypeKind::Alias(t) |
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::Reference(t) => {
+ if self.have_vtable.contains(&t) {
+ self.insert(id)
+ } else {
+ ConstrainResult::Same
+ }
+ },
+
+ TypeKind::Comp(ref info) => {
+ if info.has_own_virtual_method() {
+ return self.insert(id);
+ }
+ let bases_has_vtable = info.base_members().iter().any(|base| {
+ self.have_vtable.contains(&base.ty)
+ });
+ if bases_has_vtable {
+ self.insert(id)
+ } else {
+ ConstrainResult::Same
+ }
+ },
+
+ TypeKind::TemplateInstantiation(ref inst) => {
+ if self.have_vtable.contains(&inst.template_definition()) {
+ self.insert(id)
+ } else {
+ ConstrainResult::Same
+ }
+ },
+
+ _ => ConstrainResult::Same,
+ }
+ }
+
+ fn each_depending_on<F>(&self, id: ItemId, mut f: F)
+ where F: FnMut(ItemId),
+ {
+ if let Some(edges) = self.dependencies.get(&id) {
+ for item in edges {
+ trace!("enqueue {:?} into worklist", item);
+ f(*item);
+ }
+ }
+ }
+}
+
+impl<'ctx, 'gen> From<HasVtableAnalysis<'ctx, 'gen>> for HashSet<ItemId> {
+ fn from(analysis: HasVtableAnalysis<'ctx, 'gen>) -> Self {
+ analysis.have_vtable
+ }
+}
+
+/// A convenience trait for the things for which we might wonder if they have a
+/// vtable during codegen.
+///
+/// This is not for _computing_ whether the thing has a vtable, it is for
+/// looking up the results of the HasVtableAnalysis's computations for a
+/// specific thing.
+pub trait HasVtable {
+
+ /// Implementations can define this type to get access to any extra
+ /// information required to determine whether they have vtable. If
+ /// extra information is unneeded, then this should simply be the unit type.
+ type Extra;
+
+ /// Return `true` if this thing has vtable, `false` otherwise.
+ fn has_vtable(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool;
+}
diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs
index 5fe6785b..8a00ecce 100644
--- a/src/ir/analysis/mod.rs
+++ b/src/ir/analysis/mod.rs
@@ -42,7 +42,13 @@ mod template_params;
pub use self::template_params::UsedTemplateParameters;
mod derive_debug;
pub use self::derive_debug::CannotDeriveDebug;
+mod has_vtable;
+pub use self::has_vtable::HasVtableAnalysis;
+pub use self::has_vtable::HasVtable;
+use ir::context::{BindgenContext, ItemId};
+use ir::traversal::{EdgeKind, Trace};
+use std::collections::HashMap;
use std::fmt;
/// An analysis in the monotone framework.
@@ -131,6 +137,30 @@ pub fn analyze<Analysis>(extra: Analysis::Extra) -> Analysis::Output
analysis.into()
}
+/// Generate the dependency map for analysis
+pub fn generate_dependencies<F>(ctx: &BindgenContext, consider_edge: F) -> HashMap<ItemId, Vec<ItemId>>
+ where F: Fn(EdgeKind) -> bool {
+ let mut dependencies = HashMap::new();
+
+ for &item in ctx.whitelisted_items() {
+ dependencies.entry(item).or_insert(vec![]);
+
+ {
+ // We reverse our natural IR graph edges to find dependencies
+ // between nodes.
+ item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
+ if ctx.whitelisted_items().contains(&sub_item) &&
+ consider_edge(edge_kind) {
+ dependencies.entry(sub_item)
+ .or_insert(vec![])
+ .push(item);
+ }
+ }, &());
+ }
+ }
+ dependencies
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 0960ee11..d6644466 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -701,7 +701,7 @@ impl FieldMethods for FieldData {
}
}
-impl CanDeriveDefault for Field {
+impl<'a> CanDeriveDefault<'a> for Field {
type Extra = ();
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
@@ -819,7 +819,7 @@ pub struct CompInfo {
/// Whether this type should generate an vtable (TODO: Should be able to
/// look at the virtual methods and ditch this field).
- has_vtable: bool,
+ has_own_virtual_method: bool,
/// Whether this type has destructor.
has_destructor: bool,
@@ -870,7 +870,7 @@ impl CompInfo {
base_members: vec![],
inner_types: vec![],
inner_vars: vec![],
- has_vtable: false,
+ has_own_virtual_method: false,
has_destructor: false,
has_nonempty_base: false,
has_non_type_template_params: false,
@@ -883,10 +883,10 @@ impl CompInfo {
}
/// Is this compound type unsized?
- pub fn is_unsized(&self, ctx: &BindgenContext) -> bool {
- !self.has_vtable(ctx) && self.fields().is_empty() &&
+ pub fn is_unsized(&self, ctx: &BindgenContext, itemid: &ItemId) -> bool {
+ !ctx.lookup_item_id_has_vtable(itemid) && self.fields().is_empty() &&
self.base_members.iter().all(|base| {
- ctx.resolve_type(base.ty).canonical_type(ctx).is_unsized(ctx)
+ ctx.resolve_type(base.ty).canonical_type(ctx).is_unsized(ctx, &base.ty)
})
}
@@ -964,13 +964,10 @@ impl CompInfo {
self.has_non_type_template_params
}
- /// Does this type have a virtual table?
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- self.has_vtable ||
- self.base_members().iter().any(|base| {
- ctx.resolve_type(base.ty)
- .has_vtable(ctx)
- })
+ /// Do we see a virtual function during parsing?
+ /// Get the has_own_virtual_method boolean.
+ pub fn has_own_virtual_method(&self) -> bool {
+ return self.has_own_virtual_method;
}
/// Get this type's set of methods.
@@ -1136,7 +1133,7 @@ impl CompInfo {
// Let's just assume that if the cursor we've found is a
// definition, it's a valid inner type.
//
- // [1]: https://github.com/servo/rust-bindgen/issues/482
+ // [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/482
let is_inner_struct = cur.semantic_parent() == cursor ||
cur.is_definition();
if !is_inner_struct {
@@ -1169,7 +1166,7 @@ impl CompInfo {
}
CXCursor_CXXBaseSpecifier => {
let is_virtual_base = cur.is_virtual_base();
- ci.has_vtable |= is_virtual_base;
+ ci.has_own_virtual_method |= is_virtual_base;
let kind = if is_virtual_base {
BaseKind::Virtual
@@ -1192,7 +1189,7 @@ impl CompInfo {
debug_assert!(!(is_static && is_virtual), "How?");
ci.has_destructor |= cur.kind() == CXCursor_Destructor;
- ci.has_vtable |= is_virtual;
+ ci.has_own_virtual_method |= is_virtual;
// This used to not be here, but then I tried generating
// stylo bindings with this (without path filters), and
@@ -1335,8 +1332,8 @@ impl CompInfo {
/// Returns whether this type needs an explicit vtable because it has
/// virtual methods and none of its base classes has already a vtable.
- pub fn needs_explicit_vtable(&self, ctx: &BindgenContext) -> bool {
- self.has_vtable(ctx) &&
+ pub fn needs_explicit_vtable(&self, ctx: &BindgenContext, item: &Item) -> bool {
+ ctx.lookup_item_id_has_vtable(&item.id()) &&
!self.base_members.iter().any(|base| {
// NB: Ideally, we could rely in all these types being `comp`, and
// life would be beautiful.
@@ -1347,7 +1344,7 @@ impl CompInfo {
ctx.resolve_type(base.ty)
.canonical_type(ctx)
.as_comp()
- .map_or(false, |ci| ci.has_vtable(ctx))
+ .map_or(false, |_| ctx.lookup_item_id_has_vtable(&base.ty))
})
}
@@ -1368,7 +1365,7 @@ impl DotAttributes for CompInfo {
{
writeln!(out, "<tr><td>CompKind</td><td>{:?}</td></tr>", self.kind)?;
- if self.has_vtable {
+ if self.has_own_virtual_method {
writeln!(out, "<tr><td>has_vtable</td><td>true</td></tr>")?;
}
@@ -1424,12 +1421,12 @@ impl TemplateParameters for CompInfo {
}
}
-impl CanDeriveDefault for CompInfo {
- type Extra = Option<Layout>;
+impl<'a> CanDeriveDefault<'a> for CompInfo {
+ type Extra = (&'a Item, Option<Layout>);
fn can_derive_default(&self,
ctx: &BindgenContext,
- layout: Option<Layout>)
+ (item, layout): (&Item, Option<Layout>))
-> bool {
// We can reach here recursively via template parameters of a member,
// for example.
@@ -1452,8 +1449,8 @@ impl CanDeriveDefault for CompInfo {
self.detect_derive_default_cycle.set(true);
- let can_derive_default = !self.has_vtable(ctx) &&
- !self.needs_explicit_vtable(ctx) &&
+ let can_derive_default = !ctx.lookup_item_id_has_vtable(&item.id()) &&
+ !self.needs_explicit_vtable(ctx, item) &&
self.base_members
.iter()
.all(|base| base.ty.can_derive_default(ctx, ())) &&
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 6a5fdb83..3232e8e6 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -5,7 +5,7 @@ use super::int::IntKind;
use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath, ItemSet};
use super::item_kind::ItemKind;
use super::module::{Module, ModuleKind};
-use super::analysis::{analyze, UsedTemplateParameters, CannotDeriveDebug};
+use super::analysis::{analyze, UsedTemplateParameters, CannotDeriveDebug, HasVtableAnalysis};
use super::template::{TemplateInstantiation, TemplateParameters};
use super::traversal::{self, Edge, ItemTraversal};
use super::ty::{FloatKind, Type, TypeKind};
@@ -47,7 +47,7 @@ impl CanDeriveDebug for ItemId {
}
}
-impl CanDeriveDefault for ItemId {
+impl<'a> CanDeriveDefault<'a> for ItemId {
type Extra = ();
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
@@ -184,6 +184,12 @@ pub struct BindgenContext<'ctx> {
/// This is populated when we enter codegen by `compute_can_derive_debug`
/// and is always `None` before that and `Some` after.
cant_derive_debug: Option<HashSet<ItemId>>,
+
+ /// The set of (`ItemId's of`) types that has vtable.
+ ///
+ /// Populated when we enter codegen by `compute_has_vtable`; always `None`
+ /// before that and `Some` after.
+ have_vtable: Option<HashSet<ItemId>>,
}
/// A traversal of whitelisted items.
@@ -310,6 +316,7 @@ impl<'ctx> BindgenContext<'ctx> {
need_bitfield_allocation: Default::default(),
needs_mangling_hack: needs_mangling_hack,
cant_derive_debug: None,
+ have_vtable: None,
};
me.add_item(root_module, None, None);
@@ -780,6 +787,7 @@ impl<'ctx> BindgenContext<'ctx> {
// messes with them correctly.
self.assert_every_item_in_a_module();
+ self.compute_has_vtable();
self.find_used_template_parameters();
self.compute_cant_derive_debug();
@@ -847,6 +855,22 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
+ /// Compute whether the type has vtable.
+ fn compute_has_vtable(&mut self) {
+ assert!(self.have_vtable.is_none());
+ self.have_vtable = Some(analyze::<HasVtableAnalysis>(self));
+ }
+
+ /// Look up whether the item with `id` has vtable or not.
+ pub fn lookup_item_id_has_vtable(&self, id: &ItemId) -> bool {
+ assert!(self.in_codegen_phase(),
+ "We only compute vtables when we enter codegen");
+
+ // Look up the computed value for whether the item with `id` has a
+ // vtable or not.
+ self.have_vtable.as_ref().unwrap().contains(id)
+ }
+
fn find_used_template_parameters(&mut self) {
if self.options.whitelist_recursively {
let used_params = analyze::<UsedTemplateParameters>(self);
@@ -1391,7 +1415,13 @@ impl<'ctx> BindgenContext<'ctx> {
_ => return None,
};
- let spelling = ty.spelling();
+ let mut spelling = ty.spelling();
+ // avoid the allocation if possible
+ if spelling.contains(' ') {
+ // These names are used in generated test names,
+ // they should be valid identifiers
+ spelling = spelling.replace(' ', "_");
+ }
let is_const = ty.is_const();
let layout = ty.fallible_layout().ok();
let ty = Type::new(Some(spelling), layout, type_kind, is_const);
diff --git a/src/ir/derive.rs b/src/ir/derive.rs
index 59548163..446d2435 100644
--- a/src/ir/derive.rs
+++ b/src/ir/derive.rs
@@ -90,7 +90,7 @@ pub trait CanDeriveCopy<'a> {
/// to be a recursive method that checks whether all the proper members can
/// derive default or not, because of the limit rust has on 32 items as max in the
/// array.
-pub trait CanDeriveDefault {
+pub trait CanDeriveDefault<'a> {
/// Implementations can define this type to get access to any extra
/// information required to determine whether they can derive `Default`. If
/// extra information is unneeded, then this should simply be the unit type.
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 663bb8e3..fbb6121e 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -193,7 +193,7 @@ pub fn cursor_mangling(ctx: &BindgenContext,
// We early return here because libclang may crash in some case
// if we pass in a variable inside a partial specialized template.
- // See servo/rust-bindgen#67, and servo/rust-bindgen#462.
+ // See rust-lang-nursery/rust-bindgen#67, and rust-lang-nursery/rust-bindgen#462.
if cursor.is_in_non_fully_specialized_template() {
return None;
}
@@ -474,7 +474,7 @@ impl Trace for FunctionSig {
// Function pointers follow special rules, see:
//
-// https://github.com/servo/rust-bindgen/issues/547,
+// https://github.com/rust-lang-nursery/rust-bindgen/issues/547,
// https://github.com/rust-lang/rust/issues/38848,
// and https://github.com/rust-lang/rust/issues/40158
//
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 7f3afefb..b3a26bb7 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -14,6 +14,7 @@ use super::module::Module;
use super::template::{AsTemplateParam, TemplateParameters};
use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::{Type, TypeKind};
+use super::analysis::HasVtable;
use clang;
use clang_sys;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
@@ -277,7 +278,7 @@ impl CanDeriveDebug for Item {
}
}
-impl CanDeriveDefault for Item {
+impl<'a> CanDeriveDefault<'a> for Item {
type Extra = ();
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
@@ -289,7 +290,7 @@ impl CanDeriveDefault for Item {
.map_or(false,
|l| l.opaque().can_derive_default(ctx, ()))
} else {
- ty.can_derive_default(ctx, ())
+ ty.can_derive_default(ctx, self)
}
}
_ => false,
@@ -947,6 +948,22 @@ impl IsOpaque for Item {
}
}
+impl HasVtable for ItemId {
+ type Extra = ();
+
+ fn has_vtable(&self, ctx: &BindgenContext, _: &()) -> bool {
+ ctx.lookup_item_id_has_vtable(self)
+ }
+}
+
+impl HasVtable for Item {
+ type Extra = ();
+
+ fn has_vtable(&self, ctx: &BindgenContext, _: &()) -> bool {
+ ctx.lookup_item_id_has_vtable(&self.id())
+ }
+}
+
/// A set of items.
pub type ItemSet = BTreeSet<ItemId>;
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index 91dd9d6c..03496ad0 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -111,7 +111,7 @@ impl CanTriviallyDeriveDebug for Opaque {
}
}
-impl CanDeriveDefault for Opaque {
+impl<'a> CanDeriveDefault<'a> for Opaque {
type Extra = ();
fn can_derive_default(&self, _: &BindgenContext, _: ()) -> bool {
diff --git a/src/ir/template.rs b/src/ir/template.rs
index 25d1d438..6147365e 100644
--- a/src/ir/template.rs
+++ b/src/ir/template.rs
@@ -292,11 +292,6 @@ impl TemplateInstantiation {
Some(TemplateInstantiation::new(template_definition, template_args))
}
- /// Does this instantiation have a vtable?
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- ctx.resolve_type(self.definition).has_vtable(ctx)
- }
-
/// Does this instantiation have a destructor?
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
ctx.resolve_type(self.definition).has_destructor(ctx) ||
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 78274d94..b189ceac 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -237,19 +237,6 @@ impl Type {
})
}
- /// Whether this type has a vtable.
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- // FIXME: Can we do something about template parameters? Huh...
- match self.kind {
- TypeKind::TemplateAlias(t, _) |
- TypeKind::Alias(t) |
- TypeKind::ResolvedTypeRef(t) => ctx.resolve_type(t).has_vtable(ctx),
- TypeKind::Comp(ref info) => info.has_vtable(ctx),
- TypeKind::TemplateInstantiation(ref inst) => inst.has_vtable(ctx),
- _ => false,
- }
- }
-
/// Returns whether this type has a destructor.
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
match self.kind {
@@ -359,6 +346,7 @@ impl IsOpaque for Type {
TypeKind::Opaque => true,
TypeKind::TemplateInstantiation(ref inst) => inst.is_opaque(ctx, item),
TypeKind::Comp(ref comp) => comp.is_opaque(ctx, &()),
+ TypeKind::ResolvedTypeRef(to) => to.is_opaque(ctx, &()),
_ => false,
}
}
@@ -546,10 +534,10 @@ impl CanDeriveDebug for Type {
}
}
-impl CanDeriveDefault for Type {
- type Extra = ();
+impl<'a> CanDeriveDefault<'a> for Type {
+ type Extra = &'a Item;
- fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
+ fn can_derive_default(&self, ctx: &BindgenContext, item: &Item) -> bool {
match self.kind {
TypeKind::Array(t, len) => {
len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
@@ -559,7 +547,7 @@ impl CanDeriveDefault for Type {
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => t.can_derive_default(ctx, ()),
TypeKind::Comp(ref info) => {
- info.can_derive_default(ctx, self.layout(ctx))
+ info.can_derive_default(ctx, (&item, self.layout(ctx)))
}
TypeKind::Opaque => {
self.layout
@@ -744,23 +732,24 @@ impl Type {
/// derive whether we should generate a dummy `_address` field for structs,
/// to comply to the C and C++ layouts, that specify that every type needs
/// to be addressable.
- pub fn is_unsized(&self, ctx: &BindgenContext) -> bool {
+ pub fn is_unsized(&self, ctx: &BindgenContext, itemid: &ItemId) -> bool {
debug_assert!(ctx.in_codegen_phase(), "Not yet");
match self.kind {
TypeKind::Void => true,
- TypeKind::Comp(ref ci) => ci.is_unsized(ctx),
+ TypeKind::Comp(ref ci) => ci.is_unsized(ctx, itemid),
TypeKind::Opaque => self.layout.map_or(true, |l| l.size == 0),
TypeKind::Array(inner, size) => {
- size == 0 || ctx.resolve_type(inner).is_unsized(ctx)
+ size == 0 || ctx.resolve_type(inner).is_unsized(ctx, &inner)
}
TypeKind::ResolvedTypeRef(inner) |
TypeKind::Alias(inner) |
TypeKind::TemplateAlias(inner, _) => {
- ctx.resolve_type(inner).is_unsized(ctx)
+ ctx.resolve_type(inner).is_unsized(ctx, &inner)
}
TypeKind::TemplateInstantiation(ref inst) => {
- ctx.resolve_type(inst.template_definition()).is_unsized(ctx)
+ let definition = inst.template_definition();
+ ctx.resolve_type(definition).is_unsized(ctx, &definition)
}
TypeKind::Named |
TypeKind::Int(..) |
diff --git a/src/lib.rs b/src/lib.rs
index 700ca7e9..4eeb95f4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -484,7 +484,7 @@ impl Builder {
/// implement some processing on comments to work around issues as described
/// in:
///
- /// https://github.com/servo/rust-bindgen/issues/426
+ /// https://github.com/rust-lang-nursery/rust-bindgen/issues/426
pub fn generate_comments(mut self, doit: bool) -> Self {
self.options.generate_comments = doit;
self
@@ -513,7 +513,7 @@ impl Builder {
/// However, some old libclang versions seem to return incorrect results in
/// some cases for non-mangled functions, see [1], so we allow disabling it.
///
- /// [1]: https://github.com/servo/rust-bindgen/issues/528
+ /// [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/528
pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
self.options.enable_mangling = doit;
self
@@ -1038,7 +1038,7 @@ pub struct BindgenOptions {
/// However, some old libclang versions seem to return incorrect results in
/// some cases for non-mangled functions, see [1], so we allow disabling it.
///
- /// [1]: https://github.com/servo/rust-bindgen/issues/528
+ /// [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/528
pub enable_mangling: bool,
/// Whether to prepend the enum name to bitfield or constant variants.
diff --git a/src/main.rs b/src/main.rs
index f202cc18..9cd4f806 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -80,9 +80,9 @@ pub fn main() {
fn print_verbose_err() {
println!("Bindgen unexpectedly panicked");
println!("This may be caused by one of the known-unsupported \
- things (https://github.com/servo/rust-bindgen#c), \
+ things (https://github.com/rust-lang-nursery/rust-bindgen#c), \
please modify the bindgen flags to work around it as \
- described in https://github.com/servo/rust-bindgen#c");
+ described in https://github.com/rust-lang-nursery/rust-bindgen#c");
println!("Otherwise, please file an issue at \
- https://github.com/servo/rust-bindgen/issues/new");
+ https://github.com/rust-lang-nursery/rust-bindgen/issues/new");
}
diff --git a/src/options.rs b/src/options.rs
index bf479ca5..23df6370 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -65,7 +65,7 @@ pub fn builder_from_flags<I>
Arg::with_name("no-doc-comments")
.long("no-doc-comments")
.help("Avoid including doc comments in the output, see: \
- https://github.com/servo/rust-bindgen/issues/426"),
+ https://github.com/rust-lang-nursery/rust-bindgen/issues/426"),
Arg::with_name("no-recursive-whitelist")
.long("no-recursive-whitelist")
.help("Avoid whitelisting types recursively."),