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::ir::function::Visibility;
17use crate::parse::{ParseError, ParseResult};
18use std::borrow::Cow;
19use std::io;
20
21pub use super::int::IntKind;
22
23#[derive(Debug)]
29pub(crate) struct Type {
30 name: Option<String>,
32 layout: Option<Layout>,
34 kind: TypeKind,
36 is_const: bool,
38}
39
40pub(crate) const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
45
46impl Type {
47 pub(crate) fn as_comp_mut(&mut self) -> Option<&mut CompInfo> {
50 match self.kind {
51 TypeKind::Comp(ref mut ci) => Some(ci),
52 _ => None,
53 }
54 }
55
56 pub(crate) fn new(
58 name: Option<String>,
59 layout: Option<Layout>,
60 kind: TypeKind,
61 is_const: bool,
62 ) -> Self {
63 Type {
64 name,
65 layout,
66 kind,
67 is_const,
68 }
69 }
70
71 pub(crate) fn kind(&self) -> &TypeKind {
73 &self.kind
74 }
75
76 pub(crate) fn kind_mut(&mut self) -> &mut TypeKind {
78 &mut self.kind
79 }
80
81 pub(crate) fn name(&self) -> Option<&str> {
83 self.name.as_deref()
84 }
85
86 pub(crate) fn is_block_pointer(&self) -> bool {
88 matches!(self.kind, TypeKind::BlockPointer(..))
89 }
90
91 pub(crate) fn is_int(&self) -> bool {
93 matches!(self.kind, TypeKind::Int(_))
94 }
95
96 pub(crate) fn is_comp(&self) -> bool {
98 matches!(self.kind, TypeKind::Comp(..))
99 }
100
101 pub(crate) fn is_union(&self) -> bool {
103 match self.kind {
104 TypeKind::Comp(ref comp) => comp.is_union(),
105 _ => false,
106 }
107 }
108
109 pub(crate) fn is_type_param(&self) -> bool {
111 matches!(self.kind, TypeKind::TypeParam)
112 }
113
114 pub(crate) fn is_template_instantiation(&self) -> bool {
116 matches!(self.kind, TypeKind::TemplateInstantiation(..))
117 }
118
119 pub(crate) fn is_function(&self) -> bool {
121 matches!(self.kind, TypeKind::Function(..))
122 }
123
124 pub(crate) fn is_enum(&self) -> bool {
126 matches!(self.kind, TypeKind::Enum(..))
127 }
128
129 pub(crate) fn is_void(&self) -> bool {
131 matches!(self.kind, TypeKind::Void)
132 }
133 pub(crate) fn is_builtin_or_type_param(&self) -> bool {
135 matches!(
136 self.kind,
137 TypeKind::Void |
138 TypeKind::NullPtr |
139 TypeKind::Function(..) |
140 TypeKind::Array(..) |
141 TypeKind::Reference(..) |
142 TypeKind::Pointer(..) |
143 TypeKind::Int(..) |
144 TypeKind::Float(..) |
145 TypeKind::TypeParam
146 )
147 }
148
149 pub(crate) fn named(name: String) -> Self {
151 let name = if name.is_empty() { None } else { Some(name) };
152 Self::new(name, None, TypeKind::TypeParam, false)
153 }
154
155 pub(crate) fn is_float(&self) -> bool {
157 matches!(self.kind, TypeKind::Float(..))
158 }
159
160 pub(crate) fn is_bool(&self) -> bool {
162 matches!(self.kind, TypeKind::Int(IntKind::Bool))
163 }
164
165 pub(crate) fn is_integer(&self) -> bool {
167 matches!(self.kind, TypeKind::Int(..))
168 }
169
170 pub(crate) fn as_integer(&self) -> Option<IntKind> {
173 match self.kind {
174 TypeKind::Int(int_kind) => Some(int_kind),
175 _ => None,
176 }
177 }
178
179 pub(crate) fn is_const(&self) -> bool {
181 self.is_const
182 }
183
184 pub(crate) fn is_unresolved_ref(&self) -> bool {
186 matches!(self.kind, TypeKind::UnresolvedTypeRef(_, _, _))
187 }
188
189 pub(crate) fn is_incomplete_array(
191 &self,
192 ctx: &BindgenContext,
193 ) -> Option<ItemId> {
194 match self.kind {
195 TypeKind::Array(item, len) => {
196 if len == 0 {
197 Some(item.into())
198 } else {
199 None
200 }
201 }
202 TypeKind::ResolvedTypeRef(inner) => {
203 ctx.resolve_type(inner).is_incomplete_array(ctx)
204 }
205 _ => None,
206 }
207 }
208
209 pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
211 self.layout.or_else(|| {
212 match self.kind {
213 TypeKind::Comp(ref ci) => ci.layout(ctx),
214 TypeKind::Array(inner, 0) => Some(Layout::new(
215 0,
216 ctx.resolve_type(inner).layout(ctx)?.align,
217 )),
218 TypeKind::Pointer(..) => Some(Layout::new(
221 ctx.target_pointer_size(),
222 ctx.target_pointer_size(),
223 )),
224 TypeKind::ResolvedTypeRef(inner) => {
225 ctx.resolve_type(inner).layout(ctx)
226 }
227 _ => None,
228 }
229 })
230 }
231
232 pub(crate) fn is_invalid_type_param(&self) -> bool {
237 match self.kind {
238 TypeKind::TypeParam => {
239 let name = self.name().expect("Unnamed named type?");
240 !clang::is_valid_identifier(name)
241 }
242 _ => false,
243 }
244 }
245
246 fn sanitize_name(name: &str) -> Cow<str> {
248 if clang::is_valid_identifier(name) {
249 return Cow::Borrowed(name);
250 }
251
252 let name = name.replace([' ', ':', '.'], "_");
253 Cow::Owned(name)
254 }
255
256 pub(crate) fn sanitized_name<'a>(
258 &'a self,
259 ctx: &BindgenContext,
260 ) -> Option<Cow<'a, str>> {
261 let name_info = match *self.kind() {
262 TypeKind::Pointer(inner) => Some((inner, Cow::Borrowed("ptr"))),
263 TypeKind::Reference(inner, _) => {
264 Some((inner, Cow::Borrowed("ref")))
265 }
266 TypeKind::Array(inner, length) => {
267 Some((inner, format!("array{length}").into()))
268 }
269 _ => None,
270 };
271 if let Some((inner, prefix)) = name_info {
272 ctx.resolve_item(inner)
273 .expect_type()
274 .sanitized_name(ctx)
275 .map(|name| format!("{prefix}_{name}").into())
276 } else {
277 self.name().map(Self::sanitize_name)
278 }
279 }
280
281 pub(crate) fn canonical_type<'tr>(
283 &'tr self,
284 ctx: &'tr BindgenContext,
285 ) -> &'tr Type {
286 self.safe_canonical_type(ctx)
287 .expect("Should have been resolved after parsing!")
288 }
289
290 pub(crate) fn safe_canonical_type<'tr>(
296 &'tr self,
297 ctx: &'tr BindgenContext,
298 ) -> Option<&'tr Type> {
299 match self.kind {
300 TypeKind::TypeParam |
301 TypeKind::Array(..) |
302 TypeKind::Vector(..) |
303 TypeKind::Comp(..) |
304 TypeKind::Opaque |
305 TypeKind::Int(..) |
306 TypeKind::Float(..) |
307 TypeKind::Complex(..) |
308 TypeKind::Function(..) |
309 TypeKind::Enum(..) |
310 TypeKind::Reference(..) |
311 TypeKind::Void |
312 TypeKind::NullPtr |
313 TypeKind::Pointer(..) |
314 TypeKind::BlockPointer(..) |
315 TypeKind::ObjCId |
316 TypeKind::ObjCSel |
317 TypeKind::ObjCInterface(..) => Some(self),
318
319 TypeKind::ResolvedTypeRef(inner) |
320 TypeKind::Alias(inner) |
321 TypeKind::TemplateAlias(inner, _) => {
322 ctx.resolve_type(inner).safe_canonical_type(ctx)
323 }
324 TypeKind::TemplateInstantiation(ref inst) => ctx
325 .resolve_type(inst.template_definition())
326 .safe_canonical_type(ctx),
327
328 TypeKind::UnresolvedTypeRef(..) => None,
329 }
330 }
331
332 pub(crate) fn should_be_traced_unconditionally(&self) -> bool {
335 matches!(
336 self.kind,
337 TypeKind::Comp(..) |
338 TypeKind::Function(..) |
339 TypeKind::Pointer(..) |
340 TypeKind::Array(..) |
341 TypeKind::Reference(..) |
342 TypeKind::TemplateInstantiation(..) |
343 TypeKind::ResolvedTypeRef(..)
344 )
345 }
346}
347
348impl IsOpaque for Type {
349 type Extra = Item;
350
351 fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool {
352 match self.kind {
353 TypeKind::Opaque => true,
354 TypeKind::TemplateInstantiation(ref inst) => {
355 inst.is_opaque(ctx, item)
356 }
357 TypeKind::Comp(ref comp) => comp.is_opaque(ctx, &self.layout),
358 TypeKind::ResolvedTypeRef(to) => to.is_opaque(ctx, &()),
359 _ => false,
360 }
361 }
362}
363
364impl AsTemplateParam for Type {
365 type Extra = Item;
366
367 fn as_template_param(
368 &self,
369 ctx: &BindgenContext,
370 item: &Item,
371 ) -> Option<TypeId> {
372 self.kind.as_template_param(ctx, item)
373 }
374}
375
376impl AsTemplateParam for TypeKind {
377 type Extra = Item;
378
379 fn as_template_param(
380 &self,
381 ctx: &BindgenContext,
382 item: &Item,
383 ) -> Option<TypeId> {
384 match *self {
385 TypeKind::TypeParam => Some(item.id().expect_type_id(ctx)),
386 TypeKind::ResolvedTypeRef(id) => id.as_template_param(ctx, &()),
387 _ => None,
388 }
389 }
390}
391
392impl DotAttributes for Type {
393 fn dot_attributes<W>(
394 &self,
395 ctx: &BindgenContext,
396 out: &mut W,
397 ) -> io::Result<()>
398 where
399 W: io::Write,
400 {
401 if let Some(ref layout) = self.layout {
402 writeln!(
403 out,
404 "<tr><td>size</td><td>{}</td></tr>
405 <tr><td>align</td><td>{}</td></tr>",
406 layout.size, layout.align
407 )?;
408 if layout.packed {
409 writeln!(out, "<tr><td>packed</td><td>true</td></tr>")?;
410 }
411 }
412
413 if self.is_const {
414 writeln!(out, "<tr><td>const</td><td>true</td></tr>")?;
415 }
416
417 self.kind.dot_attributes(ctx, out)
418 }
419}
420
421impl DotAttributes for TypeKind {
422 fn dot_attributes<W>(
423 &self,
424 ctx: &BindgenContext,
425 out: &mut W,
426 ) -> io::Result<()>
427 where
428 W: io::Write,
429 {
430 writeln!(
431 out,
432 "<tr><td>type kind</td><td>{}</td></tr>",
433 self.kind_name()
434 )?;
435
436 if let TypeKind::Comp(ref comp) = *self {
437 comp.dot_attributes(ctx, out)?;
438 }
439
440 Ok(())
441 }
442}
443
444impl TypeKind {
445 fn kind_name(&self) -> &'static str {
446 match *self {
447 TypeKind::Void => "Void",
448 TypeKind::NullPtr => "NullPtr",
449 TypeKind::Comp(..) => "Comp",
450 TypeKind::Opaque => "Opaque",
451 TypeKind::Int(..) => "Int",
452 TypeKind::Float(..) => "Float",
453 TypeKind::Complex(..) => "Complex",
454 TypeKind::Alias(..) => "Alias",
455 TypeKind::TemplateAlias(..) => "TemplateAlias",
456 TypeKind::Array(..) => "Array",
457 TypeKind::Vector(..) => "Vector",
458 TypeKind::Function(..) => "Function",
459 TypeKind::Enum(..) => "Enum",
460 TypeKind::Pointer(..) => "Pointer",
461 TypeKind::BlockPointer(..) => "BlockPointer",
462 TypeKind::Reference(..) => "Reference",
463 TypeKind::TemplateInstantiation(..) => "TemplateInstantiation",
464 TypeKind::UnresolvedTypeRef(..) => "UnresolvedTypeRef",
465 TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef",
466 TypeKind::TypeParam => "TypeParam",
467 TypeKind::ObjCInterface(..) => "ObjCInterface",
468 TypeKind::ObjCId => "ObjCId",
469 TypeKind::ObjCSel => "ObjCSel",
470 }
471 }
472}
473
474#[test]
475fn is_invalid_type_param_valid() {
476 let ty = Type::new(Some("foo".into()), None, TypeKind::TypeParam, false);
477 assert!(!ty.is_invalid_type_param());
478}
479
480#[test]
481fn is_invalid_type_param_valid_underscore_and_numbers() {
482 let ty = Type::new(
483 Some("_foo123456789_".into()),
484 None,
485 TypeKind::TypeParam,
486 false,
487 );
488 assert!(!ty.is_invalid_type_param());
489}
490
491#[test]
492fn is_invalid_type_param_valid_unnamed_kind() {
493 let ty = Type::new(Some("foo".into()), None, TypeKind::Void, false);
494 assert!(!ty.is_invalid_type_param());
495}
496
497#[test]
498fn is_invalid_type_param_invalid_start() {
499 let ty = Type::new(Some("1foo".into()), None, TypeKind::TypeParam, false);
500 assert!(ty.is_invalid_type_param());
501}
502
503#[test]
504fn is_invalid_type_param_invalid_remaining() {
505 let ty = Type::new(Some("foo-".into()), None, TypeKind::TypeParam, false);
506 assert!(ty.is_invalid_type_param());
507}
508
509#[test]
510#[should_panic(expected = "Unnamed named type")]
511fn is_invalid_type_param_unnamed() {
512 let ty = Type::new(None, None, TypeKind::TypeParam, false);
513 assert!(ty.is_invalid_type_param());
514}
515
516#[test]
517fn is_invalid_type_param_empty_name() {
518 let ty = Type::new(Some(String::new()), None, TypeKind::TypeParam, false);
519 assert!(ty.is_invalid_type_param());
520}
521
522impl TemplateParameters for Type {
523 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
524 self.kind.self_template_params(ctx)
525 }
526}
527
528impl TemplateParameters for TypeKind {
529 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
530 match *self {
531 TypeKind::ResolvedTypeRef(id) => {
532 ctx.resolve_type(id).self_template_params(ctx)
533 }
534 TypeKind::Comp(ref comp) => comp.self_template_params(ctx),
535 TypeKind::TemplateAlias(_, ref args) => args.clone(),
536
537 TypeKind::Opaque |
538 TypeKind::TemplateInstantiation(..) |
539 TypeKind::Void |
540 TypeKind::NullPtr |
541 TypeKind::Int(_) |
542 TypeKind::Float(_) |
543 TypeKind::Complex(_) |
544 TypeKind::Array(..) |
545 TypeKind::Vector(..) |
546 TypeKind::Function(_) |
547 TypeKind::Enum(_) |
548 TypeKind::Pointer(_) |
549 TypeKind::BlockPointer(_) |
550 TypeKind::Reference(..) |
551 TypeKind::UnresolvedTypeRef(..) |
552 TypeKind::TypeParam |
553 TypeKind::Alias(_) |
554 TypeKind::ObjCId |
555 TypeKind::ObjCSel |
556 TypeKind::ObjCInterface(_) => vec![],
557 }
558 }
559}
560
561#[derive(Debug, Copy, Clone, PartialEq, Eq)]
563pub(crate) enum FloatKind {
564 Float16,
566 Float,
568 Double,
570 LongDouble,
572 Float128,
574}
575
576#[derive(Debug)]
578pub(crate) enum TypeKind {
579 Void,
581
582 NullPtr,
584
585 Comp(CompInfo),
587
588 Opaque,
592
593 Int(IntKind),
596
597 Float(FloatKind),
599
600 Complex(FloatKind),
602
603 Alias(TypeId),
605
606 TemplateAlias(TypeId, Vec<TypeId>),
609
610 Vector(TypeId, usize),
612
613 Array(TypeId, usize),
615
616 Function(FunctionSig),
618
619 Enum(Enum),
621
622 Pointer(TypeId),
625
626 BlockPointer(TypeId),
628
629 Reference(TypeId, bool),
632
633 TemplateInstantiation(TemplateInstantiation),
636
637 UnresolvedTypeRef(clang::Type, Cursor, Option<ItemId>),
645
646 ResolvedTypeRef(TypeId),
651
652 TypeParam,
654
655 ObjCInterface(ObjCInterface),
657
658 ObjCId,
660
661 ObjCSel,
663}
664
665impl Type {
666 pub(crate) fn from_clang_ty(
672 potential_id: ItemId,
673 ty: &clang::Type,
674 location: Cursor,
675 parent_id: Option<ItemId>,
676 ctx: &mut BindgenContext,
677 ) -> Result<ParseResult<Self>, ParseError> {
678 use clang_sys::*;
679 {
680 let already_resolved = ctx.builtin_or_resolved_ty(
681 potential_id,
682 parent_id,
683 ty,
684 Some(location),
685 );
686 if let Some(ty) = already_resolved {
687 debug!("{ty:?} already resolved: {location:?}");
688 return Ok(ParseResult::AlreadyResolved(ty.into()));
689 }
690 }
691
692 let layout = ty.fallible_layout(ctx).ok();
693 let cursor = ty.declaration();
694 let is_anonymous = cursor.is_anonymous();
695 let mut name = if is_anonymous {
696 None
697 } else {
698 Some(cursor.spelling()).filter(|n| !n.is_empty())
699 };
700
701 debug!(
702 "from_clang_ty: {potential_id:?}, ty: {ty:?}, loc: {location:?}"
703 );
704 debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types());
705
706 let canonical_ty = ty.canonical_type();
707
708 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 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 if is_canonical_objcpointer && is_template_type_param {
730 name = Some("id".to_owned());
733 }
734 }
735
736 if location.kind() == CXCursor_ClassTemplatePartialSpecialization {
737 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 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 !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 if ty.ret_type().is_some() {
792 let signature =
793 FunctionSig::from_ty(ty, &location, ctx)?;
794 TypeKind::Function(signature)
795 } else if ty.is_fully_instantiated_template() {
798 debug!("Template specialization: {ty:?}, {location:?} {canonical_ty:?}");
799 let complex = CompInfo::from_ty(
800 potential_id,
801 ty,
802 Some(location),
803 ctx,
804 )
805 .expect("C'mon");
806 TypeKind::Comp(complex)
807 } else {
808 match location.kind() {
809 CXCursor_CXXBaseSpecifier |
810 CXCursor_ClassTemplate => {
811 if location.kind() == CXCursor_CXXBaseSpecifier
812 {
813 if location.spelling().chars().all(|c| {
853 c.is_alphanumeric() || c == '_'
854 }) {
855 return Err(ParseError::Recurse);
856 }
857 } else {
858 name = Some(location.spelling());
859 }
860
861 let complex = CompInfo::from_ty(
862 potential_id,
863 ty,
864 Some(location),
865 ctx,
866 );
867 if let Ok(complex) = complex {
868 TypeKind::Comp(complex)
869 } else {
870 warn!(
871 "Could not create complex type \
872 from class template or base \
873 specifier, using opaque blob"
874 );
875 let opaque = Opaque::from_clang_ty(ty, ctx);
876 return Ok(ParseResult::New(opaque, None));
877 }
878 }
879 CXCursor_TypeAliasTemplateDecl => {
880 debug!("TypeAliasTemplateDecl");
881
882 let mut inner = Err(ParseError::Continue);
884 let mut args = vec![];
885
886 location.visit(|cur| {
887 match cur.kind() {
888 CXCursor_TypeAliasDecl => {
889 let current = cur.cur_type();
890
891 debug_assert_eq!(
892 current.kind(),
893 CXType_Typedef
894 );
895
896 name = Some(location.spelling());
897
898 let inner_ty = cur
899 .typedef_type()
900 .expect("Not valid Type?");
901 inner = Ok(Item::from_ty_or_ref(
902 inner_ty,
903 cur,
904 Some(potential_id),
905 ctx,
906 ));
907 }
908 CXCursor_TemplateTypeParameter => {
909 let param = Item::type_param(
910 None, cur, ctx,
911 )
912 .expect(
913 "Item::type_param shouldn't \
914 ever fail if we are looking \
915 at a TemplateTypeParameter",
916 );
917 args.push(param);
918 }
919 _ => {}
920 }
921 CXChildVisit_Continue
922 });
923
924 let Ok(inner_type) = inner else {
925 warn!(
926 "Failed to parse template alias \
927 {:?}",
928 location
929 );
930 return Err(ParseError::Continue);
931 };
932
933 TypeKind::TemplateAlias(inner_type, args)
934 }
935 CXCursor_TemplateRef => {
936 let referenced = location.referenced().unwrap();
937 let referenced_ty = referenced.cur_type();
938
939 debug!("TemplateRef: location = {location:?}; referenced = {referenced:?}; referenced_ty = {referenced_ty:?}");
940
941 return Self::from_clang_ty(
942 potential_id,
943 &referenced_ty,
944 referenced,
945 parent_id,
946 ctx,
947 );
948 }
949 CXCursor_TypeRef => {
950 let referenced = location.referenced().unwrap();
951 let referenced_ty = referenced.cur_type();
952 let declaration = referenced_ty.declaration();
953
954 debug!("TypeRef: location = {location:?}; referenced = {referenced:?}; referenced_ty = {referenced_ty:?}");
955
956 let id = Item::from_ty_or_ref_with_id(
957 potential_id,
958 referenced_ty,
959 declaration,
960 parent_id,
961 ctx,
962 );
963 return Ok(ParseResult::AlreadyResolved(
964 id.into(),
965 ));
966 }
967 CXCursor_NamespaceRef => {
968 return Err(ParseError::Continue);
969 }
970 _ => {
971 if ty.kind() == CXType_Unexposed {
972 warn!("Unexposed type {ty:?}, recursing inside, loc: {location:?}");
973 return Err(ParseError::Recurse);
974 }
975
976 warn!("invalid type {ty:?}");
977 return Err(ParseError::Continue);
978 }
979 }
980 }
981 }
982 CXType_Auto => {
983 if canonical_ty == *ty {
984 debug!("Couldn't find deduced type: {ty:?}");
985 return Err(ParseError::Continue);
986 }
987
988 return Self::from_clang_ty(
989 potential_id,
990 &canonical_ty,
991 location,
992 parent_id,
993 ctx,
994 );
995 }
996 CXType_ObjCObjectPointer |
1004 CXType_MemberPointer |
1005 CXType_Pointer => {
1006 let mut pointee = ty.pointee_type().unwrap();
1007 if *ty != canonical_ty {
1008 let canonical_pointee =
1009 canonical_ty.pointee_type().unwrap();
1010 if canonical_pointee.is_const() != pointee.is_const() {
1013 pointee = canonical_pointee;
1014 }
1015 }
1016 let inner =
1017 Item::from_ty_or_ref(pointee, location, None, ctx);
1018 TypeKind::Pointer(inner)
1019 }
1020 CXType_BlockPointer => {
1021 let pointee = ty.pointee_type().expect("Not valid Type?");
1022 let inner =
1023 Item::from_ty_or_ref(pointee, location, None, ctx);
1024 TypeKind::BlockPointer(inner)
1025 }
1026 CXType_LValueReference => {
1029 let inner = Item::from_ty_or_ref(
1030 ty.pointee_type().unwrap(),
1031 location,
1032 None,
1033 ctx,
1034 );
1035 TypeKind::Reference(inner, false)
1036 }
1037 CXType_RValueReference => {
1038 let inner = Item::from_ty_or_ref(
1039 ty.pointee_type().unwrap(),
1040 location,
1041 None,
1042 ctx,
1043 );
1044 TypeKind::Reference(inner, true)
1045 }
1046 CXType_VariableArray | CXType_DependentSizedArray => {
1048 let inner = Item::from_ty(
1049 ty.elem_type().as_ref().unwrap(),
1050 location,
1051 None,
1052 ctx,
1053 )
1054 .expect("Not able to resolve array element?");
1055 TypeKind::Pointer(inner)
1056 }
1057 CXType_IncompleteArray => {
1058 let inner = Item::from_ty(
1059 ty.elem_type().as_ref().unwrap(),
1060 location,
1061 None,
1062 ctx,
1063 )
1064 .expect("Not able to resolve array element?");
1065 TypeKind::Array(inner, 0)
1066 }
1067 CXType_FunctionNoProto | CXType_FunctionProto => {
1068 let signature = FunctionSig::from_ty(ty, &location, ctx)?;
1069 TypeKind::Function(signature)
1070 }
1071 CXType_Typedef => {
1072 let inner = cursor.typedef_type().expect("Not valid Type?");
1073 let inner_id =
1074 Item::from_ty_or_ref(inner, location, None, ctx);
1075 if inner_id == potential_id {
1076 warn!(
1077 "Generating opaque type instead of self-referential \
1078 typedef");
1079 TypeKind::Opaque
1082 } else {
1083 if let Some(ref mut name) = name {
1087 if inner.kind() == CXType_Pointer &&
1088 !ctx.options().c_naming
1089 {
1090 let pointee = inner.pointee_type().unwrap();
1091 if pointee.kind() == CXType_Elaborated &&
1092 pointee.declaration().spelling() == *name
1093 {
1094 *name += "_ptr";
1095 }
1096 }
1097 }
1098 TypeKind::Alias(inner_id)
1099 }
1100 }
1101 CXType_Enum => {
1102 let visibility =
1103 Visibility::from(cursor.access_specifier());
1104 let enum_ = Enum::from_ty(ty, visibility, ctx)
1105 .expect("Not an enum?");
1106
1107 if !is_anonymous {
1108 let pretty_name = ty.spelling();
1109 if clang::is_valid_identifier(&pretty_name) {
1110 name = Some(pretty_name);
1111 }
1112 }
1113
1114 TypeKind::Enum(enum_)
1115 }
1116 CXType_Record => {
1117 let complex = CompInfo::from_ty(
1118 potential_id,
1119 ty,
1120 Some(location),
1121 ctx,
1122 )
1123 .expect("Not a complex type?");
1124
1125 if !is_anonymous {
1126 let pretty_name = ty.spelling();
1129 if clang::is_valid_identifier(&pretty_name) {
1130 name = Some(pretty_name);
1131 }
1132 }
1133
1134 TypeKind::Comp(complex)
1135 }
1136 CXType_Vector => {
1137 let inner = Item::from_ty(
1138 ty.elem_type().as_ref().unwrap(),
1139 location,
1140 None,
1141 ctx,
1142 )?;
1143 TypeKind::Vector(inner, ty.num_elements().unwrap())
1144 }
1145 CXType_ConstantArray => {
1146 let inner = Item::from_ty(
1147 ty.elem_type().as_ref().unwrap(),
1148 location,
1149 None,
1150 ctx,
1151 )
1152 .expect("Not able to resolve array element?");
1153 TypeKind::Array(inner, ty.num_elements().unwrap())
1154 }
1155 CXType_Atomic => {
1156 return Self::from_clang_ty(
1160 potential_id,
1161 &ty.atomic_value_type(),
1162 location,
1163 parent_id,
1164 ctx,
1165 );
1166 }
1167 CXType_Elaborated => {
1168 return Self::from_clang_ty(
1169 potential_id,
1170 &ty.named(),
1171 location,
1172 parent_id,
1173 ctx,
1174 );
1175 }
1176 CXType_ObjCId => TypeKind::ObjCId,
1177 CXType_ObjCSel => TypeKind::ObjCSel,
1178 CXType_ObjCClass | CXType_ObjCInterface => {
1179 let interface = ObjCInterface::from_ty(&location, ctx)
1180 .expect("Not a valid objc interface?");
1181 if !is_anonymous {
1182 name = Some(interface.rust_name());
1183 }
1184 TypeKind::ObjCInterface(interface)
1185 }
1186 CXType_Dependent => {
1187 return Err(ParseError::Continue);
1188 }
1189 _ => {
1190 warn!(
1191 "unsupported type: kind = {:?}; ty = {ty:?}; at {location:?}",
1192 ty.kind(),
1193 );
1194 return Err(ParseError::Continue);
1195 }
1196 }
1197 };
1198
1199 name = name.filter(|n| !n.is_empty());
1200
1201 let is_const = ty.is_const() ||
1202 (ty.kind() == CXType_ConstantArray &&
1203 ty.elem_type().is_some_and(|element| element.is_const()));
1204
1205 let ty = Type::new(name, layout, kind, is_const);
1206 Ok(ParseResult::New(ty, Some(cursor.canonical())))
1208 }
1209}
1210
1211impl Trace for Type {
1212 type Extra = Item;
1213
1214 fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
1215 where
1216 T: Tracer,
1217 {
1218 if self.name().is_some_and(|name| context.is_stdint_type(name)) {
1219 return;
1221 }
1222 match *self.kind() {
1223 TypeKind::Pointer(inner) |
1224 TypeKind::Reference(inner, _) |
1225 TypeKind::Array(inner, _) |
1226 TypeKind::Vector(inner, _) |
1227 TypeKind::BlockPointer(inner) |
1228 TypeKind::Alias(inner) |
1229 TypeKind::ResolvedTypeRef(inner) => {
1230 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1231 }
1232 TypeKind::TemplateAlias(inner, ref template_params) => {
1233 tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
1234 for param in template_params {
1235 tracer.visit_kind(
1236 param.into(),
1237 EdgeKind::TemplateParameterDefinition,
1238 );
1239 }
1240 }
1241 TypeKind::TemplateInstantiation(ref inst) => {
1242 inst.trace(context, tracer, &());
1243 }
1244 TypeKind::Comp(ref ci) => ci.trace(context, tracer, item),
1245 TypeKind::Function(ref sig) => sig.trace(context, tracer, &()),
1246 TypeKind::Enum(ref en) => {
1247 if let Some(repr) = en.repr() {
1248 tracer.visit(repr.into());
1249 }
1250 }
1251 TypeKind::UnresolvedTypeRef(_, _, Some(id)) => {
1252 tracer.visit(id);
1253 }
1254
1255 TypeKind::ObjCInterface(ref interface) => {
1256 interface.trace(context, tracer, &());
1257 }
1258
1259 TypeKind::Opaque |
1261 TypeKind::UnresolvedTypeRef(_, _, None) |
1262 TypeKind::TypeParam |
1263 TypeKind::Void |
1264 TypeKind::NullPtr |
1265 TypeKind::Int(_) |
1266 TypeKind::Float(_) |
1267 TypeKind::Complex(_) |
1268 TypeKind::ObjCId |
1269 TypeKind::ObjCSel => {}
1270 }
1271 }
1272}