1use super::super::time::Timer;
4use super::analysis::{
5 analyze, as_cannot_derive_set, CannotDerive, DeriveTrait,
6 HasDestructorAnalysis, HasFloat, HasTypeParameterInArray,
7 HasVtableAnalysis, HasVtableResult, SizednessAnalysis, SizednessResult,
8 UsedTemplateParameters,
9};
10use super::derive::{
11 CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
12 CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
13};
14use super::function::Function;
15use super::int::IntKind;
16use super::item::{IsOpaque, Item, ItemAncestors, ItemSet};
17use super::item_kind::ItemKind;
18use super::module::{Module, ModuleKind};
19use super::template::{TemplateInstantiation, TemplateParameters};
20use super::traversal::{self, Edge, ItemTraversal};
21use super::ty::{FloatKind, Type, TypeKind};
22use crate::clang::{self, ABIKind, Cursor};
23use crate::codegen::CodegenError;
24use crate::BindgenOptions;
25use crate::{Entry, HashMap, HashSet};
26
27use proc_macro2::{Ident, Span, TokenStream};
28use quote::ToTokens;
29use std::borrow::Cow;
30use std::cell::{Cell, RefCell};
31use std::collections::{BTreeSet, HashMap as StdHashMap};
32use std::mem;
33use std::path::Path;
34
35#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
37pub(crate) struct ItemId(usize);
38
39macro_rules! item_id_newtype {
41 (
42 $( #[$attr:meta] )*
43 pub(crate) struct $name:ident(ItemId)
44 where
45 $( #[$checked_attr:meta] )*
46 checked = $checked:ident with $check_method:ident,
47 $( #[$expected_attr:meta] )*
48 expected = $expected:ident,
49 $( #[$unchecked_attr:meta] )*
50 unchecked = $unchecked:ident;
51 ) => {
52 $( #[$attr] )*
53 #[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
54 pub(crate) struct $name(ItemId);
55
56 impl $name {
57 #[allow(dead_code)]
59 pub(crate) fn into_resolver(self) -> ItemResolver {
60 let id: ItemId = self.into();
61 id.into()
62 }
63 }
64
65 impl<T> ::std::cmp::PartialEq<T> for $name
66 where
67 T: Copy + Into<ItemId>
68 {
69 fn eq(&self, rhs: &T) -> bool {
70 let rhs: ItemId = (*rhs).into();
71 self.0 == rhs
72 }
73 }
74
75 impl From<$name> for ItemId {
76 fn from(id: $name) -> ItemId {
77 id.0
78 }
79 }
80
81 impl<'a> From<&'a $name> for ItemId {
82 fn from(id: &'a $name) -> ItemId {
83 id.0
84 }
85 }
86
87 #[allow(dead_code)]
88 impl ItemId {
89 $( #[$checked_attr] )*
90 pub(crate) fn $checked(&self, ctx: &BindgenContext) -> Option<$name> {
91 if ctx.resolve_item(*self).kind().$check_method() {
92 Some($name(*self))
93 } else {
94 None
95 }
96 }
97
98 $( #[$expected_attr] )*
99 pub(crate) fn $expected(&self, ctx: &BindgenContext) -> $name {
100 self.$checked(ctx)
101 .expect(concat!(
102 stringify!($expected),
103 " called with ItemId that points to the wrong ItemKind"
104 ))
105 }
106
107 $( #[$unchecked_attr] )*
108 pub(crate) fn $unchecked(&self) -> $name {
109 $name(*self)
110 }
111 }
112 }
113}
114
115item_id_newtype! {
116 pub(crate) struct TypeId(ItemId)
119 where
120 checked = as_type_id with is_type,
123
124 expected = expect_type_id,
128
129 unchecked = as_type_id_unchecked;
132}
133
134item_id_newtype! {
135 pub(crate) struct ModuleId(ItemId)
138 where
139 checked = as_module_id with is_module,
142
143 expected = expect_module_id,
147
148 unchecked = as_module_id_unchecked;
151}
152
153item_id_newtype! {
154 pub(crate) struct VarId(ItemId)
157 where
158 checked = as_var_id with is_var,
161
162 expected = expect_var_id,
166
167 unchecked = as_var_id_unchecked;
170}
171
172item_id_newtype! {
173 pub(crate) struct FunctionId(ItemId)
176 where
177 checked = as_function_id with is_function,
180
181 expected = expect_function_id,
185
186 unchecked = as_function_id_unchecked;
189}
190
191impl From<ItemId> for usize {
192 fn from(id: ItemId) -> usize {
193 id.0
194 }
195}
196
197impl ItemId {
198 pub(crate) fn as_usize(self) -> usize {
200 self.into()
201 }
202}
203
204impl<T> ::std::cmp::PartialEq<T> for ItemId
205where
206 T: Copy + Into<ItemId>,
207{
208 fn eq(&self, rhs: &T) -> bool {
209 let rhs: ItemId = (*rhs).into();
210 self.0 == rhs.0
211 }
212}
213
214impl<T> CanDeriveDebug for T
215where
216 T: Copy + Into<ItemId>,
217{
218 fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
219 ctx.options().derive_debug && ctx.lookup_can_derive_debug(*self)
220 }
221}
222
223impl<T> CanDeriveDefault for T
224where
225 T: Copy + Into<ItemId>,
226{
227 fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
228 ctx.options().derive_default && ctx.lookup_can_derive_default(*self)
229 }
230}
231
232impl<T> CanDeriveCopy for T
233where
234 T: Copy + Into<ItemId>,
235{
236 fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
237 ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self)
238 }
239}
240
241impl<T> CanDeriveHash for T
242where
243 T: Copy + Into<ItemId>,
244{
245 fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
246 ctx.options().derive_hash && ctx.lookup_can_derive_hash(*self)
247 }
248}
249
250impl<T> CanDerivePartialOrd for T
251where
252 T: Copy + Into<ItemId>,
253{
254 fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
255 ctx.options().derive_partialord &&
256 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
257 CanDerive::Yes
258 }
259}
260
261impl<T> CanDerivePartialEq for T
262where
263 T: Copy + Into<ItemId>,
264{
265 fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
266 ctx.options().derive_partialeq &&
267 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
268 CanDerive::Yes
269 }
270}
271
272impl<T> CanDeriveEq for T
273where
274 T: Copy + Into<ItemId>,
275{
276 fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
277 ctx.options().derive_eq &&
278 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
279 CanDerive::Yes &&
280 !ctx.lookup_has_float(*self)
281 }
282}
283
284impl<T> CanDeriveOrd for T
285where
286 T: Copy + Into<ItemId>,
287{
288 fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
289 ctx.options().derive_ord &&
290 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
291 CanDerive::Yes &&
292 !ctx.lookup_has_float(*self)
293 }
294}
295
296#[derive(Eq, PartialEq, Hash, Debug)]
303enum TypeKey {
304 Usr(String),
305 Declaration(Cursor),
306}
307
308#[derive(Debug)]
310pub(crate) struct BindgenContext {
311 items: Vec<Option<Item>>,
313
314 types: HashMap<TypeKey, TypeId>,
317
318 type_params: HashMap<Cursor, TypeId>,
321
322 modules: HashMap<Cursor, ModuleId>,
324
325 root_module: ModuleId,
327
328 current_module: ModuleId,
330
331 semantic_parents: HashMap<Cursor, ItemId>,
338
339 currently_parsed_types: Vec<PartialType>,
351
352 parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,
358
359 includes: StdHashMap<String, (String, usize)>,
366
367 deps: BTreeSet<Box<str>>,
369
370 replacements: HashMap<Vec<String>, ItemId>,
372
373 collected_typerefs: bool,
374
375 in_codegen: bool,
376
377 translation_unit: clang::TranslationUnit,
379
380 fallback_tu: Option<clang::FallbackTranslationUnit>,
382
383 target_info: clang::TargetInfo,
385
386 options: BindgenOptions,
388
389 generated_opaque_array: Cell<bool>,
391
392 generated_bindgen_complex: Cell<bool>,
394
395 generated_bindgen_float16: Cell<bool>,
397
398 allowlisted: Option<ItemSet>,
401
402 blocklisted_types_implement_traits:
404 RefCell<HashMap<DeriveTrait, HashMap<ItemId, CanDerive>>>,
405
406 codegen_items: Option<ItemSet>,
411
412 used_template_parameters: Option<HashMap<ItemId, ItemSet>>,
416
417 need_bitfield_allocation: Vec<ItemId>,
420
421 enum_typedef_combos: Option<HashSet<ItemId>>,
436
437 cannot_derive_debug: Option<HashSet<ItemId>>,
442
443 cannot_derive_default: Option<HashSet<ItemId>>,
448
449 cannot_derive_copy: Option<HashSet<ItemId>>,
454
455 cannot_derive_hash: Option<HashSet<ItemId>>,
460
461 cannot_derive_partialeq_or_partialord: Option<HashMap<ItemId, CanDerive>>,
467
468 sizedness: Option<HashMap<TypeId, SizednessResult>>,
473
474 have_vtable: Option<HashMap<ItemId, HasVtableResult>>,
479
480 have_destructor: Option<HashSet<ItemId>>,
485
486 has_type_param_in_array: Option<HashSet<ItemId>>,
491
492 has_float: Option<HashSet<ItemId>>,
497}
498
499struct AllowlistedItemsTraversal<'ctx> {
501 ctx: &'ctx BindgenContext,
502 traversal: ItemTraversal<'ctx, ItemSet, Vec<ItemId>>,
503}
504
505impl Iterator for AllowlistedItemsTraversal<'_> {
506 type Item = ItemId;
507
508 fn next(&mut self) -> Option<ItemId> {
509 loop {
510 let id = self.traversal.next()?;
511
512 if self.ctx.resolve_item(id).is_blocklisted(self.ctx) {
513 continue;
514 }
515
516 return Some(id);
517 }
518 }
519}
520
521impl<'ctx> AllowlistedItemsTraversal<'ctx> {
522 pub(crate) fn new<R>(
524 ctx: &'ctx BindgenContext,
525 roots: R,
526 predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool,
527 ) -> Self
528 where
529 R: IntoIterator<Item = ItemId>,
530 {
531 AllowlistedItemsTraversal {
532 ctx,
533 traversal: ItemTraversal::new(ctx, roots, predicate),
534 }
535 }
536}
537
538impl BindgenContext {
539 pub(crate) fn new(
541 options: BindgenOptions,
542 input_unsaved_files: &[clang::UnsavedFile],
543 ) -> Self {
544 let index = clang::Index::new(false, true);
548
549 let parse_options =
550 clang_sys::CXTranslationUnit_DetailedPreprocessingRecord;
551
552 let translation_unit = {
553 let _t =
554 Timer::new("translation_unit").with_output(options.time_phases);
555
556 clang::TranslationUnit::parse(
557 &index,
558 "",
559 &options.clang_args,
560 input_unsaved_files,
561 parse_options,
562 ).expect("libclang error; possible causes include:
563- Invalid flag syntax
564- Unrecognized flags
565- Invalid flag arguments
566- File I/O errors
567- Host vs. target architecture mismatch
568If you encounter an error missing from this list, please file an issue or a PR!")
569 };
570
571 let target_info = clang::TargetInfo::new(&translation_unit);
572 let root_module = Self::build_root_module(ItemId(0));
573 let root_module_id = root_module.id().as_module_id_unchecked();
574
575 let deps = options.input_headers.iter().cloned().collect();
577
578 BindgenContext {
579 items: vec![Some(root_module)],
580 includes: Default::default(),
581 deps,
582 types: Default::default(),
583 type_params: Default::default(),
584 modules: Default::default(),
585 root_module: root_module_id,
586 current_module: root_module_id,
587 semantic_parents: Default::default(),
588 currently_parsed_types: vec![],
589 parsed_macros: Default::default(),
590 replacements: Default::default(),
591 collected_typerefs: false,
592 in_codegen: false,
593 translation_unit,
594 fallback_tu: None,
595 target_info,
596 options,
597 generated_bindgen_complex: Cell::new(false),
598 generated_bindgen_float16: Cell::new(false),
599 generated_opaque_array: Cell::new(false),
600 allowlisted: None,
601 blocklisted_types_implement_traits: Default::default(),
602 codegen_items: None,
603 used_template_parameters: None,
604 need_bitfield_allocation: Default::default(),
605 enum_typedef_combos: None,
606 cannot_derive_debug: None,
607 cannot_derive_default: None,
608 cannot_derive_copy: None,
609 cannot_derive_hash: None,
610 cannot_derive_partialeq_or_partialord: None,
611 sizedness: None,
612 have_vtable: None,
613 have_destructor: None,
614 has_type_param_in_array: None,
615 has_float: None,
616 }
617 }
618
619 pub(crate) fn is_target_wasm32(&self) -> bool {
621 self.target_info.triple.starts_with("wasm32-")
622 }
623
624 pub(crate) fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
628 Timer::new(name).with_output(self.options.time_phases)
629 }
630
631 pub(crate) fn target_pointer_size(&self) -> usize {
634 self.target_info.pointer_width / 8
635 }
636
637 pub(crate) fn abi_kind(&self) -> ABIKind {
639 self.target_info.abi
640 }
641
642 pub(crate) fn currently_parsed_types(&self) -> &[PartialType] {
645 &self.currently_parsed_types[..]
646 }
647
648 pub(crate) fn begin_parsing(&mut self, partial_ty: PartialType) {
652 self.currently_parsed_types.push(partial_ty);
653 }
654
655 pub(crate) fn finish_parsing(&mut self) -> PartialType {
658 self.currently_parsed_types.pop().expect(
659 "should have been parsing a type, if we finished parsing a type",
660 )
661 }
662
663 pub(crate) fn add_include(
665 &mut self,
666 source_file: String,
667 included_file: String,
668 offset: usize,
669 ) {
670 self.includes
671 .entry(included_file)
672 .or_insert((source_file, offset));
673 }
674
675 pub(crate) fn included_file_location(
677 &self,
678 included_file: &str,
679 ) -> Option<(String, usize)> {
680 self.includes.get(included_file).cloned()
681 }
682
683 pub(crate) fn add_dep(&mut self, dep: Box<str>) {
685 self.deps.insert(dep);
686 }
687
688 pub(crate) fn deps(&self) -> &BTreeSet<Box<str>> {
690 &self.deps
691 }
692
693 pub(crate) fn add_item(
698 &mut self,
699 item: Item,
700 declaration: Option<Cursor>,
701 location: Option<Cursor>,
702 ) {
703 debug!("BindgenContext::add_item({item:?}, declaration: {declaration:?}, loc: {location:?}");
704 debug_assert!(
705 declaration.is_some() ||
706 !item.kind().is_type() ||
707 item.kind().expect_type().is_builtin_or_type_param() ||
708 item.kind().expect_type().is_opaque(self, &item) ||
709 item.kind().expect_type().is_unresolved_ref(),
710 "Adding a type without declaration?"
711 );
712
713 let id = item.id();
714 let is_type = item.kind().is_type();
715 let is_unnamed = is_type && item.expect_type().name().is_none();
716 let is_template_instantiation =
717 is_type && item.expect_type().is_template_instantiation();
718
719 if item.id() != self.root_module {
720 self.add_item_to_module(&item);
721 }
722
723 if is_type && item.expect_type().is_comp() {
724 self.need_bitfield_allocation.push(id);
725 }
726
727 let old_item = mem::replace(&mut self.items[id.0], Some(item));
728 assert!(
729 old_item.is_none(),
730 "should not have already associated an item with the given id"
731 );
732
733 if !is_type || is_template_instantiation {
737 return;
738 }
739 if let Some(mut declaration) = declaration {
740 if !declaration.is_valid() {
741 if let Some(location) = location {
742 if location.is_template_like() {
743 declaration = location;
744 }
745 }
746 }
747 declaration = declaration.canonical();
748 if !declaration.is_valid() {
749 debug!(
755 "Invalid declaration {declaration:?} found for type {:?}",
756 self.resolve_item_fallible(id)
757 .unwrap()
758 .kind()
759 .expect_type()
760 );
761 return;
762 }
763
764 let key = if is_unnamed {
765 TypeKey::Declaration(declaration)
766 } else if let Some(usr) = declaration.usr() {
767 TypeKey::Usr(usr)
768 } else {
769 warn!("Valid declaration with no USR: {declaration:?}, {location:?}");
770 TypeKey::Declaration(declaration)
771 };
772
773 let old = self.types.insert(key, id.as_type_id_unchecked());
774 debug_assert_eq!(old, None);
775 }
776 }
777
778 fn add_item_to_module(&mut self, item: &Item) {
783 assert_ne!(item.id(), self.root_module);
784 assert!(self.resolve_item_fallible(item.id()).is_none());
785
786 if let Some(ref mut parent) = self.items[item.parent_id().0] {
787 if let Some(module) = parent.as_module_mut() {
788 debug!(
789 "add_item_to_module: adding {:?} as child of parent module {:?}",
790 item.id(),
791 item.parent_id()
792 );
793
794 module.children_mut().insert(item.id());
795 return;
796 }
797 }
798
799 debug!(
800 "add_item_to_module: adding {:?} as child of current module {:?}",
801 item.id(),
802 self.current_module
803 );
804
805 self.items[self.current_module.0 .0]
806 .as_mut()
807 .expect("Should always have an item for self.current_module")
808 .as_module_mut()
809 .expect("self.current_module should always be a module")
810 .children_mut()
811 .insert(item.id());
812 }
813
814 pub(crate) fn add_type_param(&mut self, item: Item, definition: Cursor) {
816 debug!("BindgenContext::add_type_param: item = {item:?}; definition = {definition:?}");
817
818 assert!(
819 item.expect_type().is_type_param(),
820 "Should directly be a named type, not a resolved reference or anything"
821 );
822 assert_eq!(
823 definition.kind(),
824 clang_sys::CXCursor_TemplateTypeParameter
825 );
826
827 self.add_item_to_module(&item);
828
829 let id = item.id();
830 let old_item = mem::replace(&mut self.items[id.0], Some(item));
831 assert!(
832 old_item.is_none(),
833 "should not have already associated an item with the given id"
834 );
835
836 let old_named_ty = self
837 .type_params
838 .insert(definition, id.as_type_id_unchecked());
839 assert!(
840 old_named_ty.is_none(),
841 "should not have already associated a named type with this id"
842 );
843 }
844
845 pub(crate) fn get_type_param(&self, definition: &Cursor) -> Option<TypeId> {
848 assert_eq!(
849 definition.kind(),
850 clang_sys::CXCursor_TemplateTypeParameter
851 );
852 self.type_params.get(definition).copied()
853 }
854
855 #[rustfmt::skip]
859 pub(crate) fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
860 if name.contains('@') ||
861 name.contains('?') ||
862 name.contains('$') ||
863 matches!(
864 name,
865 "abstract" | "alignof" | "as" | "async" | "await" | "become" |
866 "box" | "break" | "const" | "continue" | "crate" | "do" |
867 "dyn" | "else" | "enum" | "extern" | "false" | "final" |
868 "fn" | "for" | "gen" | "if" | "impl" | "in" | "let" | "loop" |
869 "macro" | "match" | "mod" | "move" | "mut" | "offsetof" |
870 "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
871 "return" | "Self" | "self" | "sizeof" | "static" |
872 "struct" | "super" | "trait" | "true" | "try" | "type" | "typeof" |
873 "unsafe" | "unsized" | "use" | "virtual" | "where" |
874 "while" | "yield" | "str" | "bool" | "f32" | "f64" |
875 "usize" | "isize" | "u128" | "i128" | "u64" | "i64" |
876 "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "_"
877 )
878 {
879 let mut s = name.to_owned();
880 s = s.replace('@', "_");
881 s = s.replace('?', "_");
882 s = s.replace('$', "_");
883 s.push('_');
884 return Cow::Owned(s);
885 }
886 Cow::Borrowed(name)
887 }
888
889 pub(crate) fn rust_ident<S>(&self, name: S) -> Ident
891 where
892 S: AsRef<str>,
893 {
894 self.rust_ident_raw(self.rust_mangle(name.as_ref()))
895 }
896
897 pub(crate) fn rust_ident_raw<T>(&self, name: T) -> Ident
899 where
900 T: AsRef<str>,
901 {
902 Ident::new(name.as_ref(), Span::call_site())
903 }
904
905 pub(crate) fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
907 self.items.iter().enumerate().filter_map(|(index, item)| {
908 let item = item.as_ref()?;
909 Some((ItemId(index), item))
910 })
911 }
912
913 pub(crate) fn collected_typerefs(&self) -> bool {
915 self.collected_typerefs
916 }
917
918 fn collect_typerefs(
920 &mut self,
921 ) -> Vec<(ItemId, clang::Type, Cursor, Option<ItemId>)> {
922 debug_assert!(!self.collected_typerefs);
923 self.collected_typerefs = true;
924 let mut typerefs = vec![];
925
926 for (id, item) in self.items() {
927 let kind = item.kind();
928 let Some(ty) = kind.as_type() else { continue };
929
930 if let TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) =
931 *ty.kind()
932 {
933 typerefs.push((id, *ty, loc, parent_id));
934 }
935 }
936 typerefs
937 }
938
939 fn resolve_typerefs(&mut self) {
941 let _t = self.timer("resolve_typerefs");
942
943 let typerefs = self.collect_typerefs();
944
945 for (id, ty, loc, parent_id) in typerefs {
946 let _resolved =
947 {
948 let resolved = Item::from_ty(&ty, loc, parent_id, self)
949 .unwrap_or_else(|_| {
950 warn!("Could not resolve type reference, falling back \
951 to opaque blob");
952 Item::new_opaque_type(self.next_item_id(), &ty, self)
953 });
954
955 let item = self.items[id.0].as_mut().unwrap();
956 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
957 TypeKind::ResolvedTypeRef(resolved);
958 resolved
959 };
960
961 }
970 }
971
972 fn with_loaned_item<F, T>(&mut self, id: ItemId, f: F) -> T
983 where
984 F: (FnOnce(&BindgenContext, &mut Item) -> T),
985 {
986 let mut item = self.items[id.0].take().unwrap();
987
988 let result = f(self, &mut item);
989
990 let existing = mem::replace(&mut self.items[id.0], Some(item));
991 assert!(existing.is_none());
992
993 result
994 }
995
996 fn compute_bitfield_units(&mut self) {
999 let _t = self.timer("compute_bitfield_units");
1000
1001 assert!(self.collected_typerefs());
1002
1003 let need_bitfield_allocation =
1004 mem::take(&mut self.need_bitfield_allocation);
1005 for id in need_bitfield_allocation {
1006 self.with_loaned_item(id, |ctx, item| {
1007 let ty = item.kind_mut().as_type_mut().unwrap();
1008 let layout = ty.layout(ctx);
1009 ty.as_comp_mut()
1010 .unwrap()
1011 .compute_bitfield_units(ctx, layout.as_ref());
1012 });
1013 }
1014 }
1015
1016 fn deanonymize_fields(&mut self) {
1018 let _t = self.timer("deanonymize_fields");
1019
1020 let comp_item_ids: Vec<ItemId> = self
1021 .items()
1022 .filter_map(|(id, item)| {
1023 if item.kind().as_type()?.is_comp() {
1024 return Some(id);
1025 }
1026 None
1027 })
1028 .collect();
1029
1030 for id in comp_item_ids {
1031 self.with_loaned_item(id, |ctx, item| {
1032 item.kind_mut()
1033 .as_type_mut()
1034 .unwrap()
1035 .as_comp_mut()
1036 .unwrap()
1037 .deanonymize_fields(ctx);
1038 });
1039 }
1040 }
1041
1042 fn process_replacements(&mut self) {
1045 let _t = self.timer("process_replacements");
1046 if self.replacements.is_empty() {
1047 debug!("No replacements to process");
1048 return;
1049 }
1050
1051 let mut replacements = vec![];
1057
1058 for (id, item) in self.items() {
1059 if item.annotations().use_instead_of().is_some() {
1060 continue;
1061 }
1062
1063 let Some(ty) = item.kind().as_type() else {
1066 continue;
1067 };
1068
1069 match *ty.kind() {
1070 TypeKind::Comp(..) |
1071 TypeKind::TemplateAlias(..) |
1072 TypeKind::Enum(..) |
1073 TypeKind::Alias(..) => {}
1074 _ => continue,
1075 }
1076
1077 let path = item.path_for_allowlisting(self);
1078 let replacement = self.replacements.get(&path[1..]);
1079
1080 if let Some(replacement) = replacement {
1081 if *replacement != id {
1082 if self.resolve_item_fallible(*replacement).is_some() {
1085 replacements.push((
1086 id.expect_type_id(self),
1087 replacement.expect_type_id(self),
1088 ));
1089 }
1090 }
1091 }
1092 }
1093
1094 for (id, replacement_id) in replacements {
1095 debug!("Replacing {id:?} with {replacement_id:?}");
1096 let new_parent = {
1097 let item_id: ItemId = id.into();
1098 let item = self.items[item_id.0].as_mut().unwrap();
1099 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
1100 TypeKind::ResolvedTypeRef(replacement_id);
1101 item.parent_id()
1102 };
1103
1104 let old_parent = self.resolve_item(replacement_id).parent_id();
1110 if new_parent == old_parent {
1111 continue;
1114 }
1115
1116 let replacement_item_id: ItemId = replacement_id.into();
1117 self.items[replacement_item_id.0]
1118 .as_mut()
1119 .unwrap()
1120 .set_parent_for_replacement(new_parent);
1121
1122 let old_module = {
1126 let immut_self = &*self;
1127 old_parent
1128 .ancestors(immut_self)
1129 .chain(Some(immut_self.root_module.into()))
1130 .find(|id| {
1131 let item = immut_self.resolve_item(*id);
1132 item.as_module().is_some_and(|m| {
1133 m.children().contains(&replacement_id.into())
1134 })
1135 })
1136 };
1137 let old_module = old_module
1138 .expect("Every replacement item should be in a module");
1139
1140 let new_module = {
1141 let immut_self = &*self;
1142 new_parent
1143 .ancestors(immut_self)
1144 .find(|id| immut_self.resolve_item(*id).is_module())
1145 };
1146 let new_module =
1147 new_module.unwrap_or_else(|| self.root_module.into());
1148
1149 if new_module == old_module {
1150 continue;
1152 }
1153
1154 self.items[old_module.0]
1155 .as_mut()
1156 .unwrap()
1157 .as_module_mut()
1158 .unwrap()
1159 .children_mut()
1160 .remove(&replacement_id.into());
1161
1162 self.items[new_module.0]
1163 .as_mut()
1164 .unwrap()
1165 .as_module_mut()
1166 .unwrap()
1167 .children_mut()
1168 .insert(replacement_id.into());
1169 }
1170 }
1171
1172 pub(crate) fn gen<F, Out>(
1175 mut self,
1176 cb: F,
1177 ) -> Result<(Out, BindgenOptions), CodegenError>
1178 where
1179 F: FnOnce(&Self) -> Result<Out, CodegenError>,
1180 {
1181 self.in_codegen = true;
1182
1183 self.resolve_typerefs();
1184 self.compute_bitfield_units();
1185 self.process_replacements();
1186
1187 self.deanonymize_fields();
1188
1189 self.assert_no_dangling_references();
1190
1191 self.compute_allowlisted_and_codegen_items();
1195
1196 self.assert_every_item_in_a_module();
1200
1201 self.compute_has_vtable();
1202 self.compute_sizedness();
1203 self.compute_has_destructor();
1204 self.find_used_template_parameters();
1205 self.compute_enum_typedef_combos();
1206 self.compute_cannot_derive_debug();
1207 self.compute_cannot_derive_default();
1208 self.compute_cannot_derive_copy();
1209 self.compute_has_type_param_in_array();
1210 self.compute_has_float();
1211 self.compute_cannot_derive_hash();
1212 self.compute_cannot_derive_partialord_partialeq_or_eq();
1213
1214 let ret = cb(&self)?;
1215 Ok((ret, self.options))
1216 }
1217
1218 fn assert_no_dangling_references(&self) {
1222 if cfg!(feature = "__testing_only_extra_assertions") {
1223 for _ in self.assert_no_dangling_item_traversal() {
1224 }
1226 }
1227 }
1228
1229 fn assert_no_dangling_item_traversal(
1230 &self,
1231 ) -> traversal::AssertNoDanglingItemsTraversal<'_> {
1232 assert!(self.in_codegen_phase());
1233 assert_eq!(self.current_module, self.root_module);
1234
1235 let roots = self.items().map(|(id, _)| id);
1236 traversal::AssertNoDanglingItemsTraversal::new(
1237 self,
1238 roots,
1239 traversal::all_edges,
1240 )
1241 }
1242
1243 fn assert_every_item_in_a_module(&self) {
1247 if cfg!(feature = "__testing_only_extra_assertions") {
1248 assert!(self.in_codegen_phase());
1249 assert_eq!(self.current_module, self.root_module);
1250
1251 for (id, _item) in self.items() {
1252 if id == self.root_module {
1253 continue;
1254 }
1255
1256 assert!(
1257 {
1258 let id = id
1259 .into_resolver()
1260 .through_type_refs()
1261 .through_type_aliases()
1262 .resolve(self)
1263 .id();
1264 id.ancestors(self)
1265 .chain(Some(self.root_module.into()))
1266 .any(|ancestor| {
1267 debug!("Checking if {id:?} is a child of {ancestor:?}");
1268 self.resolve_item(ancestor)
1269 .as_module()
1270 .is_some_and(|m| m.children().contains(&id))
1271 })
1272 },
1273 "{id:?} should be in some ancestor module's children set"
1274 );
1275 }
1276 }
1277 }
1278
1279 fn compute_sizedness(&mut self) {
1282 let _t = self.timer("compute_sizedness");
1283 assert!(self.sizedness.is_none());
1284 self.sizedness = Some(analyze::<SizednessAnalysis>(self));
1285 }
1286
1287 pub(crate) fn lookup_sizedness(&self, id: TypeId) -> SizednessResult {
1289 assert!(
1290 self.in_codegen_phase(),
1291 "We only compute sizedness after we've entered codegen"
1292 );
1293
1294 self.sizedness
1295 .as_ref()
1296 .unwrap()
1297 .get(&id)
1298 .copied()
1299 .unwrap_or(SizednessResult::ZeroSized)
1300 }
1301
1302 fn compute_has_vtable(&mut self) {
1304 let _t = self.timer("compute_has_vtable");
1305 assert!(self.have_vtable.is_none());
1306 self.have_vtable = Some(analyze::<HasVtableAnalysis>(self));
1307 }
1308
1309 pub(crate) fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult {
1311 assert!(
1312 self.in_codegen_phase(),
1313 "We only compute vtables when we enter codegen"
1314 );
1315
1316 self.have_vtable
1319 .as_ref()
1320 .unwrap()
1321 .get(&id.into())
1322 .copied()
1323 .unwrap_or(HasVtableResult::No)
1324 }
1325
1326 fn compute_has_destructor(&mut self) {
1328 let _t = self.timer("compute_has_destructor");
1329 assert!(self.have_destructor.is_none());
1330 self.have_destructor = Some(analyze::<HasDestructorAnalysis>(self));
1331 }
1332
1333 pub(crate) fn lookup_has_destructor(&self, id: TypeId) -> bool {
1335 assert!(
1336 self.in_codegen_phase(),
1337 "We only compute destructors when we enter codegen"
1338 );
1339
1340 self.have_destructor.as_ref().unwrap().contains(&id.into())
1341 }
1342
1343 fn find_used_template_parameters(&mut self) {
1344 let _t = self.timer("find_used_template_parameters");
1345 if self.options.allowlist_recursively {
1346 let used_params = analyze::<UsedTemplateParameters>(self);
1347 self.used_template_parameters = Some(used_params);
1348 } else {
1349 let mut used_params = HashMap::default();
1352 for &id in self.allowlisted_items() {
1353 used_params.entry(id).or_insert_with(|| {
1354 id.self_template_params(self)
1355 .into_iter()
1356 .map(|p| p.into())
1357 .collect()
1358 });
1359 }
1360 self.used_template_parameters = Some(used_params);
1361 }
1362 }
1363
1364 pub(crate) fn uses_template_parameter(
1379 &self,
1380 item: ItemId,
1381 template_param: TypeId,
1382 ) -> bool {
1383 assert!(
1384 self.in_codegen_phase(),
1385 "We only compute template parameter usage as we enter codegen"
1386 );
1387
1388 if self.resolve_item(item).is_blocklisted(self) {
1389 return true;
1390 }
1391
1392 let template_param = template_param
1393 .into_resolver()
1394 .through_type_refs()
1395 .through_type_aliases()
1396 .resolve(self)
1397 .id();
1398
1399 self.used_template_parameters
1400 .as_ref()
1401 .expect("should have found template parameter usage if we're in codegen")
1402 .get(&item).is_some_and(|items_used_params| items_used_params.contains(&template_param))
1403 }
1404
1405 pub(crate) fn uses_any_template_parameters(&self, item: ItemId) -> bool {
1410 assert!(
1411 self.in_codegen_phase(),
1412 "We only compute template parameter usage as we enter codegen"
1413 );
1414
1415 self.used_template_parameters
1416 .as_ref()
1417 .expect(
1418 "should have template parameter usage info in codegen phase",
1419 )
1420 .get(&item)
1421 .is_some_and(|used| !used.is_empty())
1422 }
1423
1424 fn add_builtin_item(&mut self, item: Item) {
1433 debug!("add_builtin_item: item = {item:?}");
1434 debug_assert!(item.kind().is_type());
1435 self.add_item_to_module(&item);
1436 let id = item.id();
1437 let old_item = mem::replace(&mut self.items[id.0], Some(item));
1438 assert!(old_item.is_none(), "Inserted type twice?");
1439 }
1440
1441 fn build_root_module(id: ItemId) -> Item {
1442 let module = Module::new(Some("root".into()), ModuleKind::Normal);
1443 Item::new(id, None, None, id, ItemKind::Module(module), None)
1444 }
1445
1446 pub(crate) fn root_module(&self) -> ModuleId {
1448 self.root_module
1449 }
1450
1451 pub(crate) fn resolve_type(&self, type_id: TypeId) -> &Type {
1456 self.resolve_item(type_id).kind().expect_type()
1457 }
1458
1459 pub(crate) fn resolve_func(&self, func_id: FunctionId) -> &Function {
1464 self.resolve_item(func_id).kind().expect_function()
1465 }
1466
1467 pub(crate) fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
1472 self.resolve_item_fallible(type_id)
1473 .map(|t| t.kind().expect_type())
1474 }
1475
1476 pub(crate) fn resolve_item_fallible<Id: Into<ItemId>>(
1479 &self,
1480 id: Id,
1481 ) -> Option<&Item> {
1482 self.items.get(id.into().0)?.as_ref()
1483 }
1484
1485 pub(crate) fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
1489 let item_id = item_id.into();
1490 match self.resolve_item_fallible(item_id) {
1491 Some(item) => item,
1492 None => panic!("Not an item: {item_id:?}"),
1493 }
1494 }
1495
1496 pub(crate) fn current_module(&self) -> ModuleId {
1498 self.current_module
1499 }
1500
1501 pub(crate) fn add_semantic_parent(
1510 &mut self,
1511 definition: Cursor,
1512 parent_id: ItemId,
1513 ) {
1514 self.semantic_parents.insert(definition, parent_id);
1515 }
1516
1517 pub(crate) fn known_semantic_parent(
1519 &self,
1520 definition: Cursor,
1521 ) -> Option<ItemId> {
1522 self.semantic_parents.get(&definition).copied()
1523 }
1524
1525 fn get_declaration_info_for_template_instantiation(
1533 &self,
1534 instantiation: &Cursor,
1535 ) -> Option<(Cursor, ItemId, usize)> {
1536 instantiation
1537 .cur_type()
1538 .canonical_declaration(Some(instantiation))
1539 .and_then(|canon_decl| {
1540 self.get_resolved_type(&canon_decl).and_then(
1541 |template_decl_id| {
1542 let num_params =
1543 template_decl_id.num_self_template_params(self);
1544 if num_params == 0 {
1545 None
1546 } else {
1547 Some((
1548 *canon_decl.cursor(),
1549 template_decl_id.into(),
1550 num_params,
1551 ))
1552 }
1553 },
1554 )
1555 })
1556 .or_else(|| {
1557 instantiation
1565 .referenced()
1566 .and_then(|referenced| {
1567 self.currently_parsed_types()
1568 .iter()
1569 .find(|partial_ty| *partial_ty.decl() == referenced)
1570 })
1571 .and_then(|template_decl| {
1572 let num_template_params =
1573 template_decl.num_self_template_params(self);
1574 if num_template_params == 0 {
1575 None
1576 } else {
1577 Some((
1578 *template_decl.decl(),
1579 template_decl.id(),
1580 num_template_params,
1581 ))
1582 }
1583 })
1584 })
1585 }
1586
1587 fn instantiate_template(
1621 &mut self,
1622 with_id: ItemId,
1623 template: TypeId,
1624 ty: &clang::Type,
1625 location: Cursor,
1626 ) -> Option<TypeId> {
1627 let num_expected_args =
1628 self.resolve_type(template).num_self_template_params(self);
1629 if num_expected_args == 0 {
1630 warn!(
1631 "Tried to instantiate a template for which we could not \
1632 determine any template parameters"
1633 );
1634 return None;
1635 }
1636
1637 let mut args = vec![];
1638 let mut found_const_arg = false;
1639 let mut children = location.collect_children();
1640
1641 if children.iter().all(|c| !c.has_children()) {
1642 let idx = children
1653 .iter()
1654 .position(|c| c.kind() == clang_sys::CXCursor_TemplateRef);
1655 if let Some(idx) = idx {
1656 if children
1657 .iter()
1658 .take(idx)
1659 .all(|c| c.kind() == clang_sys::CXCursor_NamespaceRef)
1660 {
1661 children = children.into_iter().skip(idx + 1).collect();
1662 }
1663 }
1664 }
1665
1666 for child in children.iter().rev() {
1667 match child.kind() {
1668 clang_sys::CXCursor_TypeRef |
1669 clang_sys::CXCursor_TypedefDecl |
1670 clang_sys::CXCursor_TypeAliasDecl => {
1671 let ty = Item::from_ty_or_ref(
1678 child.cur_type(),
1679 *child,
1680 Some(template.into()),
1681 self,
1682 );
1683 args.push(ty);
1684 }
1685 clang_sys::CXCursor_TemplateRef => {
1686 let (
1687 template_decl_cursor,
1688 template_decl_id,
1689 num_expected_template_args,
1690 ) = self.get_declaration_info_for_template_instantiation(
1691 child,
1692 )?;
1693
1694 if num_expected_template_args == 0 ||
1695 child.has_at_least_num_children(
1696 num_expected_template_args,
1697 )
1698 {
1699 let ty = Item::from_ty_or_ref(
1702 child.cur_type(),
1703 *child,
1704 Some(template.into()),
1705 self,
1706 );
1707 args.push(ty);
1708 } else {
1709 let args_len = args.len();
1714 if args_len < num_expected_template_args {
1715 warn!(
1716 "Found a template instantiation without \
1717 enough template arguments"
1718 );
1719 return None;
1720 }
1721
1722 let mut sub_args: Vec<_> = args
1723 .drain(args_len - num_expected_template_args..)
1724 .collect();
1725 sub_args.reverse();
1726
1727 let sub_name = Some(template_decl_cursor.spelling());
1728 let sub_inst = TemplateInstantiation::new(
1729 template_decl_id.as_type_id_unchecked(),
1732 sub_args,
1733 );
1734 let sub_kind =
1735 TypeKind::TemplateInstantiation(sub_inst);
1736 let sub_ty = Type::new(
1737 sub_name,
1738 template_decl_cursor
1739 .cur_type()
1740 .fallible_layout(self)
1741 .ok(),
1742 sub_kind,
1743 false,
1744 );
1745 let sub_id = self.next_item_id();
1746 let sub_item = Item::new(
1747 sub_id,
1748 None,
1749 None,
1750 self.current_module.into(),
1751 ItemKind::Type(sub_ty),
1752 Some(child.location()),
1753 );
1754
1755 debug!(
1757 "instantiate_template: inserting nested \
1758 instantiation item: {:?}",
1759 sub_item
1760 );
1761 self.add_item_to_module(&sub_item);
1762 debug_assert_eq!(sub_id, sub_item.id());
1763 self.items[sub_id.0] = Some(sub_item);
1764 args.push(sub_id.as_type_id_unchecked());
1765 }
1766 }
1767 _ => {
1768 warn!(
1769 "Found template arg cursor we can't handle: {child:?}"
1770 );
1771 found_const_arg = true;
1772 }
1773 }
1774 }
1775
1776 if found_const_arg {
1777 warn!(
1784 "Found template instantiated with a const value; \
1785 bindgen can't handle this kind of template instantiation!"
1786 );
1787 return None;
1788 }
1789
1790 if args.len() != num_expected_args {
1791 warn!(
1792 "Found a template with an unexpected number of template \
1793 arguments"
1794 );
1795 return None;
1796 }
1797
1798 args.reverse();
1799 let type_kind = TypeKind::TemplateInstantiation(
1800 TemplateInstantiation::new(template, args),
1801 );
1802 let name = ty.spelling();
1803 let name = if name.is_empty() { None } else { Some(name) };
1804 let ty = Type::new(
1805 name,
1806 ty.fallible_layout(self).ok(),
1807 type_kind,
1808 ty.is_const(),
1809 );
1810 let item = Item::new(
1811 with_id,
1812 None,
1813 None,
1814 self.current_module.into(),
1815 ItemKind::Type(ty),
1816 Some(location.location()),
1817 );
1818
1819 debug!("instantiate_template: inserting item: {item:?}");
1821 self.add_item_to_module(&item);
1822 debug_assert_eq!(with_id, item.id());
1823 self.items[with_id.0] = Some(item);
1824 Some(with_id.as_type_id_unchecked())
1825 }
1826
1827 pub(crate) fn get_resolved_type(
1830 &self,
1831 decl: &clang::CanonicalTypeDeclaration,
1832 ) -> Option<TypeId> {
1833 self.types
1834 .get(&TypeKey::Declaration(*decl.cursor()))
1835 .or_else(|| {
1836 decl.cursor()
1837 .usr()
1838 .and_then(|usr| self.types.get(&TypeKey::Usr(usr)))
1839 })
1840 .copied()
1841 }
1842
1843 pub(crate) fn builtin_or_resolved_ty(
1846 &mut self,
1847 with_id: ItemId,
1848 parent_id: Option<ItemId>,
1849 ty: &clang::Type,
1850 location: Option<Cursor>,
1851 ) -> Option<TypeId> {
1852 use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
1853 debug!("builtin_or_resolved_ty: {ty:?}, {location:?}, {with_id:?}, {parent_id:?}");
1854
1855 if let Some(decl) = ty.canonical_declaration(location.as_ref()) {
1856 if let Some(id) = self.get_resolved_type(&decl) {
1857 debug!(
1858 "Already resolved ty {id:?}, {decl:?}, {ty:?} {location:?}"
1859 );
1860 if let Some(location) = location {
1868 if decl.cursor().is_template_like() &&
1869 *ty != decl.cursor().cur_type()
1870 {
1871 if decl.cursor().kind() ==
1882 CXCursor_TypeAliasTemplateDecl &&
1883 !location.contains_cursor(CXCursor_TypeRef) &&
1884 ty.canonical_type().is_valid_and_exposed()
1885 {
1886 return None;
1887 }
1888
1889 return self
1890 .instantiate_template(with_id, id, ty, location)
1891 .or(Some(id));
1892 }
1893 }
1894
1895 return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
1896 }
1897 }
1898
1899 debug!("Not resolved, maybe builtin?");
1900 self.build_builtin_ty(ty)
1901 }
1902
1903 pub(crate) fn build_ty_wrapper(
1912 &mut self,
1913 with_id: ItemId,
1914 wrapped_id: TypeId,
1915 parent_id: Option<ItemId>,
1916 ty: &clang::Type,
1917 ) -> TypeId {
1918 self.build_wrapper(with_id, wrapped_id, parent_id, ty, ty.is_const())
1919 }
1920
1921 pub(crate) fn build_const_wrapper(
1925 &mut self,
1926 with_id: ItemId,
1927 wrapped_id: TypeId,
1928 parent_id: Option<ItemId>,
1929 ty: &clang::Type,
1930 ) -> TypeId {
1931 self.build_wrapper(
1932 with_id, wrapped_id, parent_id, ty, true,
1933 )
1934 }
1935
1936 fn build_wrapper(
1937 &mut self,
1938 with_id: ItemId,
1939 wrapped_id: TypeId,
1940 parent_id: Option<ItemId>,
1941 ty: &clang::Type,
1942 is_const: bool,
1943 ) -> TypeId {
1944 let spelling = ty.spelling();
1945 let layout = ty.fallible_layout(self).ok();
1946 let location = ty.declaration().location();
1947 let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
1948 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
1949 let item = Item::new(
1950 with_id,
1951 None,
1952 None,
1953 parent_id.unwrap_or_else(|| self.current_module.into()),
1954 ItemKind::Type(ty),
1955 Some(location),
1956 );
1957 self.add_builtin_item(item);
1958 with_id.as_type_id_unchecked()
1959 }
1960
1961 pub(crate) fn next_item_id(&mut self) -> ItemId {
1963 let ret = ItemId(self.items.len());
1964 self.items.push(None);
1965 ret
1966 }
1967
1968 fn build_builtin_ty(&mut self, ty: &clang::Type) -> Option<TypeId> {
1969 use clang_sys::*;
1970 let type_kind = match ty.kind() {
1971 CXType_NullPtr => TypeKind::NullPtr,
1972 CXType_Void => TypeKind::Void,
1973 CXType_Bool => TypeKind::Int(IntKind::Bool),
1974 CXType_Int => TypeKind::Int(IntKind::Int),
1975 CXType_UInt => TypeKind::Int(IntKind::UInt),
1976 CXType_Char_S => TypeKind::Int(IntKind::Char { is_signed: true }),
1977 CXType_Char_U => TypeKind::Int(IntKind::Char { is_signed: false }),
1978 CXType_SChar => TypeKind::Int(IntKind::SChar),
1979 CXType_UChar => TypeKind::Int(IntKind::UChar),
1980 CXType_Short => TypeKind::Int(IntKind::Short),
1981 CXType_UShort => TypeKind::Int(IntKind::UShort),
1982 CXType_WChar => TypeKind::Int(IntKind::WChar),
1983 CXType_Char16 if self.options().use_distinct_char16_t => {
1984 TypeKind::Int(IntKind::Char16)
1985 }
1986 CXType_Char16 => TypeKind::Int(IntKind::U16),
1987 CXType_Char32 => TypeKind::Int(IntKind::U32),
1988 CXType_Long => TypeKind::Int(IntKind::Long),
1989 CXType_ULong => TypeKind::Int(IntKind::ULong),
1990 CXType_LongLong => TypeKind::Int(IntKind::LongLong),
1991 CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
1992 CXType_Int128 => TypeKind::Int(IntKind::I128),
1993 CXType_UInt128 => TypeKind::Int(IntKind::U128),
1994 CXType_Float16 | CXType_Half => TypeKind::Float(FloatKind::Float16),
1995 CXType_Float => TypeKind::Float(FloatKind::Float),
1996 CXType_Double => TypeKind::Float(FloatKind::Double),
1997 CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
1998 CXType_Float128 => TypeKind::Float(FloatKind::Float128),
1999 CXType_Complex => {
2000 let float_type =
2001 ty.elem_type().expect("Not able to resolve complex type?");
2002 let float_kind = match float_type.kind() {
2003 CXType_Float16 | CXType_Half => FloatKind::Float16,
2004 CXType_Float => FloatKind::Float,
2005 CXType_Double => FloatKind::Double,
2006 CXType_LongDouble => FloatKind::LongDouble,
2007 CXType_Float128 => FloatKind::Float128,
2008 _ => panic!(
2009 "Non floating-type complex? {ty:?}, {float_type:?}",
2010 ),
2011 };
2012 TypeKind::Complex(float_kind)
2013 }
2014 _ => return None,
2015 };
2016
2017 let spelling = ty.spelling();
2018 let is_const = ty.is_const();
2019 let layout = ty.fallible_layout(self).ok();
2020 let location = ty.declaration().location();
2021 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
2022 let id = self.next_item_id();
2023 let item = Item::new(
2024 id,
2025 None,
2026 None,
2027 self.root_module.into(),
2028 ItemKind::Type(ty),
2029 Some(location),
2030 );
2031 self.add_builtin_item(item);
2032 Some(id.as_type_id_unchecked())
2033 }
2034
2035 pub(crate) fn translation_unit(&self) -> &clang::TranslationUnit {
2037 &self.translation_unit
2038 }
2039
2040 pub(crate) fn try_ensure_fallback_translation_unit(
2043 &mut self,
2044 ) -> Option<&mut clang::FallbackTranslationUnit> {
2045 if self.fallback_tu.is_none() {
2046 let file = format!(
2047 "{}/.macro_eval.c",
2048 match self.options().clang_macro_fallback_build_dir {
2049 Some(ref path) => path.as_os_str().to_str()?,
2050 None => ".",
2051 }
2052 );
2053
2054 let index = clang::Index::new(false, false);
2055
2056 let mut header_names_to_compile = Vec::new();
2057 let mut header_paths = Vec::new();
2058 let mut header_includes = Vec::new();
2059 let single_header = self.options().input_headers.last().cloned()?;
2060 for input_header in &self.options.input_headers
2061 [..self.options.input_headers.len() - 1]
2062 {
2063 let path = Path::new(input_header.as_ref());
2064 if let Some(header_path) = path.parent() {
2065 if header_path == Path::new("") {
2066 header_paths.push(".");
2067 } else {
2068 header_paths.push(header_path.as_os_str().to_str()?);
2069 }
2070 } else {
2071 header_paths.push(".");
2072 }
2073 let header_name = path.file_name()?.to_str()?;
2074 header_includes.push(header_name.to_string());
2075 header_names_to_compile
2076 .push(header_name.split(".h").next()?.to_string());
2077 }
2078 let pch = format!(
2079 "{}/{}",
2080 match self.options().clang_macro_fallback_build_dir {
2081 Some(ref path) => path.as_os_str().to_str()?,
2082 None => ".",
2083 },
2084 header_names_to_compile.join("-") + "-precompile.h.pch"
2085 );
2086
2087 let mut c_args = self.options.fallback_clang_args.clone();
2088 c_args.push("-x".to_string().into_boxed_str());
2089 c_args.push("c-header".to_string().into_boxed_str());
2090 for header_path in header_paths {
2091 c_args.push(format!("-I{header_path}").into_boxed_str());
2092 }
2093 for header_include in header_includes {
2094 c_args.push("-include".to_string().into_boxed_str());
2095 c_args.push(header_include.into_boxed_str());
2096 }
2097 let mut tu = clang::TranslationUnit::parse(
2098 &index,
2099 &single_header,
2100 &c_args,
2101 &[],
2102 clang_sys::CXTranslationUnit_ForSerialization,
2103 )?;
2104 tu.save(&pch).ok()?;
2105
2106 let mut c_args = vec![
2107 "-include-pch".to_string().into_boxed_str(),
2108 pch.clone().into_boxed_str(),
2109 ];
2110 let mut skip_next = false;
2111 for arg in &self.options.fallback_clang_args {
2112 if arg.as_ref() == "-include" {
2113 skip_next = true;
2114 } else if skip_next {
2115 skip_next = false;
2116 } else {
2117 c_args.push(arg.clone());
2118 }
2119 }
2120 self.fallback_tu =
2121 Some(clang::FallbackTranslationUnit::new(file, pch, &c_args)?);
2122 }
2123
2124 self.fallback_tu.as_mut()
2125 }
2126
2127 pub(crate) fn parsed_macro(&self, macro_name: &[u8]) -> bool {
2129 self.parsed_macros.contains_key(macro_name)
2130 }
2131
2132 pub(crate) fn parsed_macros(
2134 &self,
2135 ) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult> {
2136 debug_assert!(!self.in_codegen_phase());
2137 &self.parsed_macros
2138 }
2139
2140 pub(crate) fn note_parsed_macro(
2142 &mut self,
2143 id: Vec<u8>,
2144 value: cexpr::expr::EvalResult,
2145 ) {
2146 self.parsed_macros.insert(id, value);
2147 }
2148
2149 pub(crate) fn in_codegen_phase(&self) -> bool {
2151 self.in_codegen
2152 }
2153
2154 pub(crate) fn replace(&mut self, name: &[String], potential_ty: ItemId) {
2160 match self.replacements.entry(name.into()) {
2161 Entry::Vacant(entry) => {
2162 debug!("Defining replacement for {name:?} as {potential_ty:?}");
2163 entry.insert(potential_ty);
2164 }
2165 Entry::Occupied(occupied) => {
2166 warn!(
2167 "Replacement for {name:?} already defined as {:?}; \
2168 ignoring duplicate replacement definition as {potential_ty:?}",
2169 occupied.get(),
2170 );
2171 }
2172 }
2173 }
2174
2175 pub(crate) fn is_replaced_type<Id: Into<ItemId>>(
2178 &self,
2179 path: &[String],
2180 id: Id,
2181 ) -> bool {
2182 let id = id.into();
2183 matches!(self.replacements.get(path), Some(replaced_by) if *replaced_by != id)
2184 }
2185
2186 pub(crate) fn opaque_by_name(&self, path: &[String]) -> bool {
2188 debug_assert!(
2189 self.in_codegen_phase(),
2190 "You're not supposed to call this yet"
2191 );
2192 self.options.opaque_types.matches(path[1..].join("::"))
2193 }
2194
2195 pub(crate) fn options(&self) -> &BindgenOptions {
2197 &self.options
2198 }
2199
2200 fn tokenize_namespace(
2203 &self,
2204 cursor: &Cursor,
2205 ) -> (Option<String>, ModuleKind) {
2206 assert_eq!(
2207 cursor.kind(),
2208 ::clang_sys::CXCursor_Namespace,
2209 "Be a nice person"
2210 );
2211
2212 let mut module_name = None;
2213 let spelling = cursor.spelling();
2214 if !spelling.is_empty() {
2215 module_name = Some(spelling);
2216 }
2217
2218 let mut kind = ModuleKind::Normal;
2219 let mut looking_for_name = false;
2220 for token in cursor.tokens().iter() {
2221 match token.spelling() {
2222 b"inline" => {
2223 debug_assert!(
2224 kind != ModuleKind::Inline,
2225 "Multiple inline keywords?"
2226 );
2227 kind = ModuleKind::Inline;
2228 looking_for_name = true;
2231 }
2232 b"namespace" | b"::" => {
2240 looking_for_name = true;
2241 }
2242 b"{" => {
2243 assert!(looking_for_name);
2245 break;
2246 }
2247 name => {
2248 if looking_for_name {
2249 if module_name.is_none() {
2250 module_name = Some(
2251 String::from_utf8_lossy(name).into_owned(),
2252 );
2253 }
2254 break;
2255 }
2256 warn!("Ignored unknown namespace prefix '{}' at {token:?} in {cursor:?}", String::from_utf8_lossy(name));
2266 }
2267 }
2268 }
2269
2270 if cursor.is_inline_namespace() {
2271 kind = ModuleKind::Inline;
2272 }
2273
2274 (module_name, kind)
2275 }
2276
2277 pub(crate) fn module(&mut self, cursor: Cursor) -> ModuleId {
2280 use clang_sys::*;
2281 assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person");
2282 let cursor = cursor.canonical();
2283 if let Some(id) = self.modules.get(&cursor) {
2284 return *id;
2285 }
2286
2287 let (module_name, kind) = self.tokenize_namespace(&cursor);
2288
2289 let module_id = self.next_item_id();
2290 let module = Module::new(module_name, kind);
2291 let module = Item::new(
2292 module_id,
2293 None,
2294 None,
2295 self.current_module.into(),
2296 ItemKind::Module(module),
2297 Some(cursor.location()),
2298 );
2299
2300 let module_id = module.id().as_module_id_unchecked();
2301 self.modules.insert(cursor, module_id);
2302
2303 self.add_item(module, None, None);
2304
2305 module_id
2306 }
2307
2308 pub(crate) fn with_module<F>(&mut self, module_id: ModuleId, cb: F)
2311 where
2312 F: FnOnce(&mut Self),
2313 {
2314 debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat");
2315
2316 let previous_id = self.current_module;
2317 self.current_module = module_id;
2318
2319 cb(self);
2320
2321 self.current_module = previous_id;
2322 }
2323
2324 pub(crate) fn allowlisted_items(&self) -> &ItemSet {
2329 assert!(self.in_codegen_phase());
2330 assert_eq!(self.current_module, self.root_module);
2331
2332 self.allowlisted.as_ref().unwrap()
2333 }
2334
2335 pub(crate) fn blocklisted_type_implements_trait(
2338 &self,
2339 item: &Item,
2340 derive_trait: DeriveTrait,
2341 ) -> CanDerive {
2342 assert!(self.in_codegen_phase());
2343 assert_eq!(self.current_module, self.root_module);
2344
2345 *self
2346 .blocklisted_types_implement_traits
2347 .borrow_mut()
2348 .entry(derive_trait)
2349 .or_default()
2350 .entry(item.id())
2351 .or_insert_with(|| {
2352 item.expect_type()
2353 .name()
2354 .and_then(|name| {
2355 if self.options.parse_callbacks.is_empty() {
2356 if self.is_stdint_type(name) {
2360 Some(CanDerive::Yes)
2361 } else {
2362 Some(CanDerive::No)
2363 }
2364 } else {
2365 self.options.last_callback(|cb| {
2366 cb.blocklisted_type_implements_trait(
2367 name,
2368 derive_trait,
2369 )
2370 })
2371 }
2372 })
2373 .unwrap_or(CanDerive::No)
2374 })
2375 }
2376
2377 pub(crate) fn is_stdint_type(&self, name: &str) -> bool {
2379 match name {
2380 "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" |
2381 "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" |
2382 "intptr_t" | "ptrdiff_t" => true,
2383 "size_t" | "ssize_t" => self.options.size_t_is_usize,
2384 _ => false,
2385 }
2386 }
2387
2388 pub(crate) fn codegen_items(&self) -> &ItemSet {
2390 assert!(self.in_codegen_phase());
2391 assert_eq!(self.current_module, self.root_module);
2392 self.codegen_items.as_ref().unwrap()
2393 }
2394
2395 fn compute_allowlisted_and_codegen_items(&mut self) {
2397 assert!(self.in_codegen_phase());
2398 assert_eq!(self.current_module, self.root_module);
2399 assert!(self.allowlisted.is_none());
2400 let _t = self.timer("compute_allowlisted_and_codegen_items");
2401
2402 let roots = {
2403 let mut roots = self
2404 .items()
2405 .filter(|&(_, item)| item.is_enabled_for_codegen(self))
2407 .filter(|&(_, item)| {
2408 if self.options().allowlisted_types.is_empty() &&
2411 self.options().allowlisted_functions.is_empty() &&
2412 self.options().allowlisted_vars.is_empty() &&
2413 self.options().allowlisted_files.is_empty() &&
2414 self.options().allowlisted_items.is_empty()
2415 {
2416 return true;
2417 }
2418
2419 if item.annotations().use_instead_of().is_some() {
2422 return true;
2423 }
2424
2425 if !self.options().allowlisted_files.is_empty() {
2428 if let Some(location) = item.location() {
2429 let (file, _, _, _) = location.location();
2430 if let Some(filename) = file.name() {
2431 if self
2432 .options()
2433 .allowlisted_files
2434 .matches(filename)
2435 {
2436 return true;
2437 }
2438 }
2439 }
2440 }
2441
2442 let name = item.path_for_allowlisting(self)[1..].join("::");
2443 debug!("allowlisted_items: testing {name:?}");
2444
2445 if self.options().allowlisted_items.matches(&name) {
2446 return true;
2447 }
2448
2449 match *item.kind() {
2450 ItemKind::Module(..) => true,
2451 ItemKind::Function(_) => {
2452 self.options().allowlisted_functions.matches(&name)
2453 }
2454 ItemKind::Var(_) => {
2455 self.options().allowlisted_vars.matches(&name)
2456 }
2457 ItemKind::Type(ref ty) => {
2458 if self.options().allowlisted_types.matches(&name) {
2459 return true;
2460 }
2461
2462 if !self.options().allowlist_recursively {
2466 match *ty.kind() {
2467 TypeKind::Void |
2468 TypeKind::NullPtr |
2469 TypeKind::Int(..) |
2470 TypeKind::Float(..) |
2471 TypeKind::Complex(..) |
2472 TypeKind::Array(..) |
2473 TypeKind::Vector(..) |
2474 TypeKind::Pointer(..) |
2475 TypeKind::Reference(..) |
2476 TypeKind::Function(..) |
2477 TypeKind::ResolvedTypeRef(..) |
2478 TypeKind::Opaque |
2479 TypeKind::TypeParam => return true,
2480 _ => {}
2481 }
2482 if self.is_stdint_type(&name) {
2483 return true;
2484 }
2485 }
2486
2487 let parent = self.resolve_item(item.parent_id());
2493 if !parent.is_module() {
2494 return false;
2495 }
2496
2497 let TypeKind::Enum(ref enum_) = *ty.kind() else {
2498 return false;
2499 };
2500
2501 if ty.name().is_some() {
2502 return false;
2503 }
2504
2505 let mut prefix_path =
2506 parent.path_for_allowlisting(self).clone();
2507 enum_.variants().iter().any(|variant| {
2508 prefix_path.push(
2509 variant.name_for_allowlisting().into(),
2510 );
2511 let name = prefix_path[1..].join("::");
2512 prefix_path.pop().unwrap();
2513 self.options().allowlisted_vars.matches(&name)
2514 || self
2515 .options()
2516 .allowlisted_items
2517 .matches(name)
2518 })
2519 }
2520 }
2521 })
2522 .map(|(id, _)| id)
2523 .collect::<Vec<_>>();
2524
2525 roots.reverse();
2529 roots
2530 };
2531
2532 let allowlisted_items_predicate =
2533 if self.options().allowlist_recursively {
2534 traversal::all_edges
2535 } else {
2536 traversal::only_inner_type_edges
2541 };
2542
2543 let allowlisted = AllowlistedItemsTraversal::new(
2544 self,
2545 roots.clone(),
2546 allowlisted_items_predicate,
2547 )
2548 .collect::<ItemSet>();
2549
2550 let codegen_items = if self.options().allowlist_recursively {
2551 AllowlistedItemsTraversal::new(
2552 self,
2553 roots,
2554 traversal::codegen_edges,
2555 )
2556 .collect::<ItemSet>()
2557 } else {
2558 allowlisted.clone()
2559 };
2560
2561 self.allowlisted = Some(allowlisted);
2562 self.codegen_items = Some(codegen_items);
2563
2564 for item in self.options().allowlisted_functions.unmatched_items() {
2565 unused_regex_diagnostic(item, "--allowlist-function", self);
2566 }
2567
2568 for item in self.options().allowlisted_vars.unmatched_items() {
2569 unused_regex_diagnostic(item, "--allowlist-var", self);
2570 }
2571
2572 for item in self.options().allowlisted_types.unmatched_items() {
2573 unused_regex_diagnostic(item, "--allowlist-type", self);
2574 }
2575
2576 for item in self.options().allowlisted_items.unmatched_items() {
2577 unused_regex_diagnostic(item, "--allowlist-items", self);
2578 }
2579 }
2580
2581 pub(crate) fn trait_prefix(&self) -> Ident {
2584 if self.options().use_core {
2585 self.rust_ident_raw("core")
2586 } else {
2587 self.rust_ident_raw("std")
2588 }
2589 }
2590
2591 pub(crate) fn generated_opaque_array(&self) {
2593 self.generated_opaque_array.set(true);
2594 }
2595
2596 pub(crate) fn need_opaque_array_type(&self) -> bool {
2598 self.generated_opaque_array.get()
2599 }
2600
2601 pub(crate) fn generated_bindgen_complex(&self) {
2603 self.generated_bindgen_complex.set(true);
2604 }
2605
2606 pub(crate) fn need_bindgen_complex_type(&self) -> bool {
2608 self.generated_bindgen_complex.get()
2609 }
2610
2611 pub(crate) fn generated_bindgen_float16(&self) {
2613 self.generated_bindgen_float16.set(true);
2614 }
2615
2616 pub(crate) fn need_bindgen_float16_type(&self) -> bool {
2618 self.generated_bindgen_float16.get()
2619 }
2620
2621 fn compute_enum_typedef_combos(&mut self) {
2623 let _t = self.timer("compute_enum_typedef_combos");
2624 assert!(self.enum_typedef_combos.is_none());
2625
2626 let mut enum_typedef_combos = HashSet::default();
2627 for item in &self.items {
2628 if let Some(ItemKind::Module(module)) =
2629 item.as_ref().map(Item::kind)
2630 {
2631 let mut names_of_typedefs = HashSet::default();
2633 for child_id in module.children() {
2634 if let Some(ItemKind::Type(ty)) =
2635 self.items[child_id.0].as_ref().map(Item::kind)
2636 {
2637 if let (Some(name), TypeKind::Alias(type_id)) =
2638 (ty.name(), ty.kind())
2639 {
2640 if type_id
2643 .into_resolver()
2644 .through_type_refs()
2645 .through_type_aliases()
2646 .resolve(self)
2647 .expect_type()
2648 .is_int()
2649 {
2650 names_of_typedefs.insert(name);
2651 }
2652 }
2653 }
2654 }
2655
2656 for child_id in module.children() {
2659 if let Some(ItemKind::Type(ty)) =
2660 self.items[child_id.0].as_ref().map(Item::kind)
2661 {
2662 if let (Some(name), true) = (ty.name(), ty.is_enum()) {
2663 if names_of_typedefs.contains(name) {
2664 enum_typedef_combos.insert(*child_id);
2665 }
2666 }
2667 }
2668 }
2669 }
2670 }
2671
2672 self.enum_typedef_combos = Some(enum_typedef_combos);
2673 }
2674
2675 pub(crate) fn is_enum_typedef_combo(&self, id: ItemId) -> bool {
2678 assert!(
2679 self.in_codegen_phase(),
2680 "We only compute enum_typedef_combos when we enter codegen",
2681 );
2682 self.enum_typedef_combos.as_ref().unwrap().contains(&id)
2683 }
2684
2685 fn compute_cannot_derive_debug(&mut self) {
2687 let _t = self.timer("compute_cannot_derive_debug");
2688 assert!(self.cannot_derive_debug.is_none());
2689 if self.options.derive_debug {
2690 self.cannot_derive_debug =
2691 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2692 self,
2693 DeriveTrait::Debug,
2694 ))));
2695 }
2696 }
2697
2698 pub(crate) fn lookup_can_derive_debug<Id: Into<ItemId>>(
2701 &self,
2702 id: Id,
2703 ) -> bool {
2704 let id = id.into();
2705 assert!(
2706 self.in_codegen_phase(),
2707 "We only compute can_derive_debug when we enter codegen"
2708 );
2709
2710 !self.cannot_derive_debug.as_ref().unwrap().contains(&id)
2713 }
2714
2715 fn compute_cannot_derive_default(&mut self) {
2717 let _t = self.timer("compute_cannot_derive_default");
2718 assert!(self.cannot_derive_default.is_none());
2719 if self.options.derive_default {
2720 self.cannot_derive_default =
2721 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2722 self,
2723 DeriveTrait::Default,
2724 ))));
2725 }
2726 }
2727
2728 pub(crate) fn lookup_can_derive_default<Id: Into<ItemId>>(
2731 &self,
2732 id: Id,
2733 ) -> bool {
2734 let id = id.into();
2735 assert!(
2736 self.in_codegen_phase(),
2737 "We only compute can_derive_default when we enter codegen"
2738 );
2739
2740 !self.cannot_derive_default.as_ref().unwrap().contains(&id)
2743 }
2744
2745 fn compute_cannot_derive_copy(&mut self) {
2747 let _t = self.timer("compute_cannot_derive_copy");
2748 assert!(self.cannot_derive_copy.is_none());
2749 self.cannot_derive_copy =
2750 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2751 self,
2752 DeriveTrait::Copy,
2753 ))));
2754 }
2755
2756 fn compute_cannot_derive_hash(&mut self) {
2758 let _t = self.timer("compute_cannot_derive_hash");
2759 assert!(self.cannot_derive_hash.is_none());
2760 if self.options.derive_hash {
2761 self.cannot_derive_hash =
2762 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2763 self,
2764 DeriveTrait::Hash,
2765 ))));
2766 }
2767 }
2768
2769 pub(crate) fn lookup_can_derive_hash<Id: Into<ItemId>>(
2772 &self,
2773 id: Id,
2774 ) -> bool {
2775 let id = id.into();
2776 assert!(
2777 self.in_codegen_phase(),
2778 "We only compute can_derive_debug when we enter codegen"
2779 );
2780
2781 !self.cannot_derive_hash.as_ref().unwrap().contains(&id)
2784 }
2785
2786 fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) {
2788 let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq");
2789 assert!(self.cannot_derive_partialeq_or_partialord.is_none());
2790 if self.options.derive_partialord ||
2791 self.options.derive_partialeq ||
2792 self.options.derive_eq
2793 {
2794 self.cannot_derive_partialeq_or_partialord =
2795 Some(analyze::<CannotDerive>((
2796 self,
2797 DeriveTrait::PartialEqOrPartialOrd,
2798 )));
2799 }
2800 }
2801
2802 pub(crate) fn lookup_can_derive_partialeq_or_partialord<
2804 Id: Into<ItemId>,
2805 >(
2806 &self,
2807 id: Id,
2808 ) -> CanDerive {
2809 let id = id.into();
2810 assert!(
2811 self.in_codegen_phase(),
2812 "We only compute can_derive_partialeq_or_partialord when we enter codegen"
2813 );
2814
2815 self.cannot_derive_partialeq_or_partialord
2818 .as_ref()
2819 .unwrap()
2820 .get(&id)
2821 .copied()
2822 .unwrap_or(CanDerive::Yes)
2823 }
2824
2825 pub(crate) fn lookup_can_derive_copy<Id: Into<ItemId>>(
2827 &self,
2828 id: Id,
2829 ) -> bool {
2830 assert!(
2831 self.in_codegen_phase(),
2832 "We only compute can_derive_debug when we enter codegen"
2833 );
2834
2835 let id = id.into();
2838
2839 !self.lookup_has_type_param_in_array(id) &&
2840 !self.cannot_derive_copy.as_ref().unwrap().contains(&id)
2841 }
2842
2843 fn compute_has_type_param_in_array(&mut self) {
2845 let _t = self.timer("compute_has_type_param_in_array");
2846 assert!(self.has_type_param_in_array.is_none());
2847 self.has_type_param_in_array =
2848 Some(analyze::<HasTypeParameterInArray>(self));
2849 }
2850
2851 pub(crate) fn lookup_has_type_param_in_array<Id: Into<ItemId>>(
2853 &self,
2854 id: Id,
2855 ) -> bool {
2856 assert!(
2857 self.in_codegen_phase(),
2858 "We only compute has array when we enter codegen"
2859 );
2860
2861 self.has_type_param_in_array
2864 .as_ref()
2865 .unwrap()
2866 .contains(&id.into())
2867 }
2868
2869 fn compute_has_float(&mut self) {
2871 let _t = self.timer("compute_has_float");
2872 assert!(self.has_float.is_none());
2873 if self.options.derive_eq || self.options.derive_ord {
2874 self.has_float = Some(analyze::<HasFloat>(self));
2875 }
2876 }
2877
2878 pub(crate) fn lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool {
2880 assert!(
2881 self.in_codegen_phase(),
2882 "We only compute has float when we enter codegen"
2883 );
2884
2885 self.has_float.as_ref().unwrap().contains(&id.into())
2888 }
2889
2890 pub(crate) fn no_partialeq_by_name(&self, item: &Item) -> bool {
2892 let name = item.path_for_allowlisting(self)[1..].join("::");
2893 self.options().no_partialeq_types.matches(name)
2894 }
2895
2896 pub(crate) fn no_copy_by_name(&self, item: &Item) -> bool {
2898 let name = item.path_for_allowlisting(self)[1..].join("::");
2899 self.options().no_copy_types.matches(name)
2900 }
2901
2902 pub(crate) fn no_debug_by_name(&self, item: &Item) -> bool {
2904 let name = item.path_for_allowlisting(self)[1..].join("::");
2905 self.options().no_debug_types.matches(name)
2906 }
2907
2908 pub(crate) fn no_default_by_name(&self, item: &Item) -> bool {
2910 let name = item.path_for_allowlisting(self)[1..].join("::");
2911 self.options().no_default_types.matches(name)
2912 }
2913
2914 pub(crate) fn no_hash_by_name(&self, item: &Item) -> bool {
2916 let name = item.path_for_allowlisting(self)[1..].join("::");
2917 self.options().no_hash_types.matches(name)
2918 }
2919
2920 pub(crate) fn must_use_type_by_name(&self, item: &Item) -> bool {
2922 let name = item.path_for_allowlisting(self)[1..].join("::");
2923 self.options().must_use_types.matches(name)
2924 }
2925
2926 pub(crate) fn wrap_unsafe_ops(&self, tokens: impl ToTokens) -> TokenStream {
2928 if self.options.wrap_unsafe_ops {
2929 quote!(unsafe { #tokens })
2930 } else {
2931 tokens.into_token_stream()
2932 }
2933 }
2934
2935 pub(crate) fn wrap_static_fns_suffix(&self) -> &str {
2938 self.options()
2939 .wrap_static_fns_suffix
2940 .as_deref()
2941 .unwrap_or(crate::DEFAULT_NON_EXTERN_FNS_SUFFIX)
2942 }
2943}
2944
2945#[derive(Debug, Copy, Clone)]
2947pub(crate) struct ItemResolver {
2948 id: ItemId,
2949 through_type_refs: bool,
2950 through_type_aliases: bool,
2951}
2952
2953impl ItemId {
2954 pub(crate) fn into_resolver(self) -> ItemResolver {
2956 self.into()
2957 }
2958}
2959
2960impl<T> From<T> for ItemResolver
2961where
2962 T: Into<ItemId>,
2963{
2964 fn from(id: T) -> ItemResolver {
2965 ItemResolver::new(id)
2966 }
2967}
2968
2969impl ItemResolver {
2970 pub(crate) fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
2972 let id = id.into();
2973 ItemResolver {
2974 id,
2975 through_type_refs: false,
2976 through_type_aliases: false,
2977 }
2978 }
2979
2980 pub(crate) fn through_type_refs(mut self) -> ItemResolver {
2982 self.through_type_refs = true;
2983 self
2984 }
2985
2986 pub(crate) fn through_type_aliases(mut self) -> ItemResolver {
2988 self.through_type_aliases = true;
2989 self
2990 }
2991
2992 pub(crate) fn resolve(self, ctx: &BindgenContext) -> &Item {
2994 assert!(ctx.collected_typerefs());
2995
2996 let mut id = self.id;
2997 let mut seen_ids = HashSet::default();
2998 loop {
2999 let item = ctx.resolve_item(id);
3000
3001 if !seen_ids.insert(id) {
3004 return item;
3005 }
3006
3007 let ty_kind = item.as_type().map(|t| t.kind());
3008 match ty_kind {
3009 Some(&TypeKind::ResolvedTypeRef(next_id))
3010 if self.through_type_refs =>
3011 {
3012 id = next_id.into();
3013 }
3014 Some(&TypeKind::Alias(next_id))
3018 if self.through_type_aliases =>
3019 {
3020 id = next_id.into();
3021 }
3022 _ => return item,
3023 }
3024 }
3025 }
3026}
3027
3028#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3030pub(crate) struct PartialType {
3031 decl: Cursor,
3032 id: ItemId,
3035}
3036
3037impl PartialType {
3038 pub(crate) fn new(decl: Cursor, id: ItemId) -> PartialType {
3040 PartialType { decl, id }
3042 }
3043
3044 pub(crate) fn decl(&self) -> &Cursor {
3046 &self.decl
3047 }
3048
3049 pub(crate) fn id(&self) -> ItemId {
3052 self.id
3053 }
3054}
3055
3056impl TemplateParameters for PartialType {
3057 fn self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId> {
3058 vec![]
3061 }
3062
3063 fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize {
3064 match self.decl().kind() {
3067 clang_sys::CXCursor_ClassTemplate |
3068 clang_sys::CXCursor_FunctionTemplate |
3069 clang_sys::CXCursor_TypeAliasTemplateDecl => {
3070 let mut num_params = 0;
3071 self.decl().visit(|c| {
3072 match c.kind() {
3073 clang_sys::CXCursor_TemplateTypeParameter |
3074 clang_sys::CXCursor_TemplateTemplateParameter |
3075 clang_sys::CXCursor_NonTypeTemplateParameter => {
3076 num_params += 1;
3077 }
3078 _ => {}
3079 }
3080 clang_sys::CXChildVisit_Continue
3081 });
3082 num_params
3083 }
3084 _ => 0,
3085 }
3086 }
3087}
3088
3089fn unused_regex_diagnostic(item: &str, name: &str, _ctx: &BindgenContext) {
3090 warn!("unused option: {name} {item}");
3091
3092 #[cfg(feature = "experimental")]
3093 if _ctx.options().emit_diagnostics {
3094 use crate::diagnostics::{Diagnostic, Level};
3095
3096 Diagnostic::default()
3097 .with_title(
3098 format!("Unused regular expression: `{item}`."),
3099 Level::Warning,
3100 )
3101 .add_annotation(
3102 format!("This regular expression was passed to `{name}`."),
3103 Level::Note,
3104 )
3105 .display();
3106 }
3107}