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::fs::OpenOptions;
33use std::io::Write;
34use std::mem;
35use std::path::Path;
36
37#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
39pub(crate) struct ItemId(usize);
40
41macro_rules! item_id_newtype {
43 (
44 $( #[$attr:meta] )*
45 pub(crate) struct $name:ident(ItemId)
46 where
47 $( #[$checked_attr:meta] )*
48 checked = $checked:ident with $check_method:ident,
49 $( #[$expected_attr:meta] )*
50 expected = $expected:ident,
51 $( #[$unchecked_attr:meta] )*
52 unchecked = $unchecked:ident;
53 ) => {
54 $( #[$attr] )*
55 #[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
56 pub(crate) struct $name(ItemId);
57
58 impl $name {
59 #[allow(dead_code)]
61 pub(crate) fn into_resolver(self) -> ItemResolver {
62 let id: ItemId = self.into();
63 id.into()
64 }
65 }
66
67 impl<T> ::std::cmp::PartialEq<T> for $name
68 where
69 T: Copy + Into<ItemId>
70 {
71 fn eq(&self, rhs: &T) -> bool {
72 let rhs: ItemId = (*rhs).into();
73 self.0 == rhs
74 }
75 }
76
77 impl From<$name> for ItemId {
78 fn from(id: $name) -> ItemId {
79 id.0
80 }
81 }
82
83 impl<'a> From<&'a $name> for ItemId {
84 fn from(id: &'a $name) -> ItemId {
85 id.0
86 }
87 }
88
89 #[allow(dead_code)]
90 impl ItemId {
91 $( #[$checked_attr] )*
92 pub(crate) fn $checked(&self, ctx: &BindgenContext) -> Option<$name> {
93 if ctx.resolve_item(*self).kind().$check_method() {
94 Some($name(*self))
95 } else {
96 None
97 }
98 }
99
100 $( #[$expected_attr] )*
101 pub(crate) fn $expected(&self, ctx: &BindgenContext) -> $name {
102 self.$checked(ctx)
103 .expect(concat!(
104 stringify!($expected),
105 " called with ItemId that points to the wrong ItemKind"
106 ))
107 }
108
109 $( #[$unchecked_attr] )*
110 pub(crate) fn $unchecked(&self) -> $name {
111 $name(*self)
112 }
113 }
114 }
115}
116
117item_id_newtype! {
118 pub(crate) struct TypeId(ItemId)
121 where
122 checked = as_type_id with is_type,
125
126 expected = expect_type_id,
130
131 unchecked = as_type_id_unchecked;
134}
135
136item_id_newtype! {
137 pub(crate) struct ModuleId(ItemId)
140 where
141 checked = as_module_id with is_module,
144
145 expected = expect_module_id,
149
150 unchecked = as_module_id_unchecked;
153}
154
155item_id_newtype! {
156 pub(crate) struct VarId(ItemId)
159 where
160 checked = as_var_id with is_var,
163
164 expected = expect_var_id,
168
169 unchecked = as_var_id_unchecked;
172}
173
174item_id_newtype! {
175 pub(crate) struct FunctionId(ItemId)
178 where
179 checked = as_function_id with is_function,
182
183 expected = expect_function_id,
187
188 unchecked = as_function_id_unchecked;
191}
192
193impl From<ItemId> for usize {
194 fn from(id: ItemId) -> usize {
195 id.0
196 }
197}
198
199impl ItemId {
200 pub(crate) fn as_usize(&self) -> usize {
202 (*self).into()
203 }
204}
205
206impl<T> ::std::cmp::PartialEq<T> for ItemId
207where
208 T: Copy + Into<ItemId>,
209{
210 fn eq(&self, rhs: &T) -> bool {
211 let rhs: ItemId = (*rhs).into();
212 self.0 == rhs.0
213 }
214}
215
216impl<T> CanDeriveDebug for T
217where
218 T: Copy + Into<ItemId>,
219{
220 fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
221 ctx.options().derive_debug && ctx.lookup_can_derive_debug(*self)
222 }
223}
224
225impl<T> CanDeriveDefault for T
226where
227 T: Copy + Into<ItemId>,
228{
229 fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
230 ctx.options().derive_default && ctx.lookup_can_derive_default(*self)
231 }
232}
233
234impl<T> CanDeriveCopy for T
235where
236 T: Copy + Into<ItemId>,
237{
238 fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
239 ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self)
240 }
241}
242
243impl<T> CanDeriveHash for T
244where
245 T: Copy + Into<ItemId>,
246{
247 fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
248 ctx.options().derive_hash && ctx.lookup_can_derive_hash(*self)
249 }
250}
251
252impl<T> CanDerivePartialOrd for T
253where
254 T: Copy + Into<ItemId>,
255{
256 fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
257 ctx.options().derive_partialord &&
258 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
259 CanDerive::Yes
260 }
261}
262
263impl<T> CanDerivePartialEq for T
264where
265 T: Copy + Into<ItemId>,
266{
267 fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
268 ctx.options().derive_partialeq &&
269 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
270 CanDerive::Yes
271 }
272}
273
274impl<T> CanDeriveEq for T
275where
276 T: Copy + Into<ItemId>,
277{
278 fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
279 ctx.options().derive_eq &&
280 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
281 CanDerive::Yes &&
282 !ctx.lookup_has_float(*self)
283 }
284}
285
286impl<T> CanDeriveOrd for T
287where
288 T: Copy + Into<ItemId>,
289{
290 fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
291 ctx.options().derive_ord &&
292 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
293 CanDerive::Yes &&
294 !ctx.lookup_has_float(*self)
295 }
296}
297
298#[derive(Eq, PartialEq, Hash, Debug)]
305enum TypeKey {
306 Usr(String),
307 Declaration(Cursor),
308}
309
310#[derive(Debug)]
312pub(crate) struct BindgenContext {
313 items: Vec<Option<Item>>,
315
316 types: HashMap<TypeKey, TypeId>,
319
320 type_params: HashMap<Cursor, TypeId>,
323
324 modules: HashMap<Cursor, ModuleId>,
326
327 root_module: ModuleId,
329
330 current_module: ModuleId,
332
333 semantic_parents: HashMap<Cursor, ItemId>,
340
341 currently_parsed_types: Vec<PartialType>,
353
354 parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,
360
361 includes: StdHashMap<String, (String, usize)>,
368
369 deps: BTreeSet<Box<str>>,
371
372 replacements: HashMap<Vec<String>, ItemId>,
374
375 collected_typerefs: bool,
376
377 in_codegen: bool,
378
379 translation_unit: clang::TranslationUnit,
381
382 fallback_tu: Option<clang::FallbackTranslationUnit>,
384
385 target_info: clang::TargetInfo,
387
388 options: BindgenOptions,
390
391 generated_opaque_array: Cell<bool>,
393
394 generated_bindgen_complex: Cell<bool>,
396
397 generated_bindgen_float16: Cell<bool>,
399
400 allowlisted: Option<ItemSet>,
403
404 blocklisted_types_implement_traits:
406 RefCell<HashMap<DeriveTrait, HashMap<ItemId, CanDerive>>>,
407
408 codegen_items: Option<ItemSet>,
413
414 used_template_parameters: Option<HashMap<ItemId, ItemSet>>,
418
419 need_bitfield_allocation: Vec<ItemId>,
422
423 enum_typedef_combos: Option<HashSet<ItemId>>,
438
439 cannot_derive_debug: Option<HashSet<ItemId>>,
444
445 cannot_derive_default: Option<HashSet<ItemId>>,
450
451 cannot_derive_copy: Option<HashSet<ItemId>>,
456
457 cannot_derive_hash: Option<HashSet<ItemId>>,
462
463 cannot_derive_partialeq_or_partialord: Option<HashMap<ItemId, CanDerive>>,
469
470 sizedness: Option<HashMap<TypeId, SizednessResult>>,
475
476 have_vtable: Option<HashMap<ItemId, HasVtableResult>>,
481
482 have_destructor: Option<HashSet<ItemId>>,
487
488 has_type_param_in_array: Option<HashSet<ItemId>>,
493
494 has_float: Option<HashSet<ItemId>>,
499}
500
501struct AllowlistedItemsTraversal<'ctx> {
503 ctx: &'ctx BindgenContext,
504 traversal: ItemTraversal<'ctx, ItemSet, Vec<ItemId>>,
505}
506
507impl Iterator for AllowlistedItemsTraversal<'_> {
508 type Item = ItemId;
509
510 fn next(&mut self) -> Option<ItemId> {
511 loop {
512 let id = self.traversal.next()?;
513
514 if self.ctx.resolve_item(id).is_blocklisted(self.ctx) {
515 continue;
516 }
517
518 return Some(id);
519 }
520 }
521}
522
523impl<'ctx> AllowlistedItemsTraversal<'ctx> {
524 pub(crate) fn new<R>(
526 ctx: &'ctx BindgenContext,
527 roots: R,
528 predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool,
529 ) -> Self
530 where
531 R: IntoIterator<Item = ItemId>,
532 {
533 AllowlistedItemsTraversal {
534 ctx,
535 traversal: ItemTraversal::new(ctx, roots, predicate),
536 }
537 }
538}
539
540impl BindgenContext {
541 pub(crate) fn new(
543 options: BindgenOptions,
544 input_unsaved_files: &[clang::UnsavedFile],
545 ) -> Self {
546 let index = clang::Index::new(false, true);
550
551 let parse_options =
552 clang_sys::CXTranslationUnit_DetailedPreprocessingRecord;
553
554 let translation_unit = {
555 let _t =
556 Timer::new("translation_unit").with_output(options.time_phases);
557
558 clang::TranslationUnit::parse(
559 &index,
560 "",
561 &options.clang_args,
562 input_unsaved_files,
563 parse_options,
564 ).expect("libclang error; possible causes include:
565- Invalid flag syntax
566- Unrecognized flags
567- Invalid flag arguments
568- File I/O errors
569- Host vs. target architecture mismatch
570If you encounter an error missing from this list, please file an issue or a PR!")
571 };
572
573 let target_info = clang::TargetInfo::new(&translation_unit);
574 let root_module = Self::build_root_module(ItemId(0));
575 let root_module_id = root_module.id().as_module_id_unchecked();
576
577 let deps = options.input_headers.iter().cloned().collect();
579
580 BindgenContext {
581 items: vec![Some(root_module)],
582 includes: Default::default(),
583 deps,
584 types: Default::default(),
585 type_params: Default::default(),
586 modules: Default::default(),
587 root_module: root_module_id,
588 current_module: root_module_id,
589 semantic_parents: Default::default(),
590 currently_parsed_types: vec![],
591 parsed_macros: Default::default(),
592 replacements: Default::default(),
593 collected_typerefs: false,
594 in_codegen: false,
595 translation_unit,
596 fallback_tu: None,
597 target_info,
598 options,
599 generated_bindgen_complex: Cell::new(false),
600 generated_bindgen_float16: Cell::new(false),
601 generated_opaque_array: Cell::new(false),
602 allowlisted: None,
603 blocklisted_types_implement_traits: Default::default(),
604 codegen_items: None,
605 used_template_parameters: None,
606 need_bitfield_allocation: Default::default(),
607 enum_typedef_combos: None,
608 cannot_derive_debug: None,
609 cannot_derive_default: None,
610 cannot_derive_copy: None,
611 cannot_derive_hash: None,
612 cannot_derive_partialeq_or_partialord: None,
613 sizedness: None,
614 have_vtable: None,
615 have_destructor: None,
616 has_type_param_in_array: None,
617 has_float: None,
618 }
619 }
620
621 pub(crate) fn is_target_wasm32(&self) -> bool {
623 self.target_info.triple.starts_with("wasm32-")
624 }
625
626 pub(crate) fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
630 Timer::new(name).with_output(self.options.time_phases)
631 }
632
633 pub(crate) fn target_pointer_size(&self) -> usize {
636 self.target_info.pointer_width / 8
637 }
638
639 pub(crate) fn abi_kind(&self) -> ABIKind {
641 self.target_info.abi
642 }
643
644 pub(crate) fn currently_parsed_types(&self) -> &[PartialType] {
647 &self.currently_parsed_types[..]
648 }
649
650 pub(crate) fn begin_parsing(&mut self, partial_ty: PartialType) {
654 self.currently_parsed_types.push(partial_ty);
655 }
656
657 pub(crate) fn finish_parsing(&mut self) -> PartialType {
660 self.currently_parsed_types.pop().expect(
661 "should have been parsing a type, if we finished parsing a type",
662 )
663 }
664
665 pub(crate) fn add_include(
667 &mut self,
668 source_file: String,
669 included_file: String,
670 offset: usize,
671 ) {
672 self.includes
673 .entry(included_file)
674 .or_insert((source_file, offset));
675 }
676
677 pub(crate) fn included_file_location(
679 &self,
680 included_file: &str,
681 ) -> Option<(String, usize)> {
682 self.includes.get(included_file).cloned()
683 }
684
685 pub(crate) fn add_dep(&mut self, dep: Box<str>) {
687 self.deps.insert(dep);
688 }
689
690 pub(crate) fn deps(&self) -> &BTreeSet<Box<str>> {
692 &self.deps
693 }
694
695 pub(crate) fn add_item(
700 &mut self,
701 item: Item,
702 declaration: Option<Cursor>,
703 location: Option<Cursor>,
704 ) {
705 debug!("BindgenContext::add_item({item:?}, declaration: {declaration:?}, loc: {location:?}");
706 debug_assert!(
707 declaration.is_some() ||
708 !item.kind().is_type() ||
709 item.kind().expect_type().is_builtin_or_type_param() ||
710 item.kind().expect_type().is_opaque(self, &item) ||
711 item.kind().expect_type().is_unresolved_ref(),
712 "Adding a type without declaration?"
713 );
714
715 let id = item.id();
716 let is_type = item.kind().is_type();
717 let is_unnamed = is_type && item.expect_type().name().is_none();
718 let is_template_instantiation =
719 is_type && item.expect_type().is_template_instantiation();
720
721 if item.id() != self.root_module {
722 self.add_item_to_module(&item);
723 }
724
725 if is_type && item.expect_type().is_comp() {
726 self.need_bitfield_allocation.push(id);
727 }
728
729 let old_item = mem::replace(&mut self.items[id.0], Some(item));
730 assert!(
731 old_item.is_none(),
732 "should not have already associated an item with the given id"
733 );
734
735 if !is_type || is_template_instantiation {
739 return;
740 }
741 if let Some(mut declaration) = declaration {
742 if !declaration.is_valid() {
743 if let Some(location) = location {
744 if location.is_template_like() {
745 declaration = location;
746 }
747 }
748 }
749 declaration = declaration.canonical();
750 if !declaration.is_valid() {
751 debug!(
757 "Invalid declaration {declaration:?} found for type {:?}",
758 self.resolve_item_fallible(id)
759 .unwrap()
760 .kind()
761 .expect_type()
762 );
763 return;
764 }
765
766 let key = if is_unnamed {
767 TypeKey::Declaration(declaration)
768 } else if let Some(usr) = declaration.usr() {
769 TypeKey::Usr(usr)
770 } else {
771 warn!("Valid declaration with no USR: {declaration:?}, {location:?}");
772 TypeKey::Declaration(declaration)
773 };
774
775 let old = self.types.insert(key, id.as_type_id_unchecked());
776 debug_assert_eq!(old, None);
777 }
778 }
779
780 fn add_item_to_module(&mut self, item: &Item) {
785 assert!(item.id() != self.root_module);
786 assert!(self.resolve_item_fallible(item.id()).is_none());
787
788 if let Some(ref mut parent) = self.items[item.parent_id().0] {
789 if let Some(module) = parent.as_module_mut() {
790 debug!(
791 "add_item_to_module: adding {:?} as child of parent module {:?}",
792 item.id(),
793 item.parent_id()
794 );
795
796 module.children_mut().insert(item.id());
797 return;
798 }
799 }
800
801 debug!(
802 "add_item_to_module: adding {:?} as child of current module {:?}",
803 item.id(),
804 self.current_module
805 );
806
807 self.items[(self.current_module.0).0]
808 .as_mut()
809 .expect("Should always have an item for self.current_module")
810 .as_module_mut()
811 .expect("self.current_module should always be a module")
812 .children_mut()
813 .insert(item.id());
814 }
815
816 pub(crate) fn add_type_param(&mut self, item: Item, definition: Cursor) {
818 debug!("BindgenContext::add_type_param: item = {item:?}; definition = {definition:?}");
819
820 assert!(
821 item.expect_type().is_type_param(),
822 "Should directly be a named type, not a resolved reference or anything"
823 );
824 assert_eq!(
825 definition.kind(),
826 clang_sys::CXCursor_TemplateTypeParameter
827 );
828
829 self.add_item_to_module(&item);
830
831 let id = item.id();
832 let old_item = mem::replace(&mut self.items[id.0], Some(item));
833 assert!(
834 old_item.is_none(),
835 "should not have already associated an item with the given id"
836 );
837
838 let old_named_ty = self
839 .type_params
840 .insert(definition, id.as_type_id_unchecked());
841 assert!(
842 old_named_ty.is_none(),
843 "should not have already associated a named type with this id"
844 );
845 }
846
847 pub(crate) fn get_type_param(&self, definition: &Cursor) -> Option<TypeId> {
850 assert_eq!(
851 definition.kind(),
852 clang_sys::CXCursor_TemplateTypeParameter
853 );
854 self.type_params.get(definition).copied()
855 }
856
857 #[rustfmt::skip]
861 pub(crate) fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
862 if name.contains('@') ||
863 name.contains('?') ||
864 name.contains('$') ||
865 matches!(
866 name,
867 "abstract" | "alignof" | "as" | "async" | "await" | "become" |
868 "box" | "break" | "const" | "continue" | "crate" | "do" |
869 "dyn" | "else" | "enum" | "extern" | "false" | "final" |
870 "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" |
871 "macro" | "match" | "mod" | "move" | "mut" | "offsetof" |
872 "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
873 "return" | "Self" | "self" | "sizeof" | "static" |
874 "struct" | "super" | "trait" | "true" | "try" | "type" | "typeof" |
875 "unsafe" | "unsized" | "use" | "virtual" | "where" |
876 "while" | "yield" | "str" | "bool" | "f32" | "f64" |
877 "usize" | "isize" | "u128" | "i128" | "u64" | "i64" |
878 "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "_"
879 )
880 {
881 let mut s = name.to_owned();
882 s = s.replace('@', "_");
883 s = s.replace('?', "_");
884 s = s.replace('$', "_");
885 s.push('_');
886 return Cow::Owned(s);
887 }
888 Cow::Borrowed(name)
889 }
890
891 pub(crate) fn rust_ident<S>(&self, name: S) -> Ident
893 where
894 S: AsRef<str>,
895 {
896 self.rust_ident_raw(self.rust_mangle(name.as_ref()))
897 }
898
899 pub(crate) fn rust_ident_raw<T>(&self, name: T) -> Ident
901 where
902 T: AsRef<str>,
903 {
904 Ident::new(name.as_ref(), Span::call_site())
905 }
906
907 pub(crate) fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
909 self.items.iter().enumerate().filter_map(|(index, item)| {
910 let item = item.as_ref()?;
911 Some((ItemId(index), item))
912 })
913 }
914
915 pub(crate) fn collected_typerefs(&self) -> bool {
917 self.collected_typerefs
918 }
919
920 fn collect_typerefs(
922 &mut self,
923 ) -> Vec<(ItemId, clang::Type, Cursor, Option<ItemId>)> {
924 debug_assert!(!self.collected_typerefs);
925 self.collected_typerefs = true;
926 let mut typerefs = vec![];
927
928 for (id, item) in self.items() {
929 let kind = item.kind();
930 let Some(ty) = kind.as_type() else { continue };
931
932 if let TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) =
933 *ty.kind()
934 {
935 typerefs.push((id, *ty, loc, parent_id));
936 };
937 }
938 typerefs
939 }
940
941 fn resolve_typerefs(&mut self) {
943 let _t = self.timer("resolve_typerefs");
944
945 let typerefs = self.collect_typerefs();
946
947 for (id, ty, loc, parent_id) in typerefs {
948 let _resolved =
949 {
950 let resolved = Item::from_ty(&ty, loc, parent_id, self)
951 .unwrap_or_else(|_| {
952 warn!("Could not resolve type reference, falling back \
953 to opaque blob");
954 Item::new_opaque_type(self.next_item_id(), &ty, self)
955 });
956
957 let item = self.items[id.0].as_mut().unwrap();
958 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
959 TypeKind::ResolvedTypeRef(resolved);
960 resolved
961 };
962
963 }
972 }
973
974 fn with_loaned_item<F, T>(&mut self, id: ItemId, f: F) -> T
985 where
986 F: (FnOnce(&BindgenContext, &mut Item) -> T),
987 {
988 let mut item = self.items[id.0].take().unwrap();
989
990 let result = f(self, &mut item);
991
992 let existing = mem::replace(&mut self.items[id.0], Some(item));
993 assert!(existing.is_none());
994
995 result
996 }
997
998 fn compute_bitfield_units(&mut self) {
1001 let _t = self.timer("compute_bitfield_units");
1002
1003 assert!(self.collected_typerefs());
1004
1005 let need_bitfield_allocation =
1006 mem::take(&mut self.need_bitfield_allocation);
1007 for id in need_bitfield_allocation {
1008 self.with_loaned_item(id, |ctx, item| {
1009 let ty = item.kind_mut().as_type_mut().unwrap();
1010 let layout = ty.layout(ctx);
1011 ty.as_comp_mut()
1012 .unwrap()
1013 .compute_bitfield_units(ctx, layout.as_ref());
1014 });
1015 }
1016 }
1017
1018 fn deanonymize_fields(&mut self) {
1020 let _t = self.timer("deanonymize_fields");
1021
1022 let comp_item_ids: Vec<ItemId> = self
1023 .items()
1024 .filter_map(|(id, item)| {
1025 if item.kind().as_type()?.is_comp() {
1026 return Some(id);
1027 }
1028 None
1029 })
1030 .collect();
1031
1032 for id in comp_item_ids {
1033 self.with_loaned_item(id, |ctx, item| {
1034 item.kind_mut()
1035 .as_type_mut()
1036 .unwrap()
1037 .as_comp_mut()
1038 .unwrap()
1039 .deanonymize_fields(ctx);
1040 });
1041 }
1042 }
1043
1044 fn process_replacements(&mut self) {
1047 let _t = self.timer("process_replacements");
1048 if self.replacements.is_empty() {
1049 debug!("No replacements to process");
1050 return;
1051 }
1052
1053 let mut replacements = vec![];
1059
1060 for (id, item) in self.items() {
1061 if item.annotations().use_instead_of().is_some() {
1062 continue;
1063 }
1064
1065 let Some(ty) = item.kind().as_type() else {
1068 continue;
1069 };
1070
1071 match *ty.kind() {
1072 TypeKind::Comp(..) |
1073 TypeKind::TemplateAlias(..) |
1074 TypeKind::Enum(..) |
1075 TypeKind::Alias(..) => {}
1076 _ => continue,
1077 }
1078
1079 let path = item.path_for_allowlisting(self);
1080 let replacement = self.replacements.get(&path[1..]);
1081
1082 if let Some(replacement) = replacement {
1083 if *replacement != id {
1084 if self.resolve_item_fallible(*replacement).is_some() {
1087 replacements.push((
1088 id.expect_type_id(self),
1089 replacement.expect_type_id(self),
1090 ));
1091 }
1092 }
1093 }
1094 }
1095
1096 for (id, replacement_id) in replacements {
1097 debug!("Replacing {id:?} with {replacement_id:?}");
1098 let new_parent = {
1099 let item_id: ItemId = id.into();
1100 let item = self.items[item_id.0].as_mut().unwrap();
1101 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
1102 TypeKind::ResolvedTypeRef(replacement_id);
1103 item.parent_id()
1104 };
1105
1106 let old_parent = self.resolve_item(replacement_id).parent_id();
1112 if new_parent == old_parent {
1113 continue;
1116 }
1117
1118 let replacement_item_id: ItemId = replacement_id.into();
1119 self.items[replacement_item_id.0]
1120 .as_mut()
1121 .unwrap()
1122 .set_parent_for_replacement(new_parent);
1123
1124 let old_module = {
1128 let immut_self = &*self;
1129 old_parent
1130 .ancestors(immut_self)
1131 .chain(Some(immut_self.root_module.into()))
1132 .find(|id| {
1133 let item = immut_self.resolve_item(*id);
1134 item.as_module().is_some_and(|m| {
1135 m.children().contains(&replacement_id.into())
1136 })
1137 })
1138 };
1139 let old_module = old_module
1140 .expect("Every replacement item should be in a module");
1141
1142 let new_module = {
1143 let immut_self = &*self;
1144 new_parent
1145 .ancestors(immut_self)
1146 .find(|id| immut_self.resolve_item(*id).is_module())
1147 };
1148 let new_module =
1149 new_module.unwrap_or_else(|| self.root_module.into());
1150
1151 if new_module == old_module {
1152 continue;
1154 }
1155
1156 self.items[old_module.0]
1157 .as_mut()
1158 .unwrap()
1159 .as_module_mut()
1160 .unwrap()
1161 .children_mut()
1162 .remove(&replacement_id.into());
1163
1164 self.items[new_module.0]
1165 .as_mut()
1166 .unwrap()
1167 .as_module_mut()
1168 .unwrap()
1169 .children_mut()
1170 .insert(replacement_id.into());
1171 }
1172 }
1173
1174 pub(crate) fn gen<F, Out>(
1177 mut self,
1178 cb: F,
1179 ) -> Result<(Out, BindgenOptions), CodegenError>
1180 where
1181 F: FnOnce(&Self) -> Result<Out, CodegenError>,
1182 {
1183 self.in_codegen = true;
1184
1185 self.resolve_typerefs();
1186 self.compute_bitfield_units();
1187 self.process_replacements();
1188
1189 self.deanonymize_fields();
1190
1191 self.assert_no_dangling_references();
1192
1193 self.compute_allowlisted_and_codegen_items();
1197
1198 self.assert_every_item_in_a_module();
1202
1203 self.compute_has_vtable();
1204 self.compute_sizedness();
1205 self.compute_has_destructor();
1206 self.find_used_template_parameters();
1207 self.compute_enum_typedef_combos();
1208 self.compute_cannot_derive_debug();
1209 self.compute_cannot_derive_default();
1210 self.compute_cannot_derive_copy();
1211 self.compute_has_type_param_in_array();
1212 self.compute_has_float();
1213 self.compute_cannot_derive_hash();
1214 self.compute_cannot_derive_partialord_partialeq_or_eq();
1215
1216 let ret = cb(&self)?;
1217 Ok((ret, self.options))
1218 }
1219
1220 fn assert_no_dangling_references(&self) {
1224 if cfg!(feature = "__testing_only_extra_assertions") {
1225 for _ in self.assert_no_dangling_item_traversal() {
1226 }
1228 }
1229 }
1230
1231 fn assert_no_dangling_item_traversal(
1232 &self,
1233 ) -> traversal::AssertNoDanglingItemsTraversal {
1234 assert!(self.in_codegen_phase());
1235 assert!(self.current_module == self.root_module);
1236
1237 let roots = self.items().map(|(id, _)| id);
1238 traversal::AssertNoDanglingItemsTraversal::new(
1239 self,
1240 roots,
1241 traversal::all_edges,
1242 )
1243 }
1244
1245 fn assert_every_item_in_a_module(&self) {
1249 if cfg!(feature = "__testing_only_extra_assertions") {
1250 assert!(self.in_codegen_phase());
1251 assert!(self.current_module == self.root_module);
1252
1253 for (id, _item) in self.items() {
1254 if id == self.root_module {
1255 continue;
1256 }
1257
1258 assert!(
1259 {
1260 let id = id
1261 .into_resolver()
1262 .through_type_refs()
1263 .through_type_aliases()
1264 .resolve(self)
1265 .id();
1266 id.ancestors(self)
1267 .chain(Some(self.root_module.into()))
1268 .any(|ancestor| {
1269 debug!("Checking if {id:?} is a child of {ancestor:?}");
1270 self.resolve_item(ancestor)
1271 .as_module()
1272 .is_some_and(|m| m.children().contains(&id))
1273 })
1274 },
1275 "{id:?} should be in some ancestor module's children set"
1276 );
1277 }
1278 }
1279 }
1280
1281 fn compute_sizedness(&mut self) {
1284 let _t = self.timer("compute_sizedness");
1285 assert!(self.sizedness.is_none());
1286 self.sizedness = Some(analyze::<SizednessAnalysis>(self));
1287 }
1288
1289 pub(crate) fn lookup_sizedness(&self, id: TypeId) -> SizednessResult {
1291 assert!(
1292 self.in_codegen_phase(),
1293 "We only compute sizedness after we've entered codegen"
1294 );
1295
1296 self.sizedness
1297 .as_ref()
1298 .unwrap()
1299 .get(&id)
1300 .copied()
1301 .unwrap_or(SizednessResult::ZeroSized)
1302 }
1303
1304 fn compute_has_vtable(&mut self) {
1306 let _t = self.timer("compute_has_vtable");
1307 assert!(self.have_vtable.is_none());
1308 self.have_vtable = Some(analyze::<HasVtableAnalysis>(self));
1309 }
1310
1311 pub(crate) fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult {
1313 assert!(
1314 self.in_codegen_phase(),
1315 "We only compute vtables when we enter codegen"
1316 );
1317
1318 self.have_vtable
1321 .as_ref()
1322 .unwrap()
1323 .get(&id.into())
1324 .copied()
1325 .unwrap_or(HasVtableResult::No)
1326 }
1327
1328 fn compute_has_destructor(&mut self) {
1330 let _t = self.timer("compute_has_destructor");
1331 assert!(self.have_destructor.is_none());
1332 self.have_destructor = Some(analyze::<HasDestructorAnalysis>(self));
1333 }
1334
1335 pub(crate) fn lookup_has_destructor(&self, id: TypeId) -> bool {
1337 assert!(
1338 self.in_codegen_phase(),
1339 "We only compute destructors when we enter codegen"
1340 );
1341
1342 self.have_destructor.as_ref().unwrap().contains(&id.into())
1343 }
1344
1345 fn find_used_template_parameters(&mut self) {
1346 let _t = self.timer("find_used_template_parameters");
1347 if self.options.allowlist_recursively {
1348 let used_params = analyze::<UsedTemplateParameters>(self);
1349 self.used_template_parameters = Some(used_params);
1350 } else {
1351 let mut used_params = HashMap::default();
1354 for &id in self.allowlisted_items() {
1355 used_params.entry(id).or_insert_with(|| {
1356 id.self_template_params(self)
1357 .into_iter()
1358 .map(|p| p.into())
1359 .collect()
1360 });
1361 }
1362 self.used_template_parameters = Some(used_params);
1363 }
1364 }
1365
1366 pub(crate) fn uses_template_parameter(
1381 &self,
1382 item: ItemId,
1383 template_param: TypeId,
1384 ) -> bool {
1385 assert!(
1386 self.in_codegen_phase(),
1387 "We only compute template parameter usage as we enter codegen"
1388 );
1389
1390 if self.resolve_item(item).is_blocklisted(self) {
1391 return true;
1392 }
1393
1394 let template_param = template_param
1395 .into_resolver()
1396 .through_type_refs()
1397 .through_type_aliases()
1398 .resolve(self)
1399 .id();
1400
1401 self.used_template_parameters
1402 .as_ref()
1403 .expect("should have found template parameter usage if we're in codegen")
1404 .get(&item).is_some_and(|items_used_params| items_used_params.contains(&template_param))
1405 }
1406
1407 pub(crate) fn uses_any_template_parameters(&self, item: ItemId) -> bool {
1412 assert!(
1413 self.in_codegen_phase(),
1414 "We only compute template parameter usage as we enter codegen"
1415 );
1416
1417 self.used_template_parameters
1418 .as_ref()
1419 .expect(
1420 "should have template parameter usage info in codegen phase",
1421 )
1422 .get(&item)
1423 .is_some_and(|used| !used.is_empty())
1424 }
1425
1426 fn add_builtin_item(&mut self, item: Item) {
1435 debug!("add_builtin_item: item = {item:?}");
1436 debug_assert!(item.kind().is_type());
1437 self.add_item_to_module(&item);
1438 let id = item.id();
1439 let old_item = mem::replace(&mut self.items[id.0], Some(item));
1440 assert!(old_item.is_none(), "Inserted type twice?");
1441 }
1442
1443 fn build_root_module(id: ItemId) -> Item {
1444 let module = Module::new(Some("root".into()), ModuleKind::Normal);
1445 Item::new(id, None, None, id, ItemKind::Module(module), None)
1446 }
1447
1448 pub(crate) fn root_module(&self) -> ModuleId {
1450 self.root_module
1451 }
1452
1453 pub(crate) fn resolve_type(&self, type_id: TypeId) -> &Type {
1458 self.resolve_item(type_id).kind().expect_type()
1459 }
1460
1461 pub(crate) fn resolve_func(&self, func_id: FunctionId) -> &Function {
1466 self.resolve_item(func_id).kind().expect_function()
1467 }
1468
1469 pub(crate) fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
1474 self.resolve_item_fallible(type_id)
1475 .map(|t| t.kind().expect_type())
1476 }
1477
1478 pub(crate) fn resolve_item_fallible<Id: Into<ItemId>>(
1481 &self,
1482 id: Id,
1483 ) -> Option<&Item> {
1484 self.items.get(id.into().0)?.as_ref()
1485 }
1486
1487 pub(crate) fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
1491 let item_id = item_id.into();
1492 match self.resolve_item_fallible(item_id) {
1493 Some(item) => item,
1494 None => panic!("Not an item: {item_id:?}"),
1495 }
1496 }
1497
1498 pub(crate) fn current_module(&self) -> ModuleId {
1500 self.current_module
1501 }
1502
1503 pub(crate) fn add_semantic_parent(
1512 &mut self,
1513 definition: Cursor,
1514 parent_id: ItemId,
1515 ) {
1516 self.semantic_parents.insert(definition, parent_id);
1517 }
1518
1519 pub(crate) fn known_semantic_parent(
1521 &self,
1522 definition: Cursor,
1523 ) -> Option<ItemId> {
1524 self.semantic_parents.get(&definition).copied()
1525 }
1526
1527 fn get_declaration_info_for_template_instantiation(
1535 &self,
1536 instantiation: &Cursor,
1537 ) -> Option<(Cursor, ItemId, usize)> {
1538 instantiation
1539 .cur_type()
1540 .canonical_declaration(Some(instantiation))
1541 .and_then(|canon_decl| {
1542 self.get_resolved_type(&canon_decl).and_then(
1543 |template_decl_id| {
1544 let num_params =
1545 template_decl_id.num_self_template_params(self);
1546 if num_params == 0 {
1547 None
1548 } else {
1549 Some((
1550 *canon_decl.cursor(),
1551 template_decl_id.into(),
1552 num_params,
1553 ))
1554 }
1555 },
1556 )
1557 })
1558 .or_else(|| {
1559 instantiation
1567 .referenced()
1568 .and_then(|referenced| {
1569 self.currently_parsed_types()
1570 .iter()
1571 .find(|partial_ty| *partial_ty.decl() == referenced)
1572 })
1573 .and_then(|template_decl| {
1574 let num_template_params =
1575 template_decl.num_self_template_params(self);
1576 if num_template_params == 0 {
1577 None
1578 } else {
1579 Some((
1580 *template_decl.decl(),
1581 template_decl.id(),
1582 num_template_params,
1583 ))
1584 }
1585 })
1586 })
1587 }
1588
1589 fn instantiate_template(
1623 &mut self,
1624 with_id: ItemId,
1625 template: TypeId,
1626 ty: &clang::Type,
1627 location: Cursor,
1628 ) -> Option<TypeId> {
1629 let num_expected_args =
1630 self.resolve_type(template).num_self_template_params(self);
1631 if num_expected_args == 0 {
1632 warn!(
1633 "Tried to instantiate a template for which we could not \
1634 determine any template parameters"
1635 );
1636 return None;
1637 }
1638
1639 let mut args = vec![];
1640 let mut found_const_arg = false;
1641 let mut children = location.collect_children();
1642
1643 if children.iter().all(|c| !c.has_children()) {
1644 let idx = children
1655 .iter()
1656 .position(|c| c.kind() == clang_sys::CXCursor_TemplateRef);
1657 if let Some(idx) = idx {
1658 if children
1659 .iter()
1660 .take(idx)
1661 .all(|c| c.kind() == clang_sys::CXCursor_NamespaceRef)
1662 {
1663 children = children.into_iter().skip(idx + 1).collect();
1664 }
1665 }
1666 }
1667
1668 for child in children.iter().rev() {
1669 match child.kind() {
1670 clang_sys::CXCursor_TypeRef |
1671 clang_sys::CXCursor_TypedefDecl |
1672 clang_sys::CXCursor_TypeAliasDecl => {
1673 let ty = Item::from_ty_or_ref(
1680 child.cur_type(),
1681 *child,
1682 Some(template.into()),
1683 self,
1684 );
1685 args.push(ty);
1686 }
1687 clang_sys::CXCursor_TemplateRef => {
1688 let (
1689 template_decl_cursor,
1690 template_decl_id,
1691 num_expected_template_args,
1692 ) = self.get_declaration_info_for_template_instantiation(
1693 child,
1694 )?;
1695
1696 if num_expected_template_args == 0 ||
1697 child.has_at_least_num_children(
1698 num_expected_template_args,
1699 )
1700 {
1701 let ty = Item::from_ty_or_ref(
1704 child.cur_type(),
1705 *child,
1706 Some(template.into()),
1707 self,
1708 );
1709 args.push(ty);
1710 } else {
1711 let args_len = args.len();
1716 if args_len < num_expected_template_args {
1717 warn!(
1718 "Found a template instantiation without \
1719 enough template arguments"
1720 );
1721 return None;
1722 }
1723
1724 let mut sub_args: Vec<_> = args
1725 .drain(args_len - num_expected_template_args..)
1726 .collect();
1727 sub_args.reverse();
1728
1729 let sub_name = Some(template_decl_cursor.spelling());
1730 let sub_inst = TemplateInstantiation::new(
1731 template_decl_id.as_type_id_unchecked(),
1734 sub_args,
1735 );
1736 let sub_kind =
1737 TypeKind::TemplateInstantiation(sub_inst);
1738 let sub_ty = Type::new(
1739 sub_name,
1740 template_decl_cursor
1741 .cur_type()
1742 .fallible_layout(self)
1743 .ok(),
1744 sub_kind,
1745 false,
1746 );
1747 let sub_id = self.next_item_id();
1748 let sub_item = Item::new(
1749 sub_id,
1750 None,
1751 None,
1752 self.current_module.into(),
1753 ItemKind::Type(sub_ty),
1754 Some(child.location()),
1755 );
1756
1757 debug!(
1759 "instantiate_template: inserting nested \
1760 instantiation item: {:?}",
1761 sub_item
1762 );
1763 self.add_item_to_module(&sub_item);
1764 debug_assert_eq!(sub_id, sub_item.id());
1765 self.items[sub_id.0] = Some(sub_item);
1766 args.push(sub_id.as_type_id_unchecked());
1767 }
1768 }
1769 _ => {
1770 warn!(
1771 "Found template arg cursor we can't handle: {child:?}"
1772 );
1773 found_const_arg = true;
1774 }
1775 }
1776 }
1777
1778 if found_const_arg {
1779 warn!(
1786 "Found template instantiated with a const value; \
1787 bindgen can't handle this kind of template instantiation!"
1788 );
1789 return None;
1790 }
1791
1792 if args.len() != num_expected_args {
1793 warn!(
1794 "Found a template with an unexpected number of template \
1795 arguments"
1796 );
1797 return None;
1798 }
1799
1800 args.reverse();
1801 let type_kind = TypeKind::TemplateInstantiation(
1802 TemplateInstantiation::new(template, args),
1803 );
1804 let name = ty.spelling();
1805 let name = if name.is_empty() { None } else { Some(name) };
1806 let ty = Type::new(
1807 name,
1808 ty.fallible_layout(self).ok(),
1809 type_kind,
1810 ty.is_const(),
1811 );
1812 let item = Item::new(
1813 with_id,
1814 None,
1815 None,
1816 self.current_module.into(),
1817 ItemKind::Type(ty),
1818 Some(location.location()),
1819 );
1820
1821 debug!("instantiate_template: inserting item: {item:?}");
1823 self.add_item_to_module(&item);
1824 debug_assert_eq!(with_id, item.id());
1825 self.items[with_id.0] = Some(item);
1826 Some(with_id.as_type_id_unchecked())
1827 }
1828
1829 pub(crate) fn get_resolved_type(
1832 &self,
1833 decl: &clang::CanonicalTypeDeclaration,
1834 ) -> Option<TypeId> {
1835 self.types
1836 .get(&TypeKey::Declaration(*decl.cursor()))
1837 .or_else(|| {
1838 decl.cursor()
1839 .usr()
1840 .and_then(|usr| self.types.get(&TypeKey::Usr(usr)))
1841 })
1842 .copied()
1843 }
1844
1845 pub(crate) fn builtin_or_resolved_ty(
1848 &mut self,
1849 with_id: ItemId,
1850 parent_id: Option<ItemId>,
1851 ty: &clang::Type,
1852 location: Option<Cursor>,
1853 ) -> Option<TypeId> {
1854 use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
1855 debug!("builtin_or_resolved_ty: {ty:?}, {location:?}, {with_id:?}, {parent_id:?}");
1856
1857 if let Some(decl) = ty.canonical_declaration(location.as_ref()) {
1858 if let Some(id) = self.get_resolved_type(&decl) {
1859 debug!(
1860 "Already resolved ty {id:?}, {decl:?}, {ty:?} {location:?}"
1861 );
1862 if let Some(location) = location {
1870 if decl.cursor().is_template_like() &&
1871 *ty != decl.cursor().cur_type()
1872 {
1873 if decl.cursor().kind() ==
1884 CXCursor_TypeAliasTemplateDecl &&
1885 !location.contains_cursor(CXCursor_TypeRef) &&
1886 ty.canonical_type().is_valid_and_exposed()
1887 {
1888 return None;
1889 }
1890
1891 return self
1892 .instantiate_template(with_id, id, ty, location)
1893 .or(Some(id));
1894 }
1895 }
1896
1897 return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
1898 }
1899 }
1900
1901 debug!("Not resolved, maybe builtin?");
1902 self.build_builtin_ty(ty)
1903 }
1904
1905 pub(crate) fn build_ty_wrapper(
1914 &mut self,
1915 with_id: ItemId,
1916 wrapped_id: TypeId,
1917 parent_id: Option<ItemId>,
1918 ty: &clang::Type,
1919 ) -> TypeId {
1920 self.build_wrapper(with_id, wrapped_id, parent_id, ty, ty.is_const())
1921 }
1922
1923 pub(crate) fn build_const_wrapper(
1927 &mut self,
1928 with_id: ItemId,
1929 wrapped_id: TypeId,
1930 parent_id: Option<ItemId>,
1931 ty: &clang::Type,
1932 ) -> TypeId {
1933 self.build_wrapper(
1934 with_id, wrapped_id, parent_id, ty, true,
1935 )
1936 }
1937
1938 fn build_wrapper(
1939 &mut self,
1940 with_id: ItemId,
1941 wrapped_id: TypeId,
1942 parent_id: Option<ItemId>,
1943 ty: &clang::Type,
1944 is_const: bool,
1945 ) -> TypeId {
1946 let spelling = ty.spelling();
1947 let layout = ty.fallible_layout(self).ok();
1948 let location = ty.declaration().location();
1949 let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
1950 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
1951 let item = Item::new(
1952 with_id,
1953 None,
1954 None,
1955 parent_id.unwrap_or_else(|| self.current_module.into()),
1956 ItemKind::Type(ty),
1957 Some(location),
1958 );
1959 self.add_builtin_item(item);
1960 with_id.as_type_id_unchecked()
1961 }
1962
1963 pub(crate) fn next_item_id(&mut self) -> ItemId {
1965 let ret = ItemId(self.items.len());
1966 self.items.push(None);
1967 ret
1968 }
1969
1970 fn build_builtin_ty(&mut self, ty: &clang::Type) -> Option<TypeId> {
1971 use clang_sys::*;
1972 let type_kind = match ty.kind() {
1973 CXType_NullPtr => TypeKind::NullPtr,
1974 CXType_Void => TypeKind::Void,
1975 CXType_Bool => TypeKind::Int(IntKind::Bool),
1976 CXType_Int => TypeKind::Int(IntKind::Int),
1977 CXType_UInt => TypeKind::Int(IntKind::UInt),
1978 CXType_Char_S => TypeKind::Int(IntKind::Char { is_signed: true }),
1979 CXType_Char_U => TypeKind::Int(IntKind::Char { is_signed: false }),
1980 CXType_SChar => TypeKind::Int(IntKind::SChar),
1981 CXType_UChar => TypeKind::Int(IntKind::UChar),
1982 CXType_Short => TypeKind::Int(IntKind::Short),
1983 CXType_UShort => TypeKind::Int(IntKind::UShort),
1984 CXType_WChar => TypeKind::Int(IntKind::WChar),
1985 CXType_Char16 => TypeKind::Int(IntKind::U16),
1986 CXType_Char32 => TypeKind::Int(IntKind::U32),
1987 CXType_Long => TypeKind::Int(IntKind::Long),
1988 CXType_ULong => TypeKind::Int(IntKind::ULong),
1989 CXType_LongLong => TypeKind::Int(IntKind::LongLong),
1990 CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
1991 CXType_Int128 => TypeKind::Int(IntKind::I128),
1992 CXType_UInt128 => TypeKind::Int(IntKind::U128),
1993 CXType_Float16 | CXType_Half => TypeKind::Float(FloatKind::Float16),
1994 CXType_Float => TypeKind::Float(FloatKind::Float),
1995 CXType_Double => TypeKind::Float(FloatKind::Double),
1996 CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
1997 CXType_Float128 => TypeKind::Float(FloatKind::Float128),
1998 CXType_Complex => {
1999 let float_type =
2000 ty.elem_type().expect("Not able to resolve complex type?");
2001 let float_kind = match float_type.kind() {
2002 CXType_Float16 | CXType_Half => FloatKind::Float16,
2003 CXType_Float => FloatKind::Float,
2004 CXType_Double => FloatKind::Double,
2005 CXType_LongDouble => FloatKind::LongDouble,
2006 CXType_Float128 => FloatKind::Float128,
2007 _ => panic!(
2008 "Non floating-type complex? {ty:?}, {float_type:?}",
2009 ),
2010 };
2011 TypeKind::Complex(float_kind)
2012 }
2013 _ => return None,
2014 };
2015
2016 let spelling = ty.spelling();
2017 let is_const = ty.is_const();
2018 let layout = ty.fallible_layout(self).ok();
2019 let location = ty.declaration().location();
2020 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
2021 let id = self.next_item_id();
2022 let item = Item::new(
2023 id,
2024 None,
2025 None,
2026 self.root_module.into(),
2027 ItemKind::Type(ty),
2028 Some(location),
2029 );
2030 self.add_builtin_item(item);
2031 Some(id.as_type_id_unchecked())
2032 }
2033
2034 pub(crate) fn translation_unit(&self) -> &clang::TranslationUnit {
2036 &self.translation_unit
2037 }
2038
2039 pub(crate) fn try_ensure_fallback_translation_unit(
2042 &mut self,
2043 ) -> Option<&mut clang::FallbackTranslationUnit> {
2044 if self.fallback_tu.is_none() {
2045 let file = format!(
2046 "{}/.macro_eval.c",
2047 match self.options().clang_macro_fallback_build_dir {
2048 Some(ref path) => path.as_os_str().to_str()?,
2049 None => ".",
2050 }
2051 );
2052
2053 let index = clang::Index::new(false, false);
2054
2055 let mut header_names_to_compile = Vec::new();
2056 let mut header_paths = Vec::new();
2057 let mut header_contents = String::new();
2058 for input_header in &self.options.input_headers {
2059 let path = Path::new(input_header.as_ref());
2060 if let Some(header_path) = path.parent() {
2061 if header_path == Path::new("") {
2062 header_paths.push(".");
2063 } else {
2064 header_paths.push(header_path.as_os_str().to_str()?);
2065 }
2066 } else {
2067 header_paths.push(".");
2068 }
2069 let header_name = path.file_name()?.to_str()?;
2070 header_names_to_compile
2071 .push(header_name.split(".h").next()?.to_string());
2072 header_contents +=
2073 format!("\n#include <{header_name}>").as_str();
2074 }
2075 let header_to_precompile = format!(
2076 "{}/{}",
2077 match self.options().clang_macro_fallback_build_dir {
2078 Some(ref path) => path.as_os_str().to_str()?,
2079 None => ".",
2080 },
2081 header_names_to_compile.join("-") + "-precompile.h"
2082 );
2083 let pch = header_to_precompile.clone() + ".pch";
2084
2085 let mut header_to_precompile_file = OpenOptions::new()
2086 .create(true)
2087 .truncate(true)
2088 .write(true)
2089 .open(&header_to_precompile)
2090 .ok()?;
2091 header_to_precompile_file
2092 .write_all(header_contents.as_bytes())
2093 .ok()?;
2094
2095 let mut c_args = Vec::new();
2096 c_args.push("-x".to_string().into_boxed_str());
2097 c_args.push("c-header".to_string().into_boxed_str());
2098 for header_path in header_paths {
2099 c_args.push(format!("-I{header_path}").into_boxed_str());
2100 }
2101 c_args.extend(
2102 self.options
2103 .clang_args
2104 .iter()
2105 .filter(|next| {
2106 !self.options.input_headers.contains(next) &&
2107 next.as_ref() != "-include"
2108 })
2109 .cloned(),
2110 );
2111 let mut tu = clang::TranslationUnit::parse(
2112 &index,
2113 &header_to_precompile,
2114 &c_args,
2115 &[],
2116 clang_sys::CXTranslationUnit_ForSerialization,
2117 )?;
2118 tu.save(&pch).ok()?;
2119
2120 let mut c_args = vec![
2121 "-include-pch".to_string().into_boxed_str(),
2122 pch.clone().into_boxed_str(),
2123 ];
2124 c_args.extend(
2125 self.options
2126 .clang_args
2127 .clone()
2128 .iter()
2129 .filter(|next| {
2130 !self.options.input_headers.contains(next) &&
2131 next.as_ref() != "-include"
2132 })
2133 .cloned(),
2134 );
2135 self.fallback_tu = Some(clang::FallbackTranslationUnit::new(
2136 file,
2137 header_to_precompile,
2138 pch,
2139 &c_args,
2140 )?);
2141 }
2142
2143 self.fallback_tu.as_mut()
2144 }
2145
2146 pub(crate) fn parsed_macro(&self, macro_name: &[u8]) -> bool {
2148 self.parsed_macros.contains_key(macro_name)
2149 }
2150
2151 pub(crate) fn parsed_macros(
2153 &self,
2154 ) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult> {
2155 debug_assert!(!self.in_codegen_phase());
2156 &self.parsed_macros
2157 }
2158
2159 pub(crate) fn note_parsed_macro(
2161 &mut self,
2162 id: Vec<u8>,
2163 value: cexpr::expr::EvalResult,
2164 ) {
2165 self.parsed_macros.insert(id, value);
2166 }
2167
2168 pub(crate) fn in_codegen_phase(&self) -> bool {
2170 self.in_codegen
2171 }
2172
2173 pub(crate) fn replace(&mut self, name: &[String], potential_ty: ItemId) {
2179 match self.replacements.entry(name.into()) {
2180 Entry::Vacant(entry) => {
2181 debug!("Defining replacement for {name:?} as {potential_ty:?}");
2182 entry.insert(potential_ty);
2183 }
2184 Entry::Occupied(occupied) => {
2185 warn!(
2186 "Replacement for {name:?} already defined as {:?}; \
2187 ignoring duplicate replacement definition as {potential_ty:?}",
2188 occupied.get(),
2189 );
2190 }
2191 }
2192 }
2193
2194 pub(crate) fn is_replaced_type<Id: Into<ItemId>>(
2197 &self,
2198 path: &[String],
2199 id: Id,
2200 ) -> bool {
2201 let id = id.into();
2202 matches!(self.replacements.get(path), Some(replaced_by) if *replaced_by != id)
2203 }
2204
2205 pub(crate) fn opaque_by_name(&self, path: &[String]) -> bool {
2207 debug_assert!(
2208 self.in_codegen_phase(),
2209 "You're not supposed to call this yet"
2210 );
2211 self.options.opaque_types.matches(path[1..].join("::"))
2212 }
2213
2214 pub(crate) fn options(&self) -> &BindgenOptions {
2216 &self.options
2217 }
2218
2219 fn tokenize_namespace(
2222 &self,
2223 cursor: &Cursor,
2224 ) -> (Option<String>, ModuleKind) {
2225 assert_eq!(
2226 cursor.kind(),
2227 ::clang_sys::CXCursor_Namespace,
2228 "Be a nice person"
2229 );
2230
2231 let mut module_name = None;
2232 let spelling = cursor.spelling();
2233 if !spelling.is_empty() {
2234 module_name = Some(spelling);
2235 }
2236
2237 let mut kind = ModuleKind::Normal;
2238 let mut looking_for_name = false;
2239 for token in cursor.tokens().iter() {
2240 match token.spelling() {
2241 b"inline" => {
2242 debug_assert!(
2243 kind != ModuleKind::Inline,
2244 "Multiple inline keywords?"
2245 );
2246 kind = ModuleKind::Inline;
2247 looking_for_name = true;
2250 }
2251 b"namespace" | b"::" => {
2259 looking_for_name = true;
2260 }
2261 b"{" => {
2262 assert!(looking_for_name);
2264 break;
2265 }
2266 name => {
2267 if looking_for_name {
2268 if module_name.is_none() {
2269 module_name = Some(
2270 String::from_utf8_lossy(name).into_owned(),
2271 );
2272 }
2273 break;
2274 } else {
2275 warn!(
2285 "Ignored unknown namespace prefix '{}' at {token:?} in {cursor:?}",
2286 String::from_utf8_lossy(name),
2287 );
2288 }
2289 }
2290 }
2291 }
2292
2293 if cursor.is_inline_namespace() {
2294 kind = ModuleKind::Inline;
2295 }
2296
2297 (module_name, kind)
2298 }
2299
2300 pub(crate) fn module(&mut self, cursor: Cursor) -> ModuleId {
2303 use clang_sys::*;
2304 assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person");
2305 let cursor = cursor.canonical();
2306 if let Some(id) = self.modules.get(&cursor) {
2307 return *id;
2308 }
2309
2310 let (module_name, kind) = self.tokenize_namespace(&cursor);
2311
2312 let module_id = self.next_item_id();
2313 let module = Module::new(module_name, kind);
2314 let module = Item::new(
2315 module_id,
2316 None,
2317 None,
2318 self.current_module.into(),
2319 ItemKind::Module(module),
2320 Some(cursor.location()),
2321 );
2322
2323 let module_id = module.id().as_module_id_unchecked();
2324 self.modules.insert(cursor, module_id);
2325
2326 self.add_item(module, None, None);
2327
2328 module_id
2329 }
2330
2331 pub(crate) fn with_module<F>(&mut self, module_id: ModuleId, cb: F)
2334 where
2335 F: FnOnce(&mut Self),
2336 {
2337 debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat");
2338
2339 let previous_id = self.current_module;
2340 self.current_module = module_id;
2341
2342 cb(self);
2343
2344 self.current_module = previous_id;
2345 }
2346
2347 pub(crate) fn allowlisted_items(&self) -> &ItemSet {
2352 assert!(self.in_codegen_phase());
2353 assert!(self.current_module == self.root_module);
2354
2355 self.allowlisted.as_ref().unwrap()
2356 }
2357
2358 pub(crate) fn blocklisted_type_implements_trait(
2361 &self,
2362 item: &Item,
2363 derive_trait: DeriveTrait,
2364 ) -> CanDerive {
2365 assert!(self.in_codegen_phase());
2366 assert!(self.current_module == self.root_module);
2367
2368 *self
2369 .blocklisted_types_implement_traits
2370 .borrow_mut()
2371 .entry(derive_trait)
2372 .or_default()
2373 .entry(item.id())
2374 .or_insert_with(|| {
2375 item.expect_type()
2376 .name()
2377 .and_then(|name| {
2378 if self.options.parse_callbacks.is_empty() {
2379 if self.is_stdint_type(name) {
2383 Some(CanDerive::Yes)
2384 } else {
2385 Some(CanDerive::No)
2386 }
2387 } else {
2388 self.options.last_callback(|cb| {
2389 cb.blocklisted_type_implements_trait(
2390 name,
2391 derive_trait,
2392 )
2393 })
2394 }
2395 })
2396 .unwrap_or(CanDerive::No)
2397 })
2398 }
2399
2400 pub(crate) fn is_stdint_type(&self, name: &str) -> bool {
2402 match name {
2403 "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" |
2404 "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" |
2405 "intptr_t" | "ptrdiff_t" => true,
2406 "size_t" | "ssize_t" => self.options.size_t_is_usize,
2407 _ => false,
2408 }
2409 }
2410
2411 pub(crate) fn codegen_items(&self) -> &ItemSet {
2413 assert!(self.in_codegen_phase());
2414 assert!(self.current_module == self.root_module);
2415 self.codegen_items.as_ref().unwrap()
2416 }
2417
2418 fn compute_allowlisted_and_codegen_items(&mut self) {
2420 assert!(self.in_codegen_phase());
2421 assert!(self.current_module == self.root_module);
2422 assert!(self.allowlisted.is_none());
2423 let _t = self.timer("compute_allowlisted_and_codegen_items");
2424
2425 let roots = {
2426 let mut roots = self
2427 .items()
2428 .filter(|&(_, item)| item.is_enabled_for_codegen(self))
2430 .filter(|&(_, item)| {
2431 if self.options().allowlisted_types.is_empty() &&
2434 self.options().allowlisted_functions.is_empty() &&
2435 self.options().allowlisted_vars.is_empty() &&
2436 self.options().allowlisted_files.is_empty() &&
2437 self.options().allowlisted_items.is_empty()
2438 {
2439 return true;
2440 }
2441
2442 if item.annotations().use_instead_of().is_some() {
2445 return true;
2446 }
2447
2448 if !self.options().allowlisted_files.is_empty() {
2451 if let Some(location) = item.location() {
2452 let (file, _, _, _) = location.location();
2453 if let Some(filename) = file.name() {
2454 if self
2455 .options()
2456 .allowlisted_files
2457 .matches(filename)
2458 {
2459 return true;
2460 }
2461 }
2462 }
2463 }
2464
2465 let name = item.path_for_allowlisting(self)[1..].join("::");
2466 debug!("allowlisted_items: testing {name:?}");
2467
2468 if self.options().allowlisted_items.matches(&name) {
2469 return true;
2470 }
2471
2472 match *item.kind() {
2473 ItemKind::Module(..) => true,
2474 ItemKind::Function(_) => {
2475 self.options().allowlisted_functions.matches(&name)
2476 }
2477 ItemKind::Var(_) => {
2478 self.options().allowlisted_vars.matches(&name)
2479 }
2480 ItemKind::Type(ref ty) => {
2481 if self.options().allowlisted_types.matches(&name) {
2482 return true;
2483 }
2484
2485 if !self.options().allowlist_recursively {
2489 match *ty.kind() {
2490 TypeKind::Void |
2491 TypeKind::NullPtr |
2492 TypeKind::Int(..) |
2493 TypeKind::Float(..) |
2494 TypeKind::Complex(..) |
2495 TypeKind::Array(..) |
2496 TypeKind::Vector(..) |
2497 TypeKind::Pointer(..) |
2498 TypeKind::Reference(..) |
2499 TypeKind::Function(..) |
2500 TypeKind::ResolvedTypeRef(..) |
2501 TypeKind::Opaque |
2502 TypeKind::TypeParam => return true,
2503 _ => {}
2504 }
2505 if self.is_stdint_type(&name) {
2506 return true;
2507 }
2508 }
2509
2510 let parent = self.resolve_item(item.parent_id());
2516 if !parent.is_module() {
2517 return false;
2518 }
2519
2520 let TypeKind::Enum(ref enum_) = *ty.kind() else {
2521 return false;
2522 };
2523
2524 if ty.name().is_some() {
2525 return false;
2526 }
2527
2528 let mut prefix_path =
2529 parent.path_for_allowlisting(self).clone();
2530 enum_.variants().iter().any(|variant| {
2531 prefix_path.push(
2532 variant.name_for_allowlisting().into(),
2533 );
2534 let name = prefix_path[1..].join("::");
2535 prefix_path.pop().unwrap();
2536 self.options().allowlisted_vars.matches(&name)
2537 || self
2538 .options()
2539 .allowlisted_items
2540 .matches(name)
2541 })
2542 }
2543 }
2544 })
2545 .map(|(id, _)| id)
2546 .collect::<Vec<_>>();
2547
2548 roots.reverse();
2552 roots
2553 };
2554
2555 let allowlisted_items_predicate =
2556 if self.options().allowlist_recursively {
2557 traversal::all_edges
2558 } else {
2559 traversal::only_inner_type_edges
2564 };
2565
2566 let allowlisted = AllowlistedItemsTraversal::new(
2567 self,
2568 roots.clone(),
2569 allowlisted_items_predicate,
2570 )
2571 .collect::<ItemSet>();
2572
2573 let codegen_items = if self.options().allowlist_recursively {
2574 AllowlistedItemsTraversal::new(
2575 self,
2576 roots,
2577 traversal::codegen_edges,
2578 )
2579 .collect::<ItemSet>()
2580 } else {
2581 allowlisted.clone()
2582 };
2583
2584 self.allowlisted = Some(allowlisted);
2585 self.codegen_items = Some(codegen_items);
2586
2587 for item in self.options().allowlisted_functions.unmatched_items() {
2588 unused_regex_diagnostic(item, "--allowlist-function", self);
2589 }
2590
2591 for item in self.options().allowlisted_vars.unmatched_items() {
2592 unused_regex_diagnostic(item, "--allowlist-var", self);
2593 }
2594
2595 for item in self.options().allowlisted_types.unmatched_items() {
2596 unused_regex_diagnostic(item, "--allowlist-type", self);
2597 }
2598
2599 for item in self.options().allowlisted_items.unmatched_items() {
2600 unused_regex_diagnostic(item, "--allowlist-items", self);
2601 }
2602 }
2603
2604 pub(crate) fn trait_prefix(&self) -> Ident {
2607 if self.options().use_core {
2608 self.rust_ident_raw("core")
2609 } else {
2610 self.rust_ident_raw("std")
2611 }
2612 }
2613
2614 pub(crate) fn generated_opaque_array(&self) {
2616 self.generated_opaque_array.set(true)
2617 }
2618
2619 pub(crate) fn need_opaque_array_type(&self) -> bool {
2621 self.generated_opaque_array.get()
2622 }
2623
2624 pub(crate) fn generated_bindgen_complex(&self) {
2626 self.generated_bindgen_complex.set(true);
2627 }
2628
2629 pub(crate) fn need_bindgen_complex_type(&self) -> bool {
2631 self.generated_bindgen_complex.get()
2632 }
2633
2634 pub(crate) fn generated_bindgen_float16(&self) {
2636 self.generated_bindgen_float16.set(true);
2637 }
2638
2639 pub(crate) fn need_bindgen_float16_type(&self) -> bool {
2641 self.generated_bindgen_float16.get()
2642 }
2643
2644 fn compute_enum_typedef_combos(&mut self) {
2646 let _t = self.timer("compute_enum_typedef_combos");
2647 assert!(self.enum_typedef_combos.is_none());
2648
2649 let mut enum_typedef_combos = HashSet::default();
2650 for item in &self.items {
2651 if let Some(ItemKind::Module(module)) =
2652 item.as_ref().map(Item::kind)
2653 {
2654 let mut names_of_typedefs = HashSet::default();
2656 for child_id in module.children() {
2657 if let Some(ItemKind::Type(ty)) =
2658 self.items[child_id.0].as_ref().map(Item::kind)
2659 {
2660 if let (Some(name), TypeKind::Alias(type_id)) =
2661 (ty.name(), ty.kind())
2662 {
2663 if type_id
2666 .into_resolver()
2667 .through_type_refs()
2668 .through_type_aliases()
2669 .resolve(self)
2670 .expect_type()
2671 .is_int()
2672 {
2673 names_of_typedefs.insert(name);
2674 }
2675 }
2676 }
2677 }
2678
2679 for child_id in module.children() {
2682 if let Some(ItemKind::Type(ty)) =
2683 self.items[child_id.0].as_ref().map(Item::kind)
2684 {
2685 if let (Some(name), true) = (ty.name(), ty.is_enum()) {
2686 if names_of_typedefs.contains(name) {
2687 enum_typedef_combos.insert(*child_id);
2688 }
2689 }
2690 }
2691 }
2692 }
2693 }
2694
2695 self.enum_typedef_combos = Some(enum_typedef_combos);
2696 }
2697
2698 pub(crate) fn is_enum_typedef_combo(&self, id: ItemId) -> bool {
2701 assert!(
2702 self.in_codegen_phase(),
2703 "We only compute enum_typedef_combos when we enter codegen",
2704 );
2705 self.enum_typedef_combos.as_ref().unwrap().contains(&id)
2706 }
2707
2708 fn compute_cannot_derive_debug(&mut self) {
2710 let _t = self.timer("compute_cannot_derive_debug");
2711 assert!(self.cannot_derive_debug.is_none());
2712 if self.options.derive_debug {
2713 self.cannot_derive_debug =
2714 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2715 self,
2716 DeriveTrait::Debug,
2717 ))));
2718 }
2719 }
2720
2721 pub(crate) fn lookup_can_derive_debug<Id: Into<ItemId>>(
2724 &self,
2725 id: Id,
2726 ) -> bool {
2727 let id = id.into();
2728 assert!(
2729 self.in_codegen_phase(),
2730 "We only compute can_derive_debug when we enter codegen"
2731 );
2732
2733 !self.cannot_derive_debug.as_ref().unwrap().contains(&id)
2736 }
2737
2738 fn compute_cannot_derive_default(&mut self) {
2740 let _t = self.timer("compute_cannot_derive_default");
2741 assert!(self.cannot_derive_default.is_none());
2742 if self.options.derive_default {
2743 self.cannot_derive_default =
2744 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2745 self,
2746 DeriveTrait::Default,
2747 ))));
2748 }
2749 }
2750
2751 pub(crate) fn lookup_can_derive_default<Id: Into<ItemId>>(
2754 &self,
2755 id: Id,
2756 ) -> bool {
2757 let id = id.into();
2758 assert!(
2759 self.in_codegen_phase(),
2760 "We only compute can_derive_default when we enter codegen"
2761 );
2762
2763 !self.cannot_derive_default.as_ref().unwrap().contains(&id)
2766 }
2767
2768 fn compute_cannot_derive_copy(&mut self) {
2770 let _t = self.timer("compute_cannot_derive_copy");
2771 assert!(self.cannot_derive_copy.is_none());
2772 self.cannot_derive_copy =
2773 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2774 self,
2775 DeriveTrait::Copy,
2776 ))));
2777 }
2778
2779 fn compute_cannot_derive_hash(&mut self) {
2781 let _t = self.timer("compute_cannot_derive_hash");
2782 assert!(self.cannot_derive_hash.is_none());
2783 if self.options.derive_hash {
2784 self.cannot_derive_hash =
2785 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2786 self,
2787 DeriveTrait::Hash,
2788 ))));
2789 }
2790 }
2791
2792 pub(crate) fn lookup_can_derive_hash<Id: Into<ItemId>>(
2795 &self,
2796 id: Id,
2797 ) -> bool {
2798 let id = id.into();
2799 assert!(
2800 self.in_codegen_phase(),
2801 "We only compute can_derive_debug when we enter codegen"
2802 );
2803
2804 !self.cannot_derive_hash.as_ref().unwrap().contains(&id)
2807 }
2808
2809 fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) {
2811 let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq");
2812 assert!(self.cannot_derive_partialeq_or_partialord.is_none());
2813 if self.options.derive_partialord ||
2814 self.options.derive_partialeq ||
2815 self.options.derive_eq
2816 {
2817 self.cannot_derive_partialeq_or_partialord =
2818 Some(analyze::<CannotDerive>((
2819 self,
2820 DeriveTrait::PartialEqOrPartialOrd,
2821 )));
2822 }
2823 }
2824
2825 pub(crate) fn lookup_can_derive_partialeq_or_partialord<
2827 Id: Into<ItemId>,
2828 >(
2829 &self,
2830 id: Id,
2831 ) -> CanDerive {
2832 let id = id.into();
2833 assert!(
2834 self.in_codegen_phase(),
2835 "We only compute can_derive_partialeq_or_partialord when we enter codegen"
2836 );
2837
2838 self.cannot_derive_partialeq_or_partialord
2841 .as_ref()
2842 .unwrap()
2843 .get(&id)
2844 .copied()
2845 .unwrap_or(CanDerive::Yes)
2846 }
2847
2848 pub(crate) fn lookup_can_derive_copy<Id: Into<ItemId>>(
2850 &self,
2851 id: Id,
2852 ) -> bool {
2853 assert!(
2854 self.in_codegen_phase(),
2855 "We only compute can_derive_debug when we enter codegen"
2856 );
2857
2858 let id = id.into();
2861
2862 !self.lookup_has_type_param_in_array(id) &&
2863 !self.cannot_derive_copy.as_ref().unwrap().contains(&id)
2864 }
2865
2866 fn compute_has_type_param_in_array(&mut self) {
2868 let _t = self.timer("compute_has_type_param_in_array");
2869 assert!(self.has_type_param_in_array.is_none());
2870 self.has_type_param_in_array =
2871 Some(analyze::<HasTypeParameterInArray>(self));
2872 }
2873
2874 pub(crate) fn lookup_has_type_param_in_array<Id: Into<ItemId>>(
2876 &self,
2877 id: Id,
2878 ) -> bool {
2879 assert!(
2880 self.in_codegen_phase(),
2881 "We only compute has array when we enter codegen"
2882 );
2883
2884 self.has_type_param_in_array
2887 .as_ref()
2888 .unwrap()
2889 .contains(&id.into())
2890 }
2891
2892 fn compute_has_float(&mut self) {
2894 let _t = self.timer("compute_has_float");
2895 assert!(self.has_float.is_none());
2896 if self.options.derive_eq || self.options.derive_ord {
2897 self.has_float = Some(analyze::<HasFloat>(self));
2898 }
2899 }
2900
2901 pub(crate) fn lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool {
2903 assert!(
2904 self.in_codegen_phase(),
2905 "We only compute has float when we enter codegen"
2906 );
2907
2908 self.has_float.as_ref().unwrap().contains(&id.into())
2911 }
2912
2913 pub(crate) fn no_partialeq_by_name(&self, item: &Item) -> bool {
2915 let name = item.path_for_allowlisting(self)[1..].join("::");
2916 self.options().no_partialeq_types.matches(name)
2917 }
2918
2919 pub(crate) fn no_copy_by_name(&self, item: &Item) -> bool {
2921 let name = item.path_for_allowlisting(self)[1..].join("::");
2922 self.options().no_copy_types.matches(name)
2923 }
2924
2925 pub(crate) fn no_debug_by_name(&self, item: &Item) -> bool {
2927 let name = item.path_for_allowlisting(self)[1..].join("::");
2928 self.options().no_debug_types.matches(name)
2929 }
2930
2931 pub(crate) fn no_default_by_name(&self, item: &Item) -> bool {
2933 let name = item.path_for_allowlisting(self)[1..].join("::");
2934 self.options().no_default_types.matches(name)
2935 }
2936
2937 pub(crate) fn no_hash_by_name(&self, item: &Item) -> bool {
2939 let name = item.path_for_allowlisting(self)[1..].join("::");
2940 self.options().no_hash_types.matches(name)
2941 }
2942
2943 pub(crate) fn must_use_type_by_name(&self, item: &Item) -> bool {
2945 let name = item.path_for_allowlisting(self)[1..].join("::");
2946 self.options().must_use_types.matches(name)
2947 }
2948
2949 pub(crate) fn wrap_unsafe_ops(&self, tokens: impl ToTokens) -> TokenStream {
2951 if self.options.wrap_unsafe_ops {
2952 quote!(unsafe { #tokens })
2953 } else {
2954 tokens.into_token_stream()
2955 }
2956 }
2957
2958 pub(crate) fn wrap_static_fns_suffix(&self) -> &str {
2961 self.options()
2962 .wrap_static_fns_suffix
2963 .as_deref()
2964 .unwrap_or(crate::DEFAULT_NON_EXTERN_FNS_SUFFIX)
2965 }
2966}
2967
2968#[derive(Debug, Copy, Clone)]
2970pub(crate) struct ItemResolver {
2971 id: ItemId,
2972 through_type_refs: bool,
2973 through_type_aliases: bool,
2974}
2975
2976impl ItemId {
2977 pub(crate) fn into_resolver(self) -> ItemResolver {
2979 self.into()
2980 }
2981}
2982
2983impl<T> From<T> for ItemResolver
2984where
2985 T: Into<ItemId>,
2986{
2987 fn from(id: T) -> ItemResolver {
2988 ItemResolver::new(id)
2989 }
2990}
2991
2992impl ItemResolver {
2993 pub(crate) fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
2995 let id = id.into();
2996 ItemResolver {
2997 id,
2998 through_type_refs: false,
2999 through_type_aliases: false,
3000 }
3001 }
3002
3003 pub(crate) fn through_type_refs(mut self) -> ItemResolver {
3005 self.through_type_refs = true;
3006 self
3007 }
3008
3009 pub(crate) fn through_type_aliases(mut self) -> ItemResolver {
3011 self.through_type_aliases = true;
3012 self
3013 }
3014
3015 pub(crate) fn resolve(self, ctx: &BindgenContext) -> &Item {
3017 assert!(ctx.collected_typerefs());
3018
3019 let mut id = self.id;
3020 let mut seen_ids = HashSet::default();
3021 loop {
3022 let item = ctx.resolve_item(id);
3023
3024 if !seen_ids.insert(id) {
3027 return item;
3028 }
3029
3030 let ty_kind = item.as_type().map(|t| t.kind());
3031 match ty_kind {
3032 Some(&TypeKind::ResolvedTypeRef(next_id))
3033 if self.through_type_refs =>
3034 {
3035 id = next_id.into();
3036 }
3037 Some(&TypeKind::Alias(next_id))
3041 if self.through_type_aliases =>
3042 {
3043 id = next_id.into();
3044 }
3045 _ => return item,
3046 }
3047 }
3048 }
3049}
3050
3051#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3053pub(crate) struct PartialType {
3054 decl: Cursor,
3055 id: ItemId,
3058}
3059
3060impl PartialType {
3061 pub(crate) fn new(decl: Cursor, id: ItemId) -> PartialType {
3063 PartialType { decl, id }
3065 }
3066
3067 pub(crate) fn decl(&self) -> &Cursor {
3069 &self.decl
3070 }
3071
3072 pub(crate) fn id(&self) -> ItemId {
3075 self.id
3076 }
3077}
3078
3079impl TemplateParameters for PartialType {
3080 fn self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId> {
3081 vec![]
3084 }
3085
3086 fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize {
3087 match self.decl().kind() {
3090 clang_sys::CXCursor_ClassTemplate |
3091 clang_sys::CXCursor_FunctionTemplate |
3092 clang_sys::CXCursor_TypeAliasTemplateDecl => {
3093 let mut num_params = 0;
3094 self.decl().visit(|c| {
3095 match c.kind() {
3096 clang_sys::CXCursor_TemplateTypeParameter |
3097 clang_sys::CXCursor_TemplateTemplateParameter |
3098 clang_sys::CXCursor_NonTypeTemplateParameter => {
3099 num_params += 1;
3100 }
3101 _ => {}
3102 };
3103 clang_sys::CXChildVisit_Continue
3104 });
3105 num_params
3106 }
3107 _ => 0,
3108 }
3109 }
3110}
3111
3112fn unused_regex_diagnostic(item: &str, name: &str, _ctx: &BindgenContext) {
3113 warn!("unused option: {name} {item}");
3114
3115 #[cfg(feature = "experimental")]
3116 if _ctx.options().emit_diagnostics {
3117 use crate::diagnostics::{Diagnostic, Level};
3118
3119 Diagnostic::default()
3120 .with_title(
3121 format!("Unused regular expression: `{item}`."),
3122 Level::Warning,
3123 )
3124 .add_annotation(
3125 format!("This regular expression was passed to `{name}`."),
3126 Level::Note,
3127 )
3128 .display();
3129 }
3130}