Skip to content

Commit 6ff1c1d

Browse files
author
bors-servo
authored
Auto merge of #105 - emilio:msvc, r=fitzgen,emilio
Pass the potential id to be used as the type wrapper id, and prevent leaving a dangling a type parsing template aliases. This should fix the MSVC problems @upsuper has been having. @upsuper, can you confirm if this fixes the panic you were hitting?
2 parents 79407f3 + e04eda1 commit 6ff1c1d

File tree

8 files changed

+95
-23
lines changed

8 files changed

+95
-23
lines changed

src/ir/context.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -467,22 +467,22 @@ impl<'ctx> BindgenContext<'ctx> {
467467
/// };
468468
/// ```
469469
fn build_template_wrapper(&mut self,
470+
with_id: ItemId,
470471
wrapping: ItemId,
471472
parent_id: ItemId,
472473
ty: &clang::Type,
473474
location: clang::Cursor) -> ItemId {
474475
use clangll::*;
475476
let mut args = vec![];
476477
let mut found_invalid_template_ref = false;
477-
let self_id = ItemId::next();
478478
location.visit(|c, _| {
479479
if c.kind() == CXCursor_TemplateRef &&
480480
c.cur_type().kind() == CXType_Invalid {
481481
found_invalid_template_ref = true;
482482
}
483483
if c.kind() == CXCursor_TypeRef {
484484
let new_ty =
485-
Item::from_ty_or_ref(c.cur_type(), Some(*c), Some(self_id), self);
485+
Item::from_ty_or_ref(c.cur_type(), Some(*c), Some(with_id), self);
486486
args.push(new_ty);
487487
}
488488
CXChildVisit_Continue
@@ -528,17 +528,18 @@ impl<'ctx> BindgenContext<'ctx> {
528528
let name = ty.spelling();
529529
let name = if name.is_empty() { None } else { Some(name) };
530530
let ty = Type::new(name, ty.fallible_layout().ok(), type_kind, ty.is_const());
531-
Item::new(self_id, None, None, parent_id, ItemKind::Type(ty))
531+
Item::new(with_id, None, None, parent_id, ItemKind::Type(ty))
532532
};
533533

534534
// Bypass all the validations in add_item explicitly.
535-
self.items.insert(self_id, item);
536-
self_id
535+
self.items.insert(with_id, item);
536+
with_id
537537
}
538538

539539
/// Looks up for an already resolved type, either because it's builtin, or
540540
/// because we already have it in the map.
541541
pub fn builtin_or_resolved_ty(&mut self,
542+
with_id: ItemId,
542543
parent_id: Option<ItemId>,
543544
ty: &clang::Type,
544545
location: Option<clang::Cursor>) -> Option<ItemId> {
@@ -567,6 +568,7 @@ impl<'ctx> BindgenContext<'ctx> {
567568
if let Some(id) = id {
568569
debug!("Already resolved ty {:?}, {:?}, {:?} {:?}",
569570
id, declaration, ty, location);
571+
570572
// If the declaration existed, we *might* be done, but it's not
571573
// the case for class templates, where the template arguments
572574
// may vary.
@@ -582,11 +584,12 @@ impl<'ctx> BindgenContext<'ctx> {
582584
*ty != canonical_declaration.cur_type() &&
583585
location.is_some() && parent_id.is_some() {
584586
return Some(
585-
self.build_template_wrapper(id, parent_id.unwrap(), ty,
587+
self.build_template_wrapper(with_id, id,
588+
parent_id.unwrap(), ty,
586589
location.unwrap()));
587590
}
588591

589-
return Some(self.build_ty_wrapper(id, parent_id, ty));
592+
return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
590593
}
591594
}
592595

@@ -602,19 +605,19 @@ impl<'ctx> BindgenContext<'ctx> {
602605
// We should probably make the constness tracking separate, so it doesn't
603606
// bloat that much, but hey, we already bloat the heck out of builtin types.
604607
fn build_ty_wrapper(&mut self,
608+
with_id: ItemId,
605609
wrapped_id: ItemId,
606610
parent_id: Option<ItemId>,
607611
ty: &clang::Type) -> ItemId {
608-
let id = ItemId::next();
609612
let spelling = ty.spelling();
610613
let is_const = ty.is_const();
611614
let layout = ty.fallible_layout().ok();
612615
let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
613616
let ty = Type::new(Some(spelling), layout, type_kind, is_const);
614-
let item = Item::new(id, None, None,
617+
let item = Item::new(with_id, None, None,
615618
parent_id.unwrap_or(self.current_module), ItemKind::Type(ty));
616619
self.add_builtin_item(item);
617-
id
620+
with_id
618621
}
619622

620623
fn build_builtin_ty(&mut self,

src/ir/item.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::ty::{Type, TypeKind};
77
use super::function::Function;
88
use super::module::Module;
99
use super::annotations::Annotations;
10-
use std::cell::Cell;
10+
use std::cell::{Cell, RefCell};
1111
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
1212
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
1313
use clang;
@@ -97,11 +97,25 @@ impl ItemCanonicalPath for ItemId {
9797
pub struct Item {
9898
/// This item's id.
9999
id: ItemId,
100-
/// The item's local id, unique only amongst its siblings. Only used
101-
/// for anonymous items. Lazily initialized in local_id().
100+
101+
/// The item's local id, unique only amongst its siblings. Only used for
102+
/// anonymous items.
103+
///
104+
/// Lazily initialized in local_id().
105+
///
106+
/// Note that only structs, unions, and enums get a local type id. In any
107+
/// case this is an implementation detail.
102108
local_id: Cell<Option<usize>>,
103-
/// The next local id to use for a child.
109+
110+
/// The next local id to use for a child..
104111
next_child_local_id: Cell<usize>,
112+
113+
/// A cached copy of the canonical name, as returned by `canonical_name`.
114+
///
115+
/// This is a fairly used operation during codegen so this makes bindgen
116+
/// considerably faster in those cases.
117+
canonical_name_cache: RefCell<Option<String>>,
118+
105119
/// A doc comment over the item, if any.
106120
comment: Option<String>,
107121
/// Annotations extracted from the doc comment, or the default ones
@@ -129,6 +143,7 @@ impl Item {
129143
id: id,
130144
local_id: Cell::new(None),
131145
next_child_local_id: Cell::new(1),
146+
canonical_name_cache: RefCell::new(None),
132147
parent_id: parent_id,
133148
comment: comment,
134149
annotations: annotations.unwrap_or_default(),
@@ -536,6 +551,10 @@ impl Item {
536551
_ => {}
537552
}
538553
}
554+
555+
// Note that this `id_` prefix prevents (really unlikely) collisions
556+
// between the global id and the local id of an item with the same
557+
// parent.
539558
format!("id_{}", self.id().0)
540559
}
541560

@@ -717,7 +736,9 @@ impl ClangItemParser for Item {
717736
.expect("Unable to resolve type");
718737
}
719738

720-
if let Some(ty) = context.builtin_or_resolved_ty(parent_id, &ty, location) {
739+
if let Some(ty) = context.builtin_or_resolved_ty(potential_id,
740+
parent_id, &ty,
741+
location) {
721742
debug!("{:?} already resolved: {:?}", ty, location);
722743
return ty;
723744
}
@@ -779,7 +800,8 @@ impl ClangItemParser for Item {
779800
context.replace(replaced, id);
780801
}
781802

782-
if let Some(ty) = context.builtin_or_resolved_ty(parent_id, ty, location) {
803+
if let Some(ty) = context.builtin_or_resolved_ty(id, parent_id,
804+
ty, location) {
783805
return Ok(ty);
784806
}
785807

@@ -917,7 +939,13 @@ impl ItemCanonicalName for Item {
917939
if let Some(other_canon_type) = self.annotations.use_instead_of() {
918940
return other_canon_type.to_owned();
919941
}
920-
self.real_canonical_name(ctx, ctx.options().enable_cxx_namespaces, false)
942+
if self.canonical_name_cache.borrow().is_none() {
943+
*self.canonical_name_cache.borrow_mut() =
944+
Some(self.real_canonical_name(ctx,
945+
ctx.options().enable_cxx_namespaces,
946+
false));
947+
}
948+
return self.canonical_name_cache.borrow().as_ref().unwrap().clone();
921949
}
922950
}
923951

src/ir/ty.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,8 @@ impl Type {
471471
parent_id: Option<ItemId>,
472472
ctx: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> {
473473
use clangll::*;
474-
if let Some(ty) = ctx.builtin_or_resolved_ty(parent_id, ty, location) {
474+
if let Some(ty) = ctx.builtin_or_resolved_ty(potential_id, parent_id,
475+
ty, location) {
475476
debug!("{:?} already resolved: {:?}", ty, location);
476477
return Ok(ParseResult::AlreadyResolved(ty));
477478
}
@@ -565,11 +566,17 @@ impl Type {
565566
return Err(ParseError::Continue);
566567
}
567568

568-
if args.is_empty() {
569-
error!("Failed to get any template parameter, maybe a specialization? {:?}", location);
570-
return Err(ParseError::Continue);
571-
}
572-
569+
// NB: `args` may be empty here (if for example the
570+
// template parameters are constants).
571+
//
572+
// We can't reject it here then because inner points
573+
// to `potential_id` now, so either we remove
574+
// `inner` and return an error, or carry on.
575+
//
576+
// In this case, we just carry on, since it seems
577+
// easier if than removing every possible reference
578+
// to `item` from `ctx`, and it doesn't give any
579+
// problems that we didn't have anyway.
573580
TypeKind::TemplateAlias(inner.unwrap(), args)
574581
}
575582
CXCursor_TemplateRef => {

tests/expectations/elaborated.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
pub type whatever_t = ::std::os::raw::c_int;
8+
extern "C" {
9+
#[link_name = "_Z9somethingPKi"]
10+
pub fn something(wat: *const whatever_t);
11+
}

tests/expectations/empty_template_param_name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![allow(non_snake_case)]
55

66

7+
pub type __void_t = ::std::os::raw::c_void;
78
#[repr(C)]
89
#[derive(Debug, Copy, Clone)]
910
pub struct __iterator_traits<_Iterator> {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+

tests/headers/elaborated.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace whatever {
2+
typedef int whatever_t;
3+
}
4+
5+
void something(const whatever::whatever_t *wat);

tests/headers/type_alias_empty.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// bindgen-flags: --whitelist-type bool_constant -- -std=c++11
2+
3+
// NB: The --whitelist-type is done to trigger the traversal of the types on
4+
// codegen in order to trigger #67.
5+
6+
template<typename T, T Val>
7+
struct integral_constant {};
8+
9+
template<bool B>
10+
using bool_constant = integral_constant<bool, B>;

0 commit comments

Comments
 (0)