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. |
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. |
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`. |
64 | 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? |
79 | pub fn kind(&self) -> &TypeKind { |
80 | &self.kind |
81 | } |
82 | |
83 | /// Get a mutable reference to this type's kind. |
84 | pub fn kind_mut(&mut self) -> &mut TypeKind { |
85 | &mut self.kind |
86 | } |
87 | |
88 | /// Get this type's name. |
89 | pub fn name(&self) -> Option<&str> { |
90 | self.name.as_deref() |
91 | } |
92 | |
93 | /// Whether this is a block pointer type. |
94 | 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`? |
99 | pub fn is_int(&self) -> bool { |
100 | matches!(self.kind, TypeKind::Int(_)) |
101 | } |
102 | |
103 | /// Is this a compound type? |
104 | pub fn is_comp(&self) -> bool { |
105 | matches!(self.kind, TypeKind::Comp(..)) |
106 | } |
107 | |
108 | /// Is this a union? |
109 | 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`? |
117 | pub fn is_type_param(&self) -> bool { |
118 | matches!(self.kind, TypeKind::TypeParam) |
119 | } |
120 | |
121 | /// Is this a template instantiation type? |
122 | pub fn is_template_instantiation(&self) -> bool { |
123 | matches!(self.kind, TypeKind::TemplateInstantiation(..)) |
124 | } |
125 | |
126 | /// Is this a template alias type? |
127 | pub fn is_template_alias(&self) -> bool { |
128 | matches!(self.kind, TypeKind::TemplateAlias(..)) |
129 | } |
130 | |
131 | /// Is this a function type? |
132 | pub fn is_function(&self) -> bool { |
133 | matches!(self.kind, TypeKind::Function(..)) |
134 | } |
135 | |
136 | /// Is this an enum type? |
137 | pub fn is_enum(&self) -> bool { |
138 | matches!(self.kind, TypeKind::Enum(..)) |
139 | } |
140 | |
141 | /// Is this either a builtin or named type? |
142 | 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`. |
158 | 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? |
164 | pub fn is_float(&self) -> bool { |
165 | matches!(self.kind, TypeKind::Float(..)) |
166 | } |
167 | |
168 | /// Is this a boolean type? |
169 | pub fn is_bool(&self) -> bool { |
170 | matches!(self.kind, TypeKind::Int(IntKind::Bool)) |
171 | } |
172 | |
173 | /// Is this an integer type? |
174 | 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. |
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? |
188 | pub fn is_const(&self) -> bool { |
189 | self.is_const |
190 | } |
191 | |
192 | /// Is this a reference to another type? |
193 | 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? |
201 | pub fn is_unresolved_ref(&self) -> bool { |
202 | matches!(self.kind, TypeKind::UnresolvedTypeRef(_, _, _)) |
203 | } |
204 | |
205 | /// Is this a incomplete array type? |
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? |
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 |
248 | 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. |
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. |
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. |
292 | 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. |
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. |
344 | 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 | |
361 | fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool { |
362 | match self.kind { |
363 | TypeKind::Opaque => true, |
364 | TypeKind::TemplateInstantiation(ref inst: &TemplateInstantiation) => { |
365 | inst.is_opaque(ctx, extra:item) |
366 | } |
367 | TypeKind::Comp(ref comp: &CompInfo) => comp.is_opaque(ctx, &self.layout), |
368 | TypeKind::ResolvedTypeRef(to: TypeId) => to.is_opaque(ctx, &()), |
369 | _ => false, |
370 | } |
371 | } |
372 | } |
373 | |
374 | impl AsTemplateParam for Type { |
375 | type Extra = Item; |
376 | |
377 | fn as_template_param( |
378 | &self, |
379 | ctx: &BindgenContext, |
380 | item: &Item, |
381 | ) -> Option<TypeId> { |
382 | self.kind.as_template_param(ctx, extra:item) |
383 | } |
384 | } |
385 | |
386 | impl AsTemplateParam for TypeKind { |
387 | type Extra = Item; |
388 | |
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: TypeId) => id.as_template_param(ctx, &()), |
397 | _ => None, |
398 | } |
399 | } |
400 | } |
401 | |
402 | impl DotAttributes for Type { |
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 { |
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: &CompInfo) = *self { |
447 | comp.dot_attributes(ctx, out)?; |
448 | } |
449 | |
450 | Ok(()) |
451 | } |
452 | } |
453 | |
454 | impl TypeKind { |
455 | 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 ] |
485 | fn is_invalid_type_param_valid() { |
486 | let ty: Type = Type::new(name:Some("foo" .into()), layout:None, kind:TypeKind::TypeParam, is_const:false); |
487 | assert!(!ty.is_invalid_type_param()) |
488 | } |
489 | |
490 | #[test ] |
491 | fn is_invalid_type_param_valid_underscore_and_numbers() { |
492 | let ty: Type = Type::new( |
493 | name:Some("_foo123456789_" .into()), |
494 | layout:None, |
495 | kind:TypeKind::TypeParam, |
496 | is_const:false, |
497 | ); |
498 | assert!(!ty.is_invalid_type_param()) |
499 | } |
500 | |
501 | #[test ] |
502 | fn is_invalid_type_param_valid_unnamed_kind() { |
503 | let ty: Type = Type::new(name:Some("foo" .into()), layout:None, kind:TypeKind::Void, is_const:false); |
504 | assert!(!ty.is_invalid_type_param()) |
505 | } |
506 | |
507 | #[test ] |
508 | fn is_invalid_type_param_invalid_start() { |
509 | let ty: Type = Type::new(name:Some("1foo" .into()), layout:None, kind:TypeKind::TypeParam, is_const:false); |
510 | assert!(ty.is_invalid_type_param()) |
511 | } |
512 | |
513 | #[test ] |
514 | fn is_invalid_type_param_invalid_remaing() { |
515 | let ty: Type = Type::new(name:Some("foo-" .into()), layout:None, kind:TypeKind::TypeParam, is_const:false); |
516 | assert!(ty.is_invalid_type_param()) |
517 | } |
518 | |
519 | #[test ] |
520 | #[should_panic ] |
521 | fn is_invalid_type_param_unnamed() { |
522 | let ty: Type = Type::new(name:None, layout:None, kind:TypeKind::TypeParam, is_const:false); |
523 | assert!(ty.is_invalid_type_param()) |
524 | } |
525 | |
526 | #[test ] |
527 | fn is_invalid_type_param_empty_name() { |
528 | let ty: Type = Type::new(name:Some("" .into()), layout:None, kind:TypeKind::TypeParam, is_const:false); |
529 | assert!(ty.is_invalid_type_param()) |
530 | } |
531 | |
532 | impl TemplateParameters for Type { |
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 { |
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. |
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 | |
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 | |