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