Skip to content

Commit 33debb3

Browse files
author
bors-servo
authored
Auto merge of #58 - emilio:funcs, r=nox
Some function pointers, typedefs, and OSX's stdlib. r? @nox The change from indexing cursors to index USRs was because in the `inner_template_self` test, the `next` pointer pointed to a clang-generated class declaration that caused us to not catch the type as already resolved. Also, that's the recommended way to check against same symbols from different translation units, though now we don't use it yet.
2 parents f318b63 + cc8ed87 commit 33debb3

32 files changed

+372
-176
lines changed

src/clang.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,23 @@ pub struct Cursor {
1717

1818
impl fmt::Debug for Cursor {
1919
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
20-
write!(fmt, "Cursor({} kind: {}, loc: {})",
21-
self.spelling(), kind_to_str(self.kind()), self.location())
20+
write!(fmt, "Cursor({} kind: {}, loc: {}, usr: {:?})",
21+
self.spelling(), kind_to_str(self.kind()), self.location(), self.usr())
2222
}
2323
}
2424

2525
pub type CursorVisitor<'s> = for<'a, 'b> FnMut(&'a Cursor, &'b Cursor) -> Enum_CXChildVisitResult + 's;
2626

2727
impl Cursor {
28+
pub fn usr(&self) -> Option<String> {
29+
let s = String_ { x: unsafe { clang_getCursorUSR(self.x) } }.to_string();
30+
if s.is_empty() {
31+
None
32+
} else {
33+
Some(s)
34+
}
35+
}
36+
2837
pub fn is_declaration(&self) -> bool {
2938
unsafe { clang_isDeclaration(self.kind()) != 0 }
3039
}

src/codegen/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ impl CodeGenerator for Type {
311311
TypeKind::Float(..) |
312312
TypeKind::Array(..) |
313313
TypeKind::Pointer(..) |
314+
TypeKind::BlockPointer |
314315
TypeKind::Reference(..) |
315316
TypeKind::TemplateRef(..) |
316317
TypeKind::Function(..) |
@@ -1306,6 +1307,11 @@ impl ToRustTy for Type {
13061307
IntKind::ULongLong => raw!(c_ulonglong),
13071308
IntKind::U16 => aster::ty::TyBuilder::new().u16(),
13081309
IntKind::U32 => aster::ty::TyBuilder::new().u32(),
1310+
// FIXME: This doesn't generate the proper alignment, but we
1311+
// can't do better right now. We should be able to use
1312+
// i128/u128 when they're available.
1313+
IntKind::U128 |
1314+
IntKind::I128 => ArrayTyBuilder::new().with_len(2).build(aster::ty::TyBuilder::new().u64()),
13091315
}
13101316
}
13111317
TypeKind::Float(fk) => {
@@ -1377,10 +1383,23 @@ impl ToRustTy for Type {
13771383

13781384
utils::build_templated_path(item, ctx, false)
13791385
}
1386+
TypeKind::BlockPointer => {
1387+
let void = raw!(c_void);
1388+
void.to_ptr(/* is_const = */ false, ctx.span())
1389+
}
13801390
TypeKind::Pointer(inner) |
13811391
TypeKind::Reference(inner) => {
13821392
let inner = ctx.resolve_item(inner);
1383-
inner.to_rust_ty(ctx).to_ptr(inner.expect_type().is_const(), ctx.span())
1393+
let inner_ty = inner.expect_type();
1394+
let ty = inner.to_rust_ty(ctx);
1395+
1396+
// Avoid the first function pointer level, since it's already
1397+
// represented in Rust.
1398+
if inner_ty.canonical_type(ctx).is_function() {
1399+
ty
1400+
} else {
1401+
ty.to_ptr(inner.expect_type().is_const(), ctx.span())
1402+
}
13841403
}
13851404
TypeKind::Named(..) => {
13861405
let name = item.canonical_name(ctx);

src/ir/context.rs

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ use syntax::ext::base::ExtCtxt;
1414
use parse::ClangItemParser;
1515
use BindgenOptions;
1616

17+
/// A key used to index a resolved type, so we only process it once.
18+
///
19+
/// This is almost always a USR string (an unique identifier generated by
20+
/// clang), but it can also be the canonical declaration if the type is unnamed,
21+
/// in which case clang may generate the same USR for multiple nested unnamed
22+
/// types.
23+
#[derive(Eq, PartialEq, Hash, Debug)]
24+
enum TypeKey {
25+
USR(String),
26+
Declaration(Cursor),
27+
}
28+
1729
// This is just convenience to avoid creating a manual debug impl for the
1830
// context.
1931
struct GenContext<'ctx>(ExtCtxt<'ctx>);
@@ -33,11 +45,9 @@ pub struct BindgenContext<'ctx> {
3345
/// output.
3446
items: BTreeMap<ItemId, Item>,
3547

36-
/// Clang cursor to type map. This is needed to be able to associate types
37-
/// with item ids during parsing.
38-
///
39-
/// The cursor used for storage is the definition cursor.
40-
types: HashMap<Cursor, ItemId>,
48+
/// Clang USR to type map. This is needed to be able to associate types with
49+
/// item ids during parsing.
50+
types: HashMap<TypeKey, ItemId>,
4151

4252
/// A cursor to module map. Similar reason than above.
4353
modules: HashMap<Cursor, ItemId>,
@@ -131,29 +141,46 @@ impl<'ctx> BindgenContext<'ctx> {
131141

132142
let id = item.id();
133143
let is_type = item.kind().is_type();
144+
let is_unnamed = is_type && item.expect_type().name().is_none();
134145
let old_item = self.items.insert(id, item);
135146
assert!(old_item.is_none(), "Inserted type twice?");
136147

148+
// Unnamed items can have an USR, but they can't be referenced from
149+
// other sites explicitly and the USR can match if the unnamed items are
150+
// nested, so don't bother tracking them.
137151
if is_type && declaration.is_some() {
138-
let declaration = declaration.unwrap();
139-
debug_assert_eq!(declaration, declaration.canonical());
140-
if declaration.is_valid() {
141-
let old = self.types.insert(declaration, id);
142-
debug_assert_eq!(old, None);
143-
} else if location.is_some() &&
144-
(location.unwrap().kind() == CXCursor_ClassTemplate ||
145-
location.unwrap().kind() == CXCursor_ClassTemplatePartialSpecialization) {
146-
let old = self.types.insert(location.unwrap().canonical(), id);
147-
debug_assert_eq!(old, None);
148-
} else {
152+
let mut declaration = declaration.unwrap();
153+
if !declaration.is_valid() {
154+
if let Some(location) = location {
155+
if location.kind() == CXCursor_ClassTemplate ||
156+
location.kind() == CXCursor_ClassTemplatePartialSpecialization {
157+
declaration = location;
158+
}
159+
}
160+
}
161+
declaration = declaration.canonical();
162+
if !declaration.is_valid() {
149163
// This could happen, for example, with types like `int*` or
150164
// similar.
151165
//
152166
// Fortunately, we don't care about those types being
153167
// duplicated, so we can just ignore them.
154168
debug!("Invalid declaration {:?} found for type {:?}",
155169
declaration, self.items.get(&id).unwrap().kind().expect_type());
170+
return;
156171
}
172+
173+
let key = if is_unnamed {
174+
TypeKey::Declaration(declaration)
175+
} else if let Some(usr) = declaration.usr() {
176+
TypeKey::USR(usr)
177+
} else {
178+
error!("Valid declaration with no USR: {:?}, {:?}", declaration, location);
179+
return;
180+
};
181+
182+
let old = self.types.insert(key, id);
183+
debug_assert_eq!(old, None);
157184
}
158185
}
159186

@@ -206,7 +233,7 @@ impl<'ctx> BindgenContext<'ctx> {
206233
self.collected_typerefs
207234
}
208235

209-
fn collect_typerefs(&mut self) -> Vec<(ItemId, clang::Type, Option<clang::Cursor>)> {
236+
fn collect_typerefs(&mut self) -> Vec<(ItemId, clang::Type, Option<clang::Cursor>, Option<ItemId>)> {
210237
debug_assert!(!self.collected_typerefs);
211238
self.collected_typerefs = true;
212239
let mut typerefs = vec![];
@@ -218,8 +245,8 @@ impl<'ctx> BindgenContext<'ctx> {
218245
};
219246

220247
match *ty.kind() {
221-
TypeKind::UnresolvedTypeRef(ref ty, loc) => {
222-
typerefs.push((*id, ty.clone(), loc));
248+
TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) => {
249+
typerefs.push((*id, ty.clone(), loc, parent_id));
223250
}
224251
_ => {},
225252
};
@@ -230,9 +257,9 @@ impl<'ctx> BindgenContext<'ctx> {
230257
fn resolve_typerefs(&mut self) {
231258
let typerefs = self.collect_typerefs();
232259

233-
for (id, ty, loc) in typerefs {
260+
for (id, ty, loc, parent_id) in typerefs {
234261
let _resolved = {
235-
let resolved = Item::from_ty(&ty, loc, None, self)
262+
let resolved = Item::from_ty(&ty, loc, parent_id, self)
236263
.expect("What happened?");
237264
let mut item = self.items.get_mut(&id).unwrap();
238265

@@ -494,8 +521,15 @@ impl<'ctx> BindgenContext<'ctx> {
494521
}
495522
let canonical_declaration = declaration.canonical();
496523
if canonical_declaration.is_valid() {
497-
// First lookup to see if we already have it resolved.
498-
let id = self.types.get(&canonical_declaration).map(|id| *id);
524+
let id =
525+
self.types.get(&TypeKey::Declaration(canonical_declaration))
526+
.map(|id| *id)
527+
.or_else(|| {
528+
canonical_declaration.usr().and_then(|usr| {
529+
self.types.get(&TypeKey::USR(usr))
530+
})
531+
.map(|id| *id)
532+
});
499533
if let Some(id) = id {
500534
debug!("Already resolved ty {:?}, {:?}, {:?} {:?}",
501535
id, declaration, ty, location);
@@ -572,6 +606,8 @@ impl<'ctx> BindgenContext<'ctx> {
572606
CXType_ULong => TypeKind::Int(IntKind::ULong),
573607
CXType_LongLong => TypeKind::Int(IntKind::LongLong),
574608
CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
609+
CXType_Int128 => TypeKind::Int(IntKind::I128),
610+
CXType_UInt128 => TypeKind::Int(IntKind::U128),
575611
CXType_Float => TypeKind::Float(FloatKind::Float),
576612
CXType_Double => TypeKind::Float(FloatKind::Double),
577613
CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),

src/ir/int.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pub enum IntKind {
1313
ULongLong,
1414
U16, // For Char16 and Wchar
1515
U32, // For Char32
16+
I128,
17+
U128,
1618
// Though now we're at it we could add equivalents for the rust types...
1719
}
1820

@@ -21,10 +23,10 @@ impl IntKind {
2123
use self::IntKind::*;
2224
match *self {
2325
Bool | UChar | UShort |
24-
UInt | ULong | ULongLong | U16 | U32 => false,
26+
UInt | ULong | ULongLong | U16 | U32 | U128 => false,
2527

2628
Char | Short | Int |
27-
Long | LongLong => true,
29+
Long | LongLong | I128 => true,
2830
}
2931
}
3032
}

src/ir/item.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,19 @@ impl Item {
191191
TypeKind::Array(inner, _) |
192192
TypeKind::Pointer(inner) |
193193
TypeKind::Reference(inner) |
194-
TypeKind::Alias(_, inner) |
195194
TypeKind::ResolvedTypeRef(inner) => {
196195
ctx.resolve_item(inner).applicable_template_args(ctx)
197196
}
197+
TypeKind::Alias(_, inner) => {
198+
let parent_args = ctx.resolve_item(self.parent_id())
199+
.applicable_template_args(ctx);
200+
let inner = ctx.resolve_type(inner);
201+
// Avoid unused type parameters, sigh.
202+
parent_args.iter().cloned().filter(|arg| {
203+
let arg = ctx.resolve_type(*arg);
204+
arg.is_named() && inner.signature_contains_named_type(ctx, arg)
205+
}).collect()
206+
}
198207
// XXX Is this completely correct? Partial template specialization
199208
// is hard anyways, sigh...
200209
TypeKind::TemplateRef(_, ref args) => {
@@ -436,11 +445,19 @@ impl ClangItemParser for Item {
436445
location: Option<clang::Cursor>,
437446
parent_id: Option<ItemId>,
438447
context: &mut BindgenContext) -> ItemId {
439-
debug!("from_ty_or_ref: {:?}, {:?}, {:?}", ty, location, parent_id);
448+
Self::from_ty_or_ref_with_id(ItemId::next(), ty, location, parent_id, context)
449+
}
450+
451+
fn from_ty_or_ref_with_id(potential_id: ItemId,
452+
ty: clang::Type,
453+
location: Option<clang::Cursor>,
454+
parent_id: Option<ItemId>,
455+
context: &mut BindgenContext) -> ItemId {
456+
debug!("from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}", potential_id, ty, location, parent_id);
440457

441458
if context.collected_typerefs() {
442459
debug!("refs already collected, resolving directly");
443-
return Self::from_ty(&ty, location, parent_id, context)
460+
return Self::from_ty_with_id(potential_id, &ty, location, parent_id, context)
444461
.expect("Unable to resolve type");
445462
}
446463

@@ -452,15 +469,14 @@ impl ClangItemParser for Item {
452469
debug!("New unresolved type reference: {:?}, {:?}", ty, location);
453470

454471
let is_const = ty.is_const();
455-
let kind = TypeKind::UnresolvedTypeRef(ty, location);
456-
let id = ItemId::next();
472+
let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id);
457473
let current_module = context.current_module();
458-
context.add_item(Item::new(id, None, None,
474+
context.add_item(Item::new(potential_id, None, None,
459475
parent_id.unwrap_or(current_module),
460476
ItemKind::Type(Type::new(None, None, kind, is_const))),
461477
Some(clang::Cursor::null()),
462478
None);
463-
id
479+
potential_id
464480
}
465481

466482

0 commit comments

Comments
 (0)