1use super::comp::CompInfo;
4use super::context::{BindgenContext, ItemId, TypeId};
5use super::dot::DotAttributes;
6use super::enum_ty::Enum;
7use super::function::FunctionSig;
8use super::item::{IsOpaque, Item};
9use super::layout::{Layout, Opaque};
10use super::objc::ObjCInterface;
11use super::template::{
12 AsTemplateParam, TemplateInstantiation, TemplateParameters,
13};
14use super::traversal::{EdgeKind, Trace, Tracer};
15use crate::clang::{self, Cursor};
16use crate::parse::{ParseError, ParseResult};
17use std::borrow::Cow;
18use std::io;
19
20pub use super::int::IntKind;
21
22#[derive(Debug)]
28pub(crate) struct Type {
29 name: Option<String>,
31 layout: Option<Layout>,
33 kind: TypeKind,
35 is_const: bool,
37}
38
39pub(crate) const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
44
45impl Type {
46 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 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 pub(crate) fn kind(&self) -> &TypeKind {
72 &self.kind
73 }
74
75 pub(crate) fn kind_mut(&mut self) -> &mut TypeKind {
77 &mut self.kind
78 }
79
80 pub(crate) fn name(&self) -> Option<&str> {
82 self.name.as_deref()
83 }
84
85 pub(crate) fn is_block_pointer(&self) -> bool {
87 matches!(self.kind, TypeKind::BlockPointer(..))
88 }
89
90 pub(crate) fn is_int(&self) -> bool {
92 matches!(self.kind, TypeKind::Int(_))
93 }
94
95 pub(crate) fn is_comp(&self) -> bool {
97 matches!(self.kind, TypeKind::Comp(..))
98 }
99
100 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 pub(crate) fn is_type_param(&self) -> bool {
110 matches!(self.kind, TypeKind::TypeParam)
111 }
112
113 pub(crate) fn is_template_instantiation(&self) -> bool {
115 matches!(self.kind, TypeKind::TemplateInstantiation(..))
116 }
117
118 pub(crate) fn is_function(&self) -> bool {
120 matches!(self.kind, TypeKind::Function(..))
121 }
122
123 pub(crate) fn is_enum(&self) -> bool {
125 matches!(self.kind, TypeKind::Enum(..))
126 }
127
128 pub(crate) fn is_void(&self) -> bool {
130 matches!(self.kind, TypeKind::Void)
131 }
132 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 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 pub(crate) fn is_float(&self) -> bool {
156 matches!(self.kind, TypeKind::Float(..))
157 }
158
159 pub(crate) fn is_bool(&self) -> bool {
161 matches!(self.kind, TypeKind::Int(IntKind::Bool))
162 }
163
164 pub(crate) fn is_integer(&self) -> bool {
166 matches!(self.kind, TypeKind::Int(..))
167 }
168
169 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 pub(crate) fn is_const(&self) -> bool {
180 self.is_const
181 }
182
183 pub(crate) fn is_unresolved_ref(&self) -> bool {
185 matches!(self.kind, TypeKind::UnresolvedTypeRef(_, _, _))
186 }
187
188 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 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 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 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 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([' ', ':', '.'], "_");
252 Cow::Owned(name)
253 }
254
255 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 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 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 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
345impl IsOpaque for Type {
346 type Extra = Item;
347
348 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
361impl AsTemplateParam for Type {
362 type Extra = Item;
363
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
373impl AsTemplateParam for TypeKind {
374 type Extra = Item;
375
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
389impl DotAttributes for Type {
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
418impl DotAttributes for TypeKind {
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
441impl TypeKind {
442 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]
472fn 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]
478fn 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]
489fn 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]
495fn 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]
501fn is_invalid_type_param_invalid_remaining() {
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]
508fn 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]
514fn 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
519impl TemplateParameters for Type {
520 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
521 self.kind.self_template_params(ctx)
522 }
523}
524
525impl TemplateParameters for TypeKind {
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#[derive(Debug, Copy, Clone, PartialEq, Eq)]
560pub(crate) enum FloatKind {
561 Float16,
563 Float,
565 Double,
567 LongDouble,
569 Float128,
571}
572
573#[derive(Debug)]
575pub(crate) enum TypeKind {
576 Void,
578
579 NullPtr,
581
582 Comp(CompInfo),
584
585 Opaque,
589
590 Int(IntKind),
593
594 Float(FloatKind),
596
597 Complex(FloatKind),
599
600 Alias(TypeId),
602
603 TemplateAlias(TypeId, Vec<TypeId>),
606
607 Vector(TypeId, usize),
609
610 Array(TypeId, usize),
612
613 Function(FunctionSig),
615
616 Enum(Enum),
618
619 Pointer(TypeId),
622
623 BlockPointer(TypeId),
625
626 Reference(TypeId),
628
629 TemplateInstantiation(TemplateInstantiation),
632
633 UnresolvedTypeRef(clang::Type, Cursor, Option<ItemId>),
641
642 ResolvedTypeRef(TypeId),
647
648 TypeParam,
650
651 ObjCInterface(ObjCInterface),
653
654 ObjCId,
656
657 ObjCSel,
659}
660
661impl Type {
662 pub(crate) fn from_clang_ty(
668 potential_id: ItemId,
669 ty: &clang::Type,
670 location: Cursor,
671 parent_id: Option<ItemId>,
672 ctx: &mut BindgenContext,
673 ) -> Result<ParseResult<Self>, ParseError> {
674 use clang_sys::*;
675 {
676 let already_resolved = ctx.builtin_or_resolved_ty(
677 potential_id,
678 parent_id,
679 ty,
680 Some(location),
681 );
682 if let Some(ty) = already_resolved {
683 debug!("{ty:?} already resolved: {location:?}");
684 return Ok(ParseResult::AlreadyResolved(ty.into()));
685 }
686 }
687
688 let layout = ty.fallible_layout(ctx).ok();
689 let cursor = ty.declaration();
690 let is_anonymous = cursor.is_anonymous();
691 let mut name = if is_anonymous {
692 None
693 } else {
694 Some(cursor.spelling()).filter(|n| !n.is_empty())
695 };
696
697 debug!(
698 "from_clang_ty: {potential_id:?}, ty: {ty:?}, loc: {location:?}"
699 );
700 debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types());
701
702 let canonical_ty = ty.canonical_type();
703
704 let mut ty_kind = ty.kind();
706 match location.kind() {
707 CXCursor_ObjCProtocolDecl | CXCursor_ObjCCategoryDecl => {
708 ty_kind = CXType_ObjCInterface;
709 }
710 _ => {}
711 }
712
713 if ty_kind == CXType_Typedef {
719 let is_template_type_param =
720 ty.declaration().kind() == CXCursor_TemplateTypeParameter;
721 let is_canonical_objcpointer =
722 canonical_ty.kind() == CXType_ObjCObjectPointer;
723
724 if is_canonical_objcpointer && is_template_type_param {
726 name = Some("id".to_owned());
729 }
730 }
731
732 if location.kind() == CXCursor_ClassTemplatePartialSpecialization {
733 warn!(
735 "Found a partial template specialization; bindgen does not \
736 support partial template specialization! Constructing \
737 opaque type instead."
738 );
739 return Ok(ParseResult::New(
740 Opaque::from_clang_ty(&canonical_ty, ctx),
741 None,
742 ));
743 }
744
745 let kind = if location.kind() == CXCursor_TemplateRef ||
746 (ty.template_args().is_some() && ty_kind != CXType_Typedef)
747 {
748 match TemplateInstantiation::from_ty(ty, ctx) {
750 Some(inst) => TypeKind::TemplateInstantiation(inst),
751 None => TypeKind::Opaque,
752 }
753 } else {
754 match ty_kind {
755 CXType_Unexposed
756 if *ty != canonical_ty &&
757 canonical_ty.kind() != CXType_Invalid &&
758 ty.ret_type().is_none() &&
759 !canonical_ty.spelling().contains("type-parameter") =>
772 {
773 debug!("Looking for canonical type: {canonical_ty:?}");
774 return Self::from_clang_ty(
775 potential_id,
776 &canonical_ty,
777 location,
778 parent_id,
779 ctx,
780 );
781 }
782 CXType_Unexposed | CXType_Invalid => {
783 if ty.ret_type().is_some() {
788 let signature =
789 FunctionSig::from_ty(ty, &location, ctx)?;
790 TypeKind::Function(signature)
791 } else if ty.is_fully_instantiated_template() {
794 debug!("Template specialization: {ty:?}, {location:?} {canonical_ty:?}");
795 let complex = CompInfo::from_ty(
796 potential_id,
797 ty,
798 Some(location),
799 ctx,
800 )
801 .expect("C'mon");
802 TypeKind::Comp(complex)
803 } else {
804 match location.kind() {
805 CXCursor_CXXBaseSpecifier |
806 CXCursor_ClassTemplate => {
807 if location.kind() == CXCursor_CXXBaseSpecifier
808 {
809 if location.spelling().chars().all(|c| {
849 c.is_alphanumeric() || c == '_'
850 }) {
851 return Err(ParseError::Recurse);
852 }
853 } else {
854 name = Some(location.spelling());
855 }
856
857 let complex = CompInfo::from_ty(
858 potential_id,
859 ty,
860 Some(location),
861 ctx,
862 );
863 if let Ok(complex) = complex {
864 TypeKind::Comp(complex)
865 } else {
866 warn!(
867 "Could not create complex type \
868 from class template or base \
869 specifier, using opaque blob"
870 );
871 let opaque = Opaque::from_clang_ty(ty, ctx);
872 return Ok(ParseResult::New(opaque, None));
873 }
874 }
875 CXCursor_TypeAliasTemplateDecl => {
876 debug!("TypeAliasTemplateDecl");
877
878 let mut inner = Err(ParseError::Continue);
880 let mut args = vec![];
881
882 location.visit(|cur| {
883 match cur.kind() {
884 CXCursor_TypeAliasDecl => {
885 let current = cur.cur_type();
886
887 debug_assert_eq!(
888 current.kind(),
889 CXType_Typedef
890 );
891
892 name = Some(location.spelling());
893
894 let inner_ty = cur
895 .typedef_type()
896 .expect("Not valid Type?");
897 inner = Ok(Item::from_ty_or_ref(
898 inner_ty,
899 cur,
900 Some(potential_id),
901 ctx,
902 ));
903 }
904 CXCursor_TemplateTypeParameter => {
905 let param = Item::type_param(
906 None, cur, ctx,
907 )
908 .expect(
909 "Item::type_param shouldn't \
910 ever fail if we are looking \
911 at a TemplateTypeParameter",
912 );
913 args.push(param);
914 }
915 _ => {}
916 }
917 CXChildVisit_Continue
918 });
919
920 let Ok(inner_type) = inner else {
921 warn!(
922 "Failed to parse template alias \
923 {:?}",
924 location
925 );
926 return Err(ParseError::Continue);
927 };
928
929 TypeKind::TemplateAlias(inner_type, args)
930 }
931 CXCursor_TemplateRef => {
932 let referenced = location.referenced().unwrap();
933 let referenced_ty = referenced.cur_type();
934
935 debug!("TemplateRef: location = {location:?}; referenced = {referenced:?}; referenced_ty = {referenced_ty:?}");
936
937 return Self::from_clang_ty(
938 potential_id,
939 &referenced_ty,
940 referenced,
941 parent_id,
942 ctx,
943 );
944 }
945 CXCursor_TypeRef => {
946 let referenced = location.referenced().unwrap();
947 let referenced_ty = referenced.cur_type();
948 let declaration = referenced_ty.declaration();
949
950 debug!("TypeRef: location = {location:?}; referenced = {referenced:?}; referenced_ty = {referenced_ty:?}");
951
952 let id = Item::from_ty_or_ref_with_id(
953 potential_id,
954 referenced_ty,
955 declaration,
956 parent_id,
957 ctx,
958 );
959 return Ok(ParseResult::AlreadyResolved(
960 id.into(),
961 ));
962 }
963 CXCursor_NamespaceRef => {
964 return Err(ParseError::Continue);
965 }
966 _ => {
967 if ty.kind() == CXType_Unexposed {
968 warn!("Unexposed type {ty:?}, recursing inside, loc: {location:?}");
969 return Err(ParseError::Recurse);
970 }
971
972 warn!("invalid type {ty:?}");
973 return Err(ParseError::Continue);
974 }
975 }
976 }
977 }
978 CXType_Auto => {
979 if canonical_ty == *ty {
980 debug!("Couldn't find deduced type: {ty:?}");
981 return Err(ParseError::Continue);
982 }
983
984 return Self::from_clang_ty(
985 potential_id,
986 &canonical_ty,
987 location,
988 parent_id,
989 ctx,
990 );
991 }
992 CXType_ObjCObjectPointer |
1000 CXType_MemberPointer |
1001 CXType_Pointer => {
1002 let mut pointee = ty.pointee_type().unwrap();
1003 if *ty != canonical_ty {
1004 let canonical_pointee =
1005 canonical_ty.pointee_type().unwrap();
1006 if canonical_pointee.is_const() != pointee.is_const() {
1009 pointee = canonical_pointee;
1010 }
1011 }
1012 let inner =
1013 Item::from_ty_or_ref(pointee, location, None, ctx);
1014 TypeKind::Pointer(inner)
1015 }
1016 CXType_BlockPointer => {
1017 let pointee = ty.pointee_type().expect("Not valid Type?");
1018 let inner =
1019 Item::from_ty_or_ref(pointee, location, None, ctx);
1020 TypeKind::BlockPointer(inner)
1021 }
1022 CXType_RValueReference | CXType_LValueReference => {
1025 let inner = Item::from_ty_or_ref(
1026 ty.pointee_type().unwrap(),
1027 location,
1028 None,
1029 ctx,
1030 );
1031 TypeKind::Reference(inner)
1032 }
1033 CXType_VariableArray | CXType_DependentSizedArray => {
1035 let inner = Item::from_ty(
1036 ty.elem_type().as_ref().unwrap(),
1037 location,
1038 None,
1039 ctx,
1040 )
1041 .expect("Not able to resolve array element?");
1042 TypeKind::Pointer(inner)
1043 }
1044 CXType_IncompleteArray => {
1045 let inner = Item::from_ty(
1046 ty.elem_type().as_ref().unwrap(),
1047 location,
1048 None,
1049 ctx,
1050 )
1051 .expect("Not able to resolve array element?");
1052 TypeKind::Array(inner, 0)
1053 }
1054 CXType_FunctionNoProto | CXType_FunctionProto => {
1055 let signature = FunctionSig::from_ty(ty, &location, ctx)?;
1056 TypeKind::Function(signature)
1057 }
1058 CXType_Typedef => {
1059 let inner = cursor.typedef_type().expect("Not valid Type?");
1060 let inner_id =
1061 Item::from_ty_or_ref(inner, location, None, ctx);
1062 if inner_id == potential_id {
1063 warn!(
1064 "Generating opaque type instead of self-referential \
1065 typedef");
1066 TypeKind::Opaque
1069 } else {
1070 if let Some(ref mut name) = name {
1074 if inner.kind() == CXType_Pointer &&
1075 !ctx.options().c_naming
1076 {
1077 let pointee = inner.pointee_type().unwrap();
1078 if pointee.kind() == CXType_Elaborated &&
1079 pointee.declaration().spelling() == *name
1080 {
1081 *name += "_ptr";
1082 }
1083 }
1084 }
1085 TypeKind::Alias(inner_id)
1086 }
1087 }
1088 CXType_Enum => {
1089 let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
1090
1091 if !is_anonymous {
1092 let pretty_name = ty.spelling();
1093 if clang::is_valid_identifier(&pretty_name) {
1094 name = Some(pretty_name);
1095 }
1096 }
1097
1098 TypeKind::Enum(enum_)
1099 }
1100 CXType_Record => {
1101 let complex = CompInfo::from_ty(
1102 potential_id,
1103 ty,
1104 Some(location),
1105 ctx,
1106 )
1107 .expect("Not a complex type?");
1108
1109 if !is_anonymous {
1110 let pretty_name = ty.spelling();
1113 if clang::is_valid_identifier(&pretty_name) {
1114 name = Some(pretty_name);
1115 }
1116 }
1117
1118 TypeKind::Comp(complex)
1119 }
1120 CXType_Vector => {
1121 let inner = Item::from_ty(
1122 ty.elem_type().as_ref().unwrap(),
1123 location,
1124 None,
1125 ctx,
1126 )?;
1127 TypeKind::Vector(inner, ty.num_elements().unwrap())
1128 }
1129 CXType_ConstantArray => {
1130 let inner = Item::from_ty(
1131 ty.elem_type().as_ref().unwrap(),
1132 location,
1133 None,
1134 ctx,
1135 )
1136 .expect("Not able to resolve array element?");
1137 TypeKind::Array(inner, ty.num_elements().unwrap())
1138 }
1139 CXType_Atomic => {
1140 return Self::from_clang_ty(
1144 potential_id,
1145 &ty.atomic_value_type(),
1146 location,
1147 parent_id,
1148 ctx,
1149 );
1150 }
1151 CXType_Elaborated => {
1152 return Self::from_clang_ty(
1153 potential_id,
1154 &ty.named(),
1155 location,
1156 parent_id,
1157 ctx,
1158 );
1159 }
1160 CXType_ObjCId => TypeKind::ObjCId,
1161 CXType_ObjCSel => TypeKind::ObjCSel,
1162 CXType_ObjCClass | CXType_ObjCInterface => {
1163 let interface = ObjCInterface::from_ty(&location, ctx)
1164 .expect("Not a valid objc interface?");
1165 if !is_anonymous {
1166 name = Some(interface.rust_name());
1167 }
1168 TypeKind::ObjCInterface(interface)
1169 }
1170 CXType_Dependent => {
1171 return Err(ParseError::Continue);
1172 }
1173 _ => {
1174 warn!(
1175 "unsupported type: kind = {:?}; ty = {ty:?}; at {location:?}",
1176 ty.kind(),
1177 );
1178 return Err(ParseError::Continue);
1179 }
1180 }
1181 };
1182
1183 name = name.filter(|n| !n.is_empty());
1184
1185 let is_const = ty.is_const() ||
1186 (ty.kind() == CXType_ConstantArray &&
1187 ty.elem_type().is_some_and(|element| element.is_const()));
1188
1189 let ty = Type::new(name, layout, kind, is_const);
1190 Ok(ParseResult::New(ty, Some(cursor.canonical())))
1192 }
1193}
1194
1195impl Trace for Type {
1196 type Extra = Item;
1197
1198 fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
1199 where
1200 T: Tracer,
1201 {
1202 if self.name().is_some_and(|name| context.is_stdint_type(name)) {
1203 return;
1205 }
1206 match *self.kind() {
1207 TypeKind::Pointer(inner) |
1208 TypeKind::Reference(inner) |
1209 TypeKind::Array(inner, _) |
1210 TypeKind::Vector(inner, _) |
1211 TypeKind::BlockPointer(inner) |
1212 TypeKind::Alias(inner) |
1213 TypeKind::ResolvedTypeRef(inner) => {
1214 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1215 }
1216 TypeKind::TemplateAlias(inner, ref template_params) => {
1217 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1218 for param in template_params {
1219 tracer.visit_kind(
1220 param.into(),
1221 EdgeKind::TemplateParameterDefinition,
1222 );
1223 }
1224 }
1225 TypeKind::TemplateInstantiation(ref inst) => {
1226 inst.trace(context, tracer, &());
1227 }
1228 TypeKind::Comp(ref ci) => ci.trace(context, tracer, item),
1229 TypeKind::Function(ref sig) => sig.trace(context, tracer, &()),
1230 TypeKind::Enum(ref en) => {
1231 if let Some(repr) = en.repr() {
1232 tracer.visit(repr.into());
1233 }
1234 }
1235 TypeKind::UnresolvedTypeRef(_, _, Some(id)) => {
1236 tracer.visit(id);
1237 }
1238
1239 TypeKind::ObjCInterface(ref interface) => {
1240 interface.trace(context, tracer, &());
1241 }
1242
1243 TypeKind::Opaque |
1245 TypeKind::UnresolvedTypeRef(_, _, None) |
1246 TypeKind::TypeParam |
1247 TypeKind::Void |
1248 TypeKind::NullPtr |
1249 TypeKind::Int(_) |
1250 TypeKind::Float(_) |
1251 TypeKind::Complex(_) |
1252 TypeKind::ObjCId |
1253 TypeKind::ObjCSel => {}
1254 }
1255 }
1256}