1 //! Everything related to types in our intermediate representation.
2
3 use super::comp::CompInfo;
4 use super::context::{BindgenContext, ItemId, TypeId};
5 use super::dot::DotAttributes;
6 use super::enum_ty::Enum;
7 use super::function::FunctionSig;
8 use super::int::IntKind;
9 use super::item::{IsOpaque, Item};
10 use super::layout::{Layout, Opaque};
11 use super::objc::ObjCInterface;
12 use super::template::{
13 AsTemplateParam, TemplateInstantiation, TemplateParameters,
14 };
15 use super::traversal::{EdgeKind, Trace, Tracer};
16 use crate::clang::{self, Cursor};
17 use crate::parse::{ClangItemParser, ParseError, ParseResult};
18 use std::borrow::Cow;
19 use std::io;
20
21 /// The base representation of a type in bindgen.
22 ///
23 /// A type has an optional name, which if present cannot be empty, a `layout`
24 /// (size, alignment and packedness) if known, a `Kind`, which determines which
25 /// kind of type it is, and whether the type is const.
26 #[derive(Debug)]
27 pub struct Type {
28 /// The name of the type, or None if it was an unnamed struct or union.
29 name: Option<String>,
30 /// The layout of the type, if known.
31 layout: Option<Layout>,
32 /// The inner kind of the type
33 kind: TypeKind,
34 /// Whether this type is const-qualified.
35 is_const: bool,
36 }
37
38 /// The maximum number of items in an array for which Rust implements common
39 /// traits, and so if we have a type containing an array with more than this
40 /// many items, we won't be able to derive common traits on that type.
41 ///
42 pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
43
44 impl Type {
45 /// Get the underlying `CompInfo` for this type, or `None` if this is some
46 /// other kind of type.
as_comp(&self) -> Option<&CompInfo>47 pub fn as_comp(&self) -> Option<&CompInfo> {
48 match self.kind {
49 TypeKind::Comp(ref ci) => Some(ci),
50 _ => None,
51 }
52 }
53
54 /// Get the underlying `CompInfo` for this type as a mutable reference, or
55 /// `None` if this is some other kind of type.
as_comp_mut(&mut self) -> Option<&mut CompInfo>56 pub fn as_comp_mut(&mut self) -> Option<&mut CompInfo> {
57 match self.kind {
58 TypeKind::Comp(ref mut ci) => Some(ci),
59 _ => None,
60 }
61 }
62
63 /// Construct a new `Type`.
new( name: Option<String>, layout: Option<Layout>, kind: TypeKind, is_const: bool, ) -> Self64 pub fn new(
65 name: Option<String>,
66 layout: Option<Layout>,
67 kind: TypeKind,
68 is_const: bool,
69 ) -> Self {
70 Type {
71 name,
72 layout,
73 kind,
74 is_const,
75 }
76 }
77
78 /// Which kind of type is this?
kind(&self) -> &TypeKind79 pub fn kind(&self) -> &TypeKind {
80 &self.kind
81 }
82
83 /// Get a mutable reference to this type's kind.
kind_mut(&mut self) -> &mut TypeKind84 pub fn kind_mut(&mut self) -> &mut TypeKind {
85 &mut self.kind
86 }
87
88 /// Get this type's name.
name(&self) -> Option<&str>89 pub fn name(&self) -> Option<&str> {
90 self.name.as_deref()
91 }
92
93 /// Whether this is a block pointer type.
is_block_pointer(&self) -> bool94 pub fn is_block_pointer(&self) -> bool {
95 matches!(self.kind, TypeKind::BlockPointer(..))
96 }
97
98 /// Is this a compound type?
is_comp(&self) -> bool99 pub fn is_comp(&self) -> bool {
100 matches!(self.kind, TypeKind::Comp(..))
101 }
102
103 /// Is this a union?
is_union(&self) -> bool104 pub fn is_union(&self) -> bool {
105 match self.kind {
106 TypeKind::Comp(ref comp) => comp.is_union(),
107 _ => false,
108 }
109 }
110
111 /// Is this type of kind `TypeKind::TypeParam`?
is_type_param(&self) -> bool112 pub fn is_type_param(&self) -> bool {
113 matches!(self.kind, TypeKind::TypeParam)
114 }
115
116 /// Is this a template instantiation type?
is_template_instantiation(&self) -> bool117 pub fn is_template_instantiation(&self) -> bool {
118 matches!(self.kind, TypeKind::TemplateInstantiation(..))
119 }
120
121 /// Is this a template alias type?
is_template_alias(&self) -> bool122 pub fn is_template_alias(&self) -> bool {
123 matches!(self.kind, TypeKind::TemplateAlias(..))
124 }
125
126 /// Is this a function type?
is_function(&self) -> bool127 pub fn is_function(&self) -> bool {
128 matches!(self.kind, TypeKind::Function(..))
129 }
130
131 /// Is this an enum type?
is_enum(&self) -> bool132 pub fn is_enum(&self) -> bool {
133 matches!(self.kind, TypeKind::Enum(..))
134 }
135
136 /// Is this either a builtin or named type?
is_builtin_or_type_param(&self) -> bool137 pub fn is_builtin_or_type_param(&self) -> bool {
138 matches!(
139 self.kind,
140 TypeKind::Void |
141 TypeKind::NullPtr |
142 TypeKind::Function(..) |
143 TypeKind::Array(..) |
144 TypeKind::Reference(..) |
145 TypeKind::Pointer(..) |
146 TypeKind::Int(..) |
147 TypeKind::Float(..) |
148 TypeKind::TypeParam
149 )
150 }
151
152 /// Creates a new named type, with name `name`.
named(name: String) -> Self153 pub fn named(name: String) -> Self {
154 let name = if name.is_empty() { None } else { Some(name) };
155 Self::new(name, None, TypeKind::TypeParam, false)
156 }
157
158 /// Is this a floating point type?
is_float(&self) -> bool159 pub fn is_float(&self) -> bool {
160 matches!(self.kind, TypeKind::Float(..))
161 }
162
163 /// Is this a boolean type?
is_bool(&self) -> bool164 pub fn is_bool(&self) -> bool {
165 matches!(self.kind, TypeKind::Int(IntKind::Bool))
166 }
167
168 /// Is this an integer type?
is_integer(&self) -> bool169 pub fn is_integer(&self) -> bool {
170 matches!(self.kind, TypeKind::Int(..))
171 }
172
173 /// Cast this type to an integer kind, or `None` if it is not an integer
174 /// type.
as_integer(&self) -> Option<IntKind>175 pub fn as_integer(&self) -> Option<IntKind> {
176 match self.kind {
177 TypeKind::Int(int_kind) => Some(int_kind),
178 _ => None,
179 }
180 }
181
182 /// Is this a `const` qualified type?
is_const(&self) -> bool183 pub fn is_const(&self) -> bool {
184 self.is_const
185 }
186
187 /// Is this a reference to another type?
is_type_ref(&self) -> bool188 pub fn is_type_ref(&self) -> bool {
189 matches!(
190 self.kind,
191 TypeKind::ResolvedTypeRef(_) | TypeKind::UnresolvedTypeRef(_, _, _)
192 )
193 }
194
195 /// Is this an unresolved reference?
is_unresolved_ref(&self) -> bool196 pub fn is_unresolved_ref(&self) -> bool {
197 matches!(self.kind, TypeKind::UnresolvedTypeRef(_, _, _))
198 }
199
200 /// Is this a incomplete array type?
is_incomplete_array(&self, ctx: &BindgenContext) -> Option<ItemId>201 pub fn is_incomplete_array(&self, ctx: &BindgenContext) -> Option<ItemId> {
202 match self.kind {
203 TypeKind::Array(item, len) => {
204 if len == 0 {
205 Some(item.into())
206 } else {
207 None
208 }
209 }
210 TypeKind::ResolvedTypeRef(inner) => {
211 ctx.resolve_type(inner).is_incomplete_array(ctx)
212 }
213 _ => None,
214 }
215 }
216
217 /// What is the layout of this type?
layout(&self, ctx: &BindgenContext) -> Option<Layout>218 pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
219 self.layout.or_else(|| {
220 match self.kind {
221 TypeKind::Comp(ref ci) => ci.layout(ctx),
222 TypeKind::Array(inner, length) if length == 0 => Some(
223 Layout::new(0, ctx.resolve_type(inner).layout(ctx)?.align),
224 ),
225 // FIXME(emilio): This is a hack for anonymous union templates.
226 // Use the actual pointer size!
227 TypeKind::Pointer(..) => Some(Layout::new(
228 ctx.target_pointer_size(),
229 ctx.target_pointer_size(),
230 )),
231 TypeKind::ResolvedTypeRef(inner) => {
232 ctx.resolve_type(inner).layout(ctx)
233 }
234 _ => None,
235 }
236 })
237 }
238
239 /// Whether this named type is an invalid C++ identifier. This is done to
240 /// avoid generating invalid code with some cases we can't handle, see:
241 ///
242 /// tests/headers/381-decltype-alias.hpp
is_invalid_type_param(&self) -> bool243 pub fn is_invalid_type_param(&self) -> bool {
244 match self.kind {
245 TypeKind::TypeParam => {
246 let name = self.name().expect("Unnamed named type?");
247 !clang::is_valid_identifier(name)
248 }
249 _ => false,
250 }
251 }
252
253 /// Takes `name`, and returns a suitable identifier representation for it.
sanitize_name(name: &str) -> Cow<str>254 fn sanitize_name(name: &str) -> Cow<str> {
255 if clang::is_valid_identifier(name) {
256 return Cow::Borrowed(name);
257 }
258
259 let name = name.replace(|c| c == ' ' || c == ':' || c == '.', "_");
260 Cow::Owned(name)
261 }
262
263 /// Get this type's santizied name.
sanitized_name<'a>( &'a self, ctx: &BindgenContext, ) -> Option<Cow<'a, str>>264 pub fn sanitized_name<'a>(
265 &'a self,
266 ctx: &BindgenContext,
267 ) -> Option<Cow<'a, str>> {
268 let name_info = match *self.kind() {
269 TypeKind::Pointer(inner) => Some((inner, Cow::Borrowed("ptr"))),
270 TypeKind::Reference(inner) => Some((inner, Cow::Borrowed("ref"))),
271 TypeKind::Array(inner, length) => {
272 Some((inner, format!("array{}", length).into()))
273 }
274 _ => None,
275 };
276 if let Some((inner, prefix)) = name_info {
277 ctx.resolve_item(inner)
278 .expect_type()
279 .sanitized_name(ctx)
280 .map(|name| format!("{}_{}", prefix, name).into())
281 } else {
282 self.name().map(Self::sanitize_name)
283 }
284 }
285
286 /// See safe_canonical_type.
canonical_type<'tr>( &'tr self, ctx: &'tr BindgenContext, ) -> &'tr Type287 pub fn canonical_type<'tr>(
288 &'tr self,
289 ctx: &'tr BindgenContext,
290 ) -> &'tr Type {
291 self.safe_canonical_type(ctx)
292 .expect("Should have been resolved after parsing!")
293 }
294
295 /// Returns the canonical type of this type, that is, the "inner type".
296 ///
297 /// For example, for a `typedef`, the canonical type would be the
298 /// `typedef`ed type, for a template instantiation, would be the template
299 /// its specializing, and so on. Return None if the type is unresolved.
safe_canonical_type<'tr>( &'tr self, ctx: &'tr BindgenContext, ) -> Option<&'tr Type>300 pub fn safe_canonical_type<'tr>(
301 &'tr self,
302 ctx: &'tr BindgenContext,
303 ) -> Option<&'tr Type> {
304 match self.kind {
305 TypeKind::TypeParam |
306 TypeKind::Array(..) |
307 TypeKind::Vector(..) |
308 TypeKind::Comp(..) |
309 TypeKind::Opaque |
310 TypeKind::Int(..) |
311 TypeKind::Float(..) |
312 TypeKind::Complex(..) |
313 TypeKind::Function(..) |
314 TypeKind::Enum(..) |
315 TypeKind::Reference(..) |
316 TypeKind::Void |
317 TypeKind::NullPtr |
318 TypeKind::Pointer(..) |
319 TypeKind::BlockPointer(..) |
320 TypeKind::ObjCId |
321 TypeKind::ObjCSel |
322 TypeKind::ObjCInterface(..) => Some(self),
323
324 TypeKind::ResolvedTypeRef(inner) |
325 TypeKind::Alias(inner) |
326 TypeKind::TemplateAlias(inner, _) => {
327 ctx.resolve_type(inner).safe_canonical_type(ctx)
328 }
329 TypeKind::TemplateInstantiation(ref inst) => ctx
330 .resolve_type(inst.template_definition())
331 .safe_canonical_type(ctx),
332
333 TypeKind::UnresolvedTypeRef(..) => None,
334 }
335 }
336
337 /// There are some types we don't want to stop at when finding an opaque
338 /// item, so we can arrive to the proper item that needs to be generated.
should_be_traced_unconditionally(&self) -> bool339 pub fn should_be_traced_unconditionally(&self) -> bool {
340 matches!(
341 self.kind,
342 TypeKind::Comp(..) |
343 TypeKind::Function(..) |
344 TypeKind::Pointer(..) |
345 TypeKind::Array(..) |
346 TypeKind::Reference(..) |
347 TypeKind::TemplateInstantiation(..) |
348 TypeKind::ResolvedTypeRef(..)
349 )
350 }
351 }
352
353 impl IsOpaque for Type {
354 type Extra = Item;
355
is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool356 fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool {
357 match self.kind {
358 TypeKind::Opaque => true,
359 TypeKind::TemplateInstantiation(ref inst) => {
360 inst.is_opaque(ctx, item)
361 }
362 TypeKind::Comp(ref comp) => comp.is_opaque(ctx, &self.layout),
363 TypeKind::ResolvedTypeRef(to) => to.is_opaque(ctx, &()),
364 _ => false,
365 }
366 }
367 }
368
369 impl AsTemplateParam for Type {
370 type Extra = Item;
371
as_template_param( &self, ctx: &BindgenContext, item: &Item, ) -> Option<TypeId>372 fn as_template_param(
373 &self,
374 ctx: &BindgenContext,
375 item: &Item,
376 ) -> Option<TypeId> {
377 self.kind.as_template_param(ctx, item)
378 }
379 }
380
381 impl AsTemplateParam for TypeKind {
382 type Extra = Item;
383
as_template_param( &self, ctx: &BindgenContext, item: &Item, ) -> Option<TypeId>384 fn as_template_param(
385 &self,
386 ctx: &BindgenContext,
387 item: &Item,
388 ) -> Option<TypeId> {
389 match *self {
390 TypeKind::TypeParam => Some(item.id().expect_type_id(ctx)),
391 TypeKind::ResolvedTypeRef(id) => id.as_template_param(ctx, &()),
392 _ => None,
393 }
394 }
395 }
396
397 impl DotAttributes for Type {
dot_attributes<W>( &self, ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,398 fn dot_attributes<W>(
399 &self,
400 ctx: &BindgenContext,
401 out: &mut W,
402 ) -> io::Result<()>
403 where
404 W: io::Write,
405 {
406 if let Some(ref layout) = self.layout {
407 writeln!(
408 out,
409 "<tr><td>size</td><td>{}</td></tr>
410 <tr><td>align</td><td>{}</td></tr>",
411 layout.size, layout.align
412 )?;
413 if layout.packed {
414 writeln!(out, "<tr><td>packed</td><td>true</td></tr>")?;
415 }
416 }
417
418 if self.is_const {
419 writeln!(out, "<tr><td>const</td><td>true</td></tr>")?;
420 }
421
422 self.kind.dot_attributes(ctx, out)
423 }
424 }
425
426 impl DotAttributes for TypeKind {
dot_attributes<W>( &self, ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,427 fn dot_attributes<W>(
428 &self,
429 ctx: &BindgenContext,
430 out: &mut W,
431 ) -> io::Result<()>
432 where
433 W: io::Write,
434 {
435 writeln!(
436 out,
437 "<tr><td>type kind</td><td>{}</td></tr>",
438 self.kind_name()
439 )?;
440
441 if let TypeKind::Comp(ref comp) = *self {
442 comp.dot_attributes(ctx, out)?;
443 }
444
445 Ok(())
446 }
447 }
448
449 impl TypeKind {
kind_name(&self) -> &'static str450 fn kind_name(&self) -> &'static str {
451 match *self {
452 TypeKind::Void => "Void",
453 TypeKind::NullPtr => "NullPtr",
454 TypeKind::Comp(..) => "Comp",
455 TypeKind::Opaque => "Opaque",
456 TypeKind::Int(..) => "Int",
457 TypeKind::Float(..) => "Float",
458 TypeKind::Complex(..) => "Complex",
459 TypeKind::Alias(..) => "Alias",
460 TypeKind::TemplateAlias(..) => "TemplateAlias",
461 TypeKind::Array(..) => "Array",
462 TypeKind::Vector(..) => "Vector",
463 TypeKind::Function(..) => "Function",
464 TypeKind::Enum(..) => "Enum",
465 TypeKind::Pointer(..) => "Pointer",
466 TypeKind::BlockPointer(..) => "BlockPointer",
467 TypeKind::Reference(..) => "Reference",
468 TypeKind::TemplateInstantiation(..) => "TemplateInstantiation",
469 TypeKind::UnresolvedTypeRef(..) => "UnresolvedTypeRef",
470 TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef",
471 TypeKind::TypeParam => "TypeParam",
472 TypeKind::ObjCInterface(..) => "ObjCInterface",
473 TypeKind::ObjCId => "ObjCId",
474 TypeKind::ObjCSel => "ObjCSel",
475 }
476 }
477 }
478
479 #[test]
is_invalid_type_param_valid()480 fn is_invalid_type_param_valid() {
481 let ty = Type::new(Some("foo".into()), None, TypeKind::TypeParam, false);
482 assert!(!ty.is_invalid_type_param())
483 }
484
485 #[test]
is_invalid_type_param_valid_underscore_and_numbers()486 fn is_invalid_type_param_valid_underscore_and_numbers() {
487 let ty = Type::new(
488 Some("_foo123456789_".into()),
489 None,
490 TypeKind::TypeParam,
491 false,
492 );
493 assert!(!ty.is_invalid_type_param())
494 }
495
496 #[test]
is_invalid_type_param_valid_unnamed_kind()497 fn is_invalid_type_param_valid_unnamed_kind() {
498 let ty = Type::new(Some("foo".into()), None, TypeKind::Void, false);
499 assert!(!ty.is_invalid_type_param())
500 }
501
502 #[test]
is_invalid_type_param_invalid_start()503 fn is_invalid_type_param_invalid_start() {
504 let ty = Type::new(Some("1foo".into()), None, TypeKind::TypeParam, false);
505 assert!(ty.is_invalid_type_param())
506 }
507
508 #[test]
is_invalid_type_param_invalid_remaing()509 fn is_invalid_type_param_invalid_remaing() {
510 let ty = Type::new(Some("foo-".into()), None, TypeKind::TypeParam, false);
511 assert!(ty.is_invalid_type_param())
512 }
513
514 #[test]
515 #[should_panic]
is_invalid_type_param_unnamed()516 fn is_invalid_type_param_unnamed() {
517 let ty = Type::new(None, None, TypeKind::TypeParam, false);
518 assert!(ty.is_invalid_type_param())
519 }
520
521 #[test]
is_invalid_type_param_empty_name()522 fn is_invalid_type_param_empty_name() {
523 let ty = Type::new(Some("".into()), None, TypeKind::TypeParam, false);
524 assert!(ty.is_invalid_type_param())
525 }
526
527 impl TemplateParameters for Type {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>528 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
529 self.kind.self_template_params(ctx)
530 }
531 }
532
533 impl TemplateParameters for TypeKind {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>534 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
535 match *self {
536 TypeKind::ResolvedTypeRef(id) => {
537 ctx.resolve_type(id).self_template_params(ctx)
538 }
539 TypeKind::Comp(ref comp) => comp.self_template_params(ctx),
540 TypeKind::TemplateAlias(_, ref args) => args.clone(),
541
542 TypeKind::Opaque |
543 TypeKind::TemplateInstantiation(..) |
544 TypeKind::Void |
545 TypeKind::NullPtr |
546 TypeKind::Int(_) |
547 TypeKind::Float(_) |
548 TypeKind::Complex(_) |
549 TypeKind::Array(..) |
550 TypeKind::Vector(..) |
551 TypeKind::Function(_) |
552 TypeKind::Enum(_) |
553 TypeKind::Pointer(_) |
554 TypeKind::BlockPointer(_) |
555 TypeKind::Reference(_) |
556 TypeKind::UnresolvedTypeRef(..) |
557 TypeKind::TypeParam |
558 TypeKind::Alias(_) |
559 TypeKind::ObjCId |
560 TypeKind::ObjCSel |
561 TypeKind::ObjCInterface(_) => vec![],
562 }
563 }
564 }
565
566 /// The kind of float this type represents.
567 #[derive(Debug, Copy, Clone, PartialEq)]
568 pub enum FloatKind {
569 /// A `float`.
570 Float,
571 /// A `double`.
572 Double,
573 /// A `long double`.
574 LongDouble,
575 /// A `__float128`.
576 Float128,
577 }
578
579 /// The different kinds of types that we can parse.
580 #[derive(Debug)]
581 pub enum TypeKind {
582 /// The void type.
583 Void,
584
585 /// The `nullptr_t` type.
586 NullPtr,
587
588 /// A compound type, that is, a class, struct, or union.
589 Comp(CompInfo),
590
591 /// An opaque type that we just don't understand. All usage of this shoulf
592 /// result in an opaque blob of bytes generated from the containing type's
593 /// layout.
594 Opaque,
595
596 /// An integer type, of a given kind. `bool` and `char` are also considered
597 /// integers.
598 Int(IntKind),
599
600 /// A floating point type.
601 Float(FloatKind),
602
603 /// A complex floating point type.
604 Complex(FloatKind),
605
606 /// A type alias, with a name, that points to another type.
607 Alias(TypeId),
608
609 /// A templated alias, pointing to an inner type, just as `Alias`, but with
610 /// template parameters.
611 TemplateAlias(TypeId, Vec<TypeId>),
612
613 /// A packed vector type: element type, number of elements
614 Vector(TypeId, usize),
615
616 /// An array of a type and a length.
617 Array(TypeId, usize),
618
619 /// A function type, with a given signature.
620 Function(FunctionSig),
621
622 /// An `enum` type.
623 Enum(Enum),
624
625 /// A pointer to a type. The bool field represents whether it's const or
626 /// not.
627 Pointer(TypeId),
628
629 /// A pointer to an Apple block.
630 BlockPointer(TypeId),
631
632 /// A reference to a type, as in: int& foo().
633 Reference(TypeId),
634
635 /// An instantiation of an abstract template definition with a set of
636 /// concrete template arguments.
637 TemplateInstantiation(TemplateInstantiation),
638
639 /// A reference to a yet-to-resolve type. This stores the clang cursor
640 /// itself, and postpones its resolution.
641 ///
642 /// These are gone in a phase after parsing where these are mapped to
643 /// already known types, and are converted to ResolvedTypeRef.
644 ///
645 /// see tests/headers/typeref.hpp to see somewhere where this is a problem.
646 UnresolvedTypeRef(
647 clang::Type,
648 clang::Cursor,
649 /* parent_id */
650 Option<ItemId>,
651 ),
652
653 /// An indirection to another type.
654 ///
655 /// These are generated after we resolve a forward declaration, or when we
656 /// replace one type with another.
657 ResolvedTypeRef(TypeId),
658
659 /// A named type, that is, a template parameter.
660 TypeParam,
661
662 /// Objective C interface. Always referenced through a pointer
663 ObjCInterface(ObjCInterface),
664
665 /// Objective C 'id' type, points to any object
666 ObjCId,
667
668 /// Objective C selector type
669 ObjCSel,
670 }
671
672 impl Type {
673 /// This is another of the nasty methods. This one is the one that takes
674 /// care of the core logic of converting a clang type to a `Type`.
675 ///
676 /// It's sort of nasty and full of special-casing, but hopefully the
677 /// comments in every special case justify why they're there.
from_clang_ty( potential_id: ItemId, ty: &clang::Type, location: Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<ParseResult<Self>, ParseError>678 pub fn from_clang_ty(
679 potential_id: ItemId,
680 ty: &clang::Type,
681 location: Cursor,
682 parent_id: Option<ItemId>,
683 ctx: &mut BindgenContext,
684 ) -> Result<ParseResult<Self>, ParseError> {
685 use clang_sys::*;
686 {
687 let already_resolved = ctx.builtin_or_resolved_ty(
688 potential_id,
689 parent_id,
690 ty,
691 Some(location),
692 );
693 if let Some(ty) = already_resolved {
694 debug!("{:?} already resolved: {:?}", ty, location);
695 return Ok(ParseResult::AlreadyResolved(ty.into()));
696 }
697 }
698
699 let layout = ty.fallible_layout(ctx).ok();
700 let cursor = ty.declaration();
701 let mut name = cursor.spelling();
702
703 debug!(
704 "from_clang_ty: {:?}, ty: {:?}, loc: {:?}",
705 potential_id, ty, location
706 );
707 debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types());
708
709 let canonical_ty = ty.canonical_type();
710
711 // Parse objc protocols as if they were interfaces
712 let mut ty_kind = ty.kind();
713 match location.kind() {
714 CXCursor_ObjCProtocolDecl | CXCursor_ObjCCategoryDecl => {
715 ty_kind = CXType_ObjCInterface
716 }
717 _ => {}
718 }
719
720 // Objective C template type parameter
721 // FIXME: This is probably wrong, we are attempting to find the
722 // objc template params, which seem to manifest as a typedef.
723 // We are rewriting them as id to suppress multiple conflicting
724 // typedefs at root level
725 if ty_kind == CXType_Typedef {
726 let is_template_type_param =
727 ty.declaration().kind() == CXCursor_TemplateTypeParameter;
728 let is_canonical_objcpointer =
729 canonical_ty.kind() == CXType_ObjCObjectPointer;
730
731 // We have found a template type for objc interface
732 if is_canonical_objcpointer && is_template_type_param {
733 // Objective-C generics are just ids with fancy name.
734 // To keep it simple, just name them ids
735 name = "id".to_owned();
736 }
737 }
738
739 if location.kind() == CXCursor_ClassTemplatePartialSpecialization {
740 // Sorry! (Not sorry)
741 warn!(
742 "Found a partial template specialization; bindgen does not \
743 support partial template specialization! Constructing \
744 opaque type instead."
745 );
746 return Ok(ParseResult::New(
747 Opaque::from_clang_ty(&canonical_ty, ctx),
748 None,
749 ));
750 }
751
752 let kind = if location.kind() == CXCursor_TemplateRef ||
753 (ty.template_args().is_some() && ty_kind != CXType_Typedef)
754 {
755 // This is a template instantiation.
756 match TemplateInstantiation::from_ty(ty, ctx) {
757 Some(inst) => TypeKind::TemplateInstantiation(inst),
758 None => TypeKind::Opaque,
759 }
760 } else {
761 match ty_kind {
762 CXType_Unexposed
763 if *ty != canonical_ty &&
764 canonical_ty.kind() != CXType_Invalid &&
765 ty.ret_type().is_none() &&
766 // Sometime clang desugars some types more than
767 // what we need, specially with function
768 // pointers.
769 //
770 // We should also try the solution of inverting
771 // those checks instead of doing this, that is,
772 // something like:
773 //
774 // CXType_Unexposed if ty.ret_type().is_some()
775 // => { ... }
776 //
777 // etc.
778 !canonical_ty.spelling().contains("type-parameter") =>
779 {
780 debug!("Looking for canonical type: {:?}", canonical_ty);
781 return Self::from_clang_ty(
782 potential_id,
783 &canonical_ty,
784 location,
785 parent_id,
786 ctx,
787 );
788 }
789 CXType_Unexposed | CXType_Invalid => {
790 // For some reason Clang doesn't give us any hint in some
791 // situations where we should generate a function pointer (see
792 // tests/headers/func_ptr_in_struct.h), so we do a guess here
793 // trying to see if it has a valid return type.
794 if ty.ret_type().is_some() {
795 let signature =
796 FunctionSig::from_ty(ty, &location, ctx)?;
797 TypeKind::Function(signature)
798 // Same here, with template specialisations we can safely
799 // assume this is a Comp(..)
800 } else if ty.is_fully_instantiated_template() {
801 debug!(
802 "Template specialization: {:?}, {:?} {:?}",
803 ty, location, canonical_ty
804 );
805 let complex = CompInfo::from_ty(
806 potential_id,
807 ty,
808 Some(location),
809 ctx,
810 )
811 .expect("C'mon");
812 TypeKind::Comp(complex)
813 } else {
814 match location.kind() {
815 CXCursor_CXXBaseSpecifier |
816 CXCursor_ClassTemplate => {
817 if location.kind() == CXCursor_CXXBaseSpecifier
818 {
819 // In the case we're parsing a base specifier
820 // inside an unexposed or invalid type, it means
821 // that we're parsing one of two things:
822 //
823 // * A template parameter.
824 // * A complex class that isn't exposed.
825 //
826 // This means, unfortunately, that there's no
827 // good way to differentiate between them.
828 //
829 // Probably we could try to look at the
830 // declaration and complicate more this logic,
831 // but we'll keep it simple... if it's a valid
832 // C++ identifier, we'll consider it as a
833 // template parameter.
834 //
835 // This is because:
836 //
837 // * We expect every other base that is a
838 // proper identifier (that is, a simple
839 // struct/union declaration), to be exposed,
840 // so this path can't be reached in that
841 // case.
842 //
843 // * Quite conveniently, complex base
844 // specifiers preserve their full names (that
845 // is: Foo<T> instead of Foo). We can take
846 // advantage of this.
847 //
848 // If we find some edge case where this doesn't
849 // work (which I guess is unlikely, see the
850 // different test cases[1][2][3][4]), we'd need
851 // to find more creative ways of differentiating
852 // these two cases.
853 //
854 // [1]: inherit_named.hpp
855 // [2]: forward-inherit-struct-with-fields.hpp
856 // [3]: forward-inherit-struct.hpp
857 // [4]: inherit-namespaced.hpp
858 if location.spelling().chars().all(|c| {
859 c.is_alphanumeric() || c == '_'
860 }) {
861 return Err(ParseError::Recurse);
862 }
863 } else {
864 name = location.spelling();
865 }
866
867 let complex = CompInfo::from_ty(
868 potential_id,
869 ty,
870 Some(location),
871 ctx,
872 );
873 match complex {
874 Ok(complex) => TypeKind::Comp(complex),
875 Err(_) => {
876 warn!(
877 "Could not create complex type \
878 from class template or base \
879 specifier, using opaque blob"
880 );
881 let opaque =
882 Opaque::from_clang_ty(ty, ctx);
883 return Ok(ParseResult::New(
884 opaque, None,
885 ));
886 }
887 }
888 }
889 CXCursor_TypeAliasTemplateDecl => {
890 debug!("TypeAliasTemplateDecl");
891
892 // We need to manually unwind this one.
893 let mut inner = Err(ParseError::Continue);
894 let mut args = vec![];
895
896 location.visit(|cur| {
897 match cur.kind() {
898 CXCursor_TypeAliasDecl => {
899 let current = cur.cur_type();
900
901 debug_assert_eq!(
902 current.kind(),
903 CXType_Typedef
904 );
905
906 name = current.spelling();
907
908 let inner_ty = cur
909 .typedef_type()
910 .expect("Not valid Type?");
911 inner = Ok(Item::from_ty_or_ref(
912 inner_ty,
913 cur,
914 Some(potential_id),
915 ctx,
916 ));
917 }
918 CXCursor_TemplateTypeParameter => {
919 let param = Item::type_param(
920 None, cur, ctx,
921 )
922 .expect(
923 "Item::type_param shouldn't \
924 ever fail if we are looking \
925 at a TemplateTypeParameter",
926 );
927 args.push(param);
928 }
929 _ => {}
930 }
931 CXChildVisit_Continue
932 });
933
934 let inner_type = match inner {
935 Ok(inner) => inner,
936 Err(..) => {
937 warn!(
938 "Failed to parse template alias \
939 {:?}",
940 location
941 );
942 return Err(ParseError::Continue);
943 }
944 };
945
946 TypeKind::TemplateAlias(inner_type, args)
947 }
948 CXCursor_TemplateRef => {
949 let referenced = location.referenced().unwrap();
950 let referenced_ty = referenced.cur_type();
951
952 debug!(
953 "TemplateRef: location = {:?}; referenced = \
954 {:?}; referenced_ty = {:?}",
955 location,
956 referenced,
957 referenced_ty
958 );
959
960 return Self::from_clang_ty(
961 potential_id,
962 &referenced_ty,
963 referenced,
964 parent_id,
965 ctx,
966 );
967 }
968 CXCursor_TypeRef => {
969 let referenced = location.referenced().unwrap();
970 let referenced_ty = referenced.cur_type();
971 let declaration = referenced_ty.declaration();
972
973 debug!(
974 "TypeRef: location = {:?}; referenced = \
975 {:?}; referenced_ty = {:?}",
976 location, referenced, referenced_ty
977 );
978
979 let id = Item::from_ty_or_ref_with_id(
980 potential_id,
981 referenced_ty,
982 declaration,
983 parent_id,
984 ctx,
985 );
986 return Ok(ParseResult::AlreadyResolved(
987 id.into(),
988 ));
989 }
990 CXCursor_NamespaceRef => {
991 return Err(ParseError::Continue);
992 }
993 _ => {
994 if ty.kind() == CXType_Unexposed {
995 warn!(
996 "Unexposed type {:?}, recursing inside, \
997 loc: {:?}",
998 ty,
999 location
1000 );
1001 return Err(ParseError::Recurse);
1002 }
1003
1004 warn!("invalid type {:?}", ty);
1005 return Err(ParseError::Continue);
1006 }
1007 }
1008 }
1009 }
1010 CXType_Auto => {
1011 if canonical_ty == *ty {
1012 debug!("Couldn't find deduced type: {:?}", ty);
1013 return Err(ParseError::Continue);
1014 }
1015
1016 return Self::from_clang_ty(
1017 potential_id,
1018 &canonical_ty,
1019 location,
1020 parent_id,
1021 ctx,
1022 );
1023 }
1024 // NOTE: We don't resolve pointers eagerly because the pointee type
1025 // might not have been parsed, and if it contains templates or
1026 // something else we might get confused, see the comment inside
1027 // TypeRef.
1028 //
1029 // We might need to, though, if the context is already in the
1030 // process of resolving them.
1031 CXType_ObjCObjectPointer |
1032 CXType_MemberPointer |
1033 CXType_Pointer => {
1034 let pointee = ty.pointee_type().unwrap();
1035 let inner =
1036 Item::from_ty_or_ref(pointee, location, None, ctx);
1037 TypeKind::Pointer(inner)
1038 }
1039 CXType_BlockPointer => {
1040 let pointee = ty.pointee_type().expect("Not valid Type?");
1041 let inner =
1042 Item::from_ty_or_ref(pointee, location, None, ctx);
1043 TypeKind::BlockPointer(inner)
1044 }
1045 // XXX: RValueReference is most likely wrong, but I don't think we
1046 // can even add bindings for that, so huh.
1047 CXType_RValueReference | CXType_LValueReference => {
1048 let inner = Item::from_ty_or_ref(
1049 ty.pointee_type().unwrap(),
1050 location,
1051 None,
1052 ctx,
1053 );
1054 TypeKind::Reference(inner)
1055 }
1056 // XXX DependentSizedArray is wrong
1057 CXType_VariableArray | CXType_DependentSizedArray => {
1058 let inner = Item::from_ty(
1059 ty.elem_type().as_ref().unwrap(),
1060 location,
1061 None,
1062 ctx,
1063 )
1064 .expect("Not able to resolve array element?");
1065 TypeKind::Pointer(inner)
1066 }
1067 CXType_IncompleteArray => {
1068 let inner = Item::from_ty(
1069 ty.elem_type().as_ref().unwrap(),
1070 location,
1071 None,
1072 ctx,
1073 )
1074 .expect("Not able to resolve array element?");
1075 TypeKind::Array(inner, 0)
1076 }
1077 CXType_FunctionNoProto | CXType_FunctionProto => {
1078 let signature = FunctionSig::from_ty(ty, &location, ctx)?;
1079 TypeKind::Function(signature)
1080 }
1081 CXType_Typedef => {
1082 let inner = cursor.typedef_type().expect("Not valid Type?");
1083 let inner =
1084 Item::from_ty_or_ref(inner, location, None, ctx);
1085 if inner == potential_id {
1086 warn!(
1087 "Generating oqaque type instead of self-referential \
1088 typedef");
1089 // This can happen if we bail out of recursive situations
1090 // within the clang parsing.
1091 TypeKind::Opaque
1092 } else {
1093 TypeKind::Alias(inner)
1094 }
1095 }
1096 CXType_Enum => {
1097 let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
1098
1099 if name.is_empty() {
1100 let pretty_name = ty.spelling();
1101 if clang::is_valid_identifier(&pretty_name) {
1102 name = pretty_name;
1103 }
1104 }
1105
1106 TypeKind::Enum(enum_)
1107 }
1108 CXType_Record => {
1109 let complex = CompInfo::from_ty(
1110 potential_id,
1111 ty,
1112 Some(location),
1113 ctx,
1114 )
1115 .expect("Not a complex type?");
1116
1117 if name.is_empty() {
1118 // The pretty-printed name may contain typedefed name,
1119 // but may also be "struct (anonymous at .h:1)"
1120 let pretty_name = ty.spelling();
1121 if clang::is_valid_identifier(&pretty_name) {
1122 name = pretty_name;
1123 }
1124 }
1125
1126 TypeKind::Comp(complex)
1127 }
1128 CXType_Vector => {
1129 let inner = Item::from_ty(
1130 ty.elem_type().as_ref().unwrap(),
1131 location,
1132 None,
1133 ctx,
1134 )
1135 .expect("Not able to resolve vector element?");
1136 TypeKind::Vector(inner, ty.num_elements().unwrap())
1137 }
1138 CXType_ConstantArray => {
1139 let inner = Item::from_ty(
1140 ty.elem_type().as_ref().unwrap(),
1141 location,
1142 None,
1143 ctx,
1144 )
1145 .expect("Not able to resolve array element?");
1146 TypeKind::Array(inner, ty.num_elements().unwrap())
1147 }
1148 CXType_Elaborated => {
1149 return Self::from_clang_ty(
1150 potential_id,
1151 &ty.named(),
1152 location,
1153 parent_id,
1154 ctx,
1155 );
1156 }
1157 CXType_ObjCId => TypeKind::ObjCId,
1158 CXType_ObjCSel => TypeKind::ObjCSel,
1159 CXType_ObjCClass | CXType_ObjCInterface => {
1160 let interface = ObjCInterface::from_ty(&location, ctx)
1161 .expect("Not a valid objc interface?");
1162 name = interface.rust_name();
1163 TypeKind::ObjCInterface(interface)
1164 }
1165 CXType_Dependent => {
1166 return Err(ParseError::Continue);
1167 }
1168 _ => {
1169 warn!(
1170 "unsupported type: kind = {:?}; ty = {:?}; at {:?}",
1171 ty.kind(),
1172 ty,
1173 location
1174 );
1175 return Err(ParseError::Continue);
1176 }
1177 }
1178 };
1179
1180 let name = if name.is_empty() { None } else { Some(name) };
1181
1182 let is_const = ty.is_const() ||
1183 (ty.kind() == CXType_ConstantArray &&
1184 ty.elem_type()
1185 .map_or(false, |element| element.is_const()));
1186
1187 let ty = Type::new(name, layout, kind, is_const);
1188 // TODO: maybe declaration.canonical()?
1189 Ok(ParseResult::New(ty, Some(cursor.canonical())))
1190 }
1191 }
1192
1193 impl Trace for Type {
1194 type Extra = Item;
1195
trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item) where T: Tracer,1196 fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
1197 where
1198 T: Tracer,
1199 {
1200 match *self.kind() {
1201 TypeKind::Pointer(inner) |
1202 TypeKind::Reference(inner) |
1203 TypeKind::Array(inner, _) |
1204 TypeKind::Vector(inner, _) |
1205 TypeKind::BlockPointer(inner) |
1206 TypeKind::Alias(inner) |
1207 TypeKind::ResolvedTypeRef(inner) => {
1208 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1209 }
1210 TypeKind::TemplateAlias(inner, ref template_params) => {
1211 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1212 for param in template_params {
1213 tracer.visit_kind(
1214 param.into(),
1215 EdgeKind::TemplateParameterDefinition,
1216 );
1217 }
1218 }
1219 TypeKind::TemplateInstantiation(ref inst) => {
1220 inst.trace(context, tracer, &());
1221 }
1222 TypeKind::Comp(ref ci) => ci.trace(context, tracer, item),
1223 TypeKind::Function(ref sig) => sig.trace(context, tracer, &()),
1224 TypeKind::Enum(ref en) => {
1225 if let Some(repr) = en.repr() {
1226 tracer.visit(repr.into());
1227 }
1228 }
1229 TypeKind::UnresolvedTypeRef(_, _, Some(id)) => {
1230 tracer.visit(id);
1231 }
1232
1233 TypeKind::ObjCInterface(ref interface) => {
1234 interface.trace(context, tracer, &());
1235 }
1236
1237 // None of these variants have edges to other items and types.
1238 TypeKind::Opaque |
1239 TypeKind::UnresolvedTypeRef(_, _, None) |
1240 TypeKind::TypeParam |
1241 TypeKind::Void |
1242 TypeKind::NullPtr |
1243 TypeKind::Int(_) |
1244 TypeKind::Float(_) |
1245 TypeKind::Complex(_) |
1246 TypeKind::ObjCId |
1247 TypeKind::ObjCSel => {}
1248 }
1249 }
1250 }
1251