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