Skip to content

Commit c2aaa08

Browse files
committed
wip
1 parent 600b282 commit c2aaa08

File tree

86 files changed

+11814
-176
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+11814
-176
lines changed

src/clang.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ impl fmt::Debug for Cursor {
2525
pub type CursorVisitor<'s> = for<'a, 'b> FnMut(&'a Cursor, &'b Cursor) -> Enum_CXChildVisitResult + 's;
2626

2727
impl Cursor {
28+
pub fn null() -> Self {
29+
Cursor { x: unsafe { clang_getNullCursor() } }
30+
}
31+
2832
// common
2933
pub fn spelling(&self) -> String {
3034
unsafe {
@@ -434,7 +438,7 @@ impl Type {
434438

435439
pub fn is_const(&self) -> bool {
436440
unsafe {
437-
clang_isConstQualifiedType(self.x) == 1
441+
clang_isConstQualifiedType(self.x) != 0
438442
}
439443
}
440444

src/codegen/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use ir::layout::Layout;
1313
use std::ops;
1414
use std::mem;
1515
use std::collections::BTreeSet;
16+
use std::collections::HashSet;
1617
use std::collections::hash_map::{HashMap, Entry};
1718

1819
use syntax::abi::Abi;
@@ -49,20 +50,30 @@ macro_rules! link_name {
4950
struct CodegenResult {
5051
items: Vec<P<ast::Item>>,
5152
saw_union: bool,
53+
items_seen: HashSet<ItemId>,
5254
}
5355

5456
impl CodegenResult {
5557
fn new() -> Self {
5658
CodegenResult {
5759
items: vec![],
5860
saw_union: false,
61+
items_seen: Default::default(),
5962
}
6063
}
6164

6265
fn saw_union(&mut self) {
6366
self.saw_union = true;
6467
}
6568

69+
fn seen(&self, item: ItemId) -> bool {
70+
self.items_seen.contains(&item)
71+
}
72+
73+
fn set_seen(&mut self, item: ItemId) {
74+
self.items_seen.insert(item);
75+
}
76+
6677
fn inner<F>(&mut self, cb: F) -> Vec<P<ast::Item>>
6778
where F: FnOnce(&mut Self)
6879
{
@@ -249,10 +260,12 @@ impl CodeGenerator for Item {
249260
ctx: &BindgenContext,
250261
result: &mut CodegenResult,
251262
_extra: &()) {
252-
if self.hidden(ctx) {
263+
if self.hidden(ctx) || result.seen(self.id()) {
253264
return;
254265
}
255266

267+
result.set_seen(self.id());
268+
256269
match *self.kind() {
257270
ItemKind::Module(ref module) => {
258271
if !ctx.options().enable_cxx_namespaces && self.id() == ctx.root_module() {
@@ -365,6 +378,7 @@ impl CodeGenerator for Type {
365378
TypeKind::Reference(..) |
366379
TypeKind::TemplateRef(..) |
367380
TypeKind::Function(..) |
381+
TypeKind::ResolvedTypeRef(..) |
368382
TypeKind::Named(..) => {
369383
// These items don't need code generation, they only need to be
370384
// converted to rust types in fields, arguments, and such.
@@ -425,6 +439,8 @@ impl CodeGenerator for Type {
425439
result.push(typedef)
426440
}
427441
TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
442+
ref u @ TypeKind::UnresolvedTypeRef(..)
443+
=> unreachable!("Should have been resolved after parsing {:?}!", u),
428444
}
429445
}
430446
}
@@ -1224,6 +1240,7 @@ impl ToRustTy for Type {
12241240

12251241
P(inner_ty)
12261242
}
1243+
TypeKind::ResolvedTypeRef(inner) => inner.to_rust_ty(ctx),
12271244
TypeKind::Alias(ref spelling, inner) => {
12281245
if item.opaque(ctx) {
12291246
// Pray if there's no available layout.
@@ -1260,6 +1277,8 @@ impl ToRustTy for Type {
12601277
let ident = ctx.rust_ident(&name);
12611278
quote_ty!(ctx.ext_cx(), $ident)
12621279
}
1280+
ref u @ TypeKind::UnresolvedTypeRef(..)
1281+
=> unreachable!("Should have been resolved after parsing {:?}!", u),
12631282
}
12641283
}
12651284
}

src/ir/comp.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,9 @@ impl CompInfo {
402402
for i in 0..len {
403403
let arg_type = ty.template_arg_type(i);
404404
if arg_type.kind() != CXType_Invalid {
405-
let type_id = Item::from_ty(&arg_type, None, None, ctx)
406-
.expect("Type not found in template specialization");
405+
let type_id =
406+
Item::from_ty_or_ref(arg_type, None, None, ctx);
407+
407408
list.push(type_id);
408409
} else {
409410
ci.has_non_type_template_params = true;

src/ir/context.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ pub struct BindgenContext<'ctx> {
6767
/// hard errors while parsing duplicated macros.
6868
parsed_macros: HashSet<String>,
6969

70+
collected_typerefs: bool,
71+
7072
/// Dummy structures for code generation.
7173
gen_ctx: Option<&'ctx GenContext<'ctx>>,
7274
span: Span,
@@ -100,6 +102,7 @@ impl<'ctx> BindgenContext<'ctx> {
100102
current_module: root_module.id(),
101103
currently_parsed_types: vec![],
102104
parsed_macros: Default::default(),
105+
collected_typerefs: false,
103106
gen_ctx: None,
104107
span: DUMMY_SP,
105108
index: index,
@@ -195,6 +198,44 @@ impl<'ctx> BindgenContext<'ctx> {
195198
self.items.iter()
196199
}
197200

201+
pub fn collected_typerefs(&self) -> bool {
202+
self.collected_typerefs
203+
}
204+
205+
fn collect_typerefs(&mut self) -> Vec<(ItemId, clang::Type, Option<clang::Cursor>)> {
206+
debug_assert!(!self.collected_typerefs);
207+
self.collected_typerefs = true;
208+
let mut typerefs = vec![];
209+
for (id, ref mut item) in &mut self.items {
210+
let kind = item.kind();
211+
let ty = match kind.as_type() {
212+
Some(ty) => ty,
213+
None => continue,
214+
};
215+
216+
let inner = match *ty.kind() {
217+
TypeKind::UnresolvedTypeRef(ref ty, loc) => {
218+
typerefs.push((*id, ty.clone(), loc));
219+
}
220+
_ => {},
221+
};
222+
}
223+
typerefs
224+
}
225+
226+
fn resolve_typerefs(&mut self) {
227+
let typerefs = self.collect_typerefs();
228+
229+
for (id, ty, loc) in typerefs {
230+
let resolved = Item::from_ty(&ty, loc, None, self)
231+
.expect("What happened?");
232+
let mut item = self.items.get_mut(&id).unwrap();
233+
234+
*item.kind_mut().as_type_mut().unwrap().kind_mut() =
235+
TypeKind::ResolvedTypeRef(resolved);
236+
}
237+
}
238+
198239
// Enters in the generation phase.
199240
pub fn gen<F, Out>(&mut self, cb: F) -> Out
200241
where F: FnOnce(&Self) -> Out
@@ -205,6 +246,8 @@ impl<'ctx> BindgenContext<'ctx> {
205246
use syntax::parse;
206247
use std::mem;
207248

249+
self.resolve_typerefs();
250+
208251
let cfg = ExpansionConfig::default("xxx".to_owned());
209252
let sess = parse::ParseSess::new();
210253
let mut loader = base::DummyMacroLoader;
@@ -263,7 +306,7 @@ impl<'ctx> BindgenContext<'ctx> {
263306
}
264307

265308
pub fn resolve_item(&self, item_id: ItemId) -> &Item {
266-
self.items.get(&item_id).unwrap()
309+
self.items.get(&item_id).expect("Not an item")
267310
}
268311

269312
pub fn current_module(&self) -> ItemId {

src/ir/item.rs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,26 @@ impl Item {
128128
&self.kind
129129
}
130130

131+
pub fn kind_mut(&mut self) -> &mut ItemKind {
132+
&mut self.kind
133+
}
134+
131135
pub fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
132-
if !ctx.options().enable_cxx_namespaces {
133-
self.parent_id == ctx.root_module()
134-
} else {
135-
self.id() == ctx.root_module()
136+
// FIXME: Workaround for some types falling behind when parsing weird
137+
// stl classes.
138+
if self.kind().is_type() && self.kind().expect_type().is_named() {
139+
return false;
140+
}
141+
142+
let mut parent = ctx.resolve_item(self.parent_id);
143+
loop {
144+
if parent.id() == ctx.root_module() {
145+
return true;
146+
} else if !parent.kind().is_module() {
147+
return false;
148+
}
149+
150+
parent = ctx.resolve_item(parent.parent_id());
136151
}
137152
}
138153

@@ -168,7 +183,8 @@ impl Item {
168183
TypeKind::Array(inner, _) |
169184
TypeKind::Pointer(inner) |
170185
TypeKind::Reference(inner) |
171-
TypeKind::Alias(_, inner) => {
186+
TypeKind::Alias(_, inner) |
187+
TypeKind::ResolvedTypeRef(inner) => {
172188
ctx.resolve_item(inner).applicable_template_args(ctx)
173189
}
174190
// XXX Is this completely correct? Partial template specialization
@@ -404,6 +420,34 @@ impl ClangItemParser for Item {
404420
Err(ParseError::Continue)
405421
}
406422

423+
fn from_ty_or_ref(ty: clang::Type,
424+
location: Option<clang::Cursor>,
425+
parent_id: Option<ItemId>,
426+
context: &mut BindgenContext) -> ItemId {
427+
use clangll::*;
428+
429+
if context.collected_typerefs() {
430+
return Self::from_ty(&ty, location, parent_id, context)
431+
.expect("Unable to resolve type");
432+
}
433+
434+
if let Some(ty) = context.builtin_or_resolved_ty(parent_id, &ty, location) {
435+
debug!("{:?} already resolved: {:?}", ty, location);
436+
return ty;
437+
}
438+
439+
let is_const = ty.is_const();
440+
let kind = TypeKind::UnresolvedTypeRef(ty, location);
441+
let id = ItemId::next();
442+
let current_module = context.current_module();
443+
context.add_item(Item::new(id, None, None,
444+
parent_id.unwrap_or(current_module),
445+
ItemKind::Type(Type::new(None, None, kind, is_const))),
446+
Some(clang::Cursor::null()),
447+
None);
448+
id
449+
}
450+
407451
fn from_ty(ty: &clang::Type,
408452
location: Option<clang::Cursor>,
409453
parent_id: Option<ItemId>,

src/ir/item_kind.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ impl ItemKind {
5757
}
5858
}
5959

60+
pub fn as_type_mut(&mut self) -> Option<&mut Type> {
61+
match *self {
62+
ItemKind::Type(ref mut ty) => Some(ty),
63+
_ => None,
64+
}
65+
}
66+
6067
pub fn is_type(&self) -> bool {
6168
self.as_type().is_some()
6269
}

src/ir/ty.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ impl Type {
5353
&self.kind
5454
}
5555

56+
pub fn kind_mut(&mut self) -> &mut TypeKind {
57+
&mut self.kind
58+
}
59+
5660
pub fn name(&self) -> Option<&str> {
5761
self.name.as_ref().map(|name| &**name)
5862
}
@@ -230,9 +234,13 @@ impl Type {
230234
TypeKind::NullPtr |
231235
TypeKind::Pointer(..) => self,
232236

237+
TypeKind::ResolvedTypeRef(inner) |
233238
TypeKind::Alias(_, inner) |
234239
TypeKind::TemplateRef(inner, _)
235240
=> type_resolver.resolve_type(inner).canonical_type(type_resolver),
241+
242+
TypeKind::UnresolvedTypeRef(..)
243+
=> unreachable!("Should have been resolved after parsing!"),
236244
}
237245
}
238246
}
@@ -278,6 +286,17 @@ pub enum TypeKind {
278286
/// see why this is needed, check out the creation of this variant in
279287
/// `Type::from_clang_ty`.
280288
TemplateRef(ItemId, Vec<ItemId>),
289+
290+
/// A reference to a yet-to-resolve type. This stores the clang cursor
291+
/// itself, and postpones its resolution.
292+
///
293+
/// These are gone in a phase after parsing where these are mapped to
294+
/// already known types, and are converted to ResolvedTypeRef.
295+
///
296+
/// see tests/headers/typeref.hpp to see somewhere where this is a problem.
297+
UnresolvedTypeRef(clang::Type, Option<clang::Cursor>),
298+
ResolvedTypeRef(ItemId),
299+
281300
/// A named type, that is, a template parameter, with an optional default
282301
/// type.
283302
Named(String, Option<ItemId>),
@@ -292,6 +311,7 @@ impl Type {
292311
size == 0 ||
293312
type_resolver.resolve_type(inner).is_unsized(type_resolver)
294313
}
314+
TypeKind::ResolvedTypeRef(inner) |
295315
TypeKind::Alias(_, inner) |
296316
TypeKind::TemplateRef(inner, _)
297317
=> type_resolver.resolve_type(inner).is_unsized(type_resolver),
@@ -303,6 +323,9 @@ impl Type {
303323
TypeKind::Reference(..) |
304324
TypeKind::NullPtr |
305325
TypeKind::Pointer(..) => false,
326+
327+
TypeKind::UnresolvedTypeRef(..)
328+
=> unreachable!("Should have been resolved after parsing!"),
306329
}
307330
}
308331

@@ -389,18 +412,25 @@ impl Type {
389412
return Err(ParseError::Continue);
390413
}
391414
}
415+
// NOTE: We don't resolve pointers eagerly because the pointee type
416+
// might not have been parsed, and if it contains templates or
417+
// something else we might get confused, see the comment inside
418+
// TypeRef.
419+
//
420+
// We might need to, though, if the context is already in the
421+
// process of resolving them.
392422
CXType_MemberPointer |
393423
CXType_Pointer => {
394-
let inner = Item::from_ty(&ty.pointee_type(), location, parent_id, ctx)
395-
.expect("Not able to resolve pointee?");
424+
let inner =
425+
Item::from_ty_or_ref(ty.pointee_type(), location, parent_id, ctx);
396426
TypeKind::Pointer(inner)
397427
}
398428
// XXX: RValueReference is most likely wrong, but I don't think we
399429
// can even add bindings for that, so huh.
400430
CXType_RValueReference |
401431
CXType_LValueReference => {
402-
let inner = Item::from_ty(&ty.pointee_type(), location, parent_id, ctx)
403-
.expect("Not able to resolve pointee?");
432+
let inner =
433+
Item::from_ty_or_ref(ty.pointee_type(), location, parent_id, ctx);
404434
TypeKind::Reference(inner)
405435
}
406436
// XXX DependentSizedArray is wrong
@@ -418,8 +448,8 @@ impl Type {
418448
}
419449
CXType_Typedef => {
420450
let inner = cursor.typedef_type();
421-
let inner = Item::from_ty(&inner, location, parent_id, ctx)
422-
.expect("Not able to resolve array element?");
451+
let inner =
452+
Item::from_ty_or_ref(inner, location, parent_id, ctx);
423453
TypeKind::Alias(ty.spelling(), inner)
424454
}
425455
CXType_Enum => {

0 commit comments

Comments
 (0)