1//! Common context that is passed around during parsing and codegen.
2
3use 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, Cursor};
23use crate::codegen::CodegenError;
24use crate::BindgenOptions;
25use crate::{Entry, HashMap, HashSet};
26use cexpr;
27use clang_sys;
28use proc_macro2::{Ident, Span, TokenStream};
29use quote::ToTokens;
30use std::borrow::Cow;
31use std::cell::{Cell, RefCell};
32use std::collections::{BTreeSet, HashMap as StdHashMap};
33use std::iter::IntoIterator;
34use std::mem;
35
36/// An identifier for some kind of IR item.
37#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
38pub struct ItemId(usize);
39
40macro_rules! item_id_newtype {
41 (
42 $( #[$attr:meta] )*
43 pub 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 struct $name(ItemId);
55
56 impl $name {
57 /// Create an `ItemResolver` from this id.
58 pub fn into_resolver(self) -> ItemResolver {
59 let id: ItemId = self.into();
60 id.into()
61 }
62 }
63
64 impl<T> ::std::cmp::PartialEq<T> for $name
65 where
66 T: Copy + Into<ItemId>
67 {
68 fn eq(&self, rhs: &T) -> bool {
69 let rhs: ItemId = (*rhs).into();
70 self.0 == rhs
71 }
72 }
73
74 impl From<$name> for ItemId {
75 fn from(id: $name) -> ItemId {
76 id.0
77 }
78 }
79
80 impl<'a> From<&'a $name> for ItemId {
81 fn from(id: &'a $name) -> ItemId {
82 id.0
83 }
84 }
85
86 impl ItemId {
87 $( #[$checked_attr] )*
88 pub fn $checked(&self, ctx: &BindgenContext) -> Option<$name> {
89 if ctx.resolve_item(*self).kind().$check_method() {
90 Some($name(*self))
91 } else {
92 None
93 }
94 }
95
96 $( #[$expected_attr] )*
97 pub fn $expected(&self, ctx: &BindgenContext) -> $name {
98 self.$checked(ctx)
99 .expect(concat!(
100 stringify!($expected),
101 " called with ItemId that points to the wrong ItemKind"
102 ))
103 }
104
105 $( #[$unchecked_attr] )*
106 pub fn $unchecked(&self) -> $name {
107 $name(*self)
108 }
109 }
110 }
111}
112
113item_id_newtype! {
114 /// An identifier for an `Item` whose `ItemKind` is known to be
115 /// `ItemKind::Type`.
116 pub struct TypeId(ItemId)
117 where
118 /// Convert this `ItemId` into a `TypeId` if its associated item is a type,
119 /// otherwise return `None`.
120 checked = as_type_id with is_type,
121
122 /// Convert this `ItemId` into a `TypeId`.
123 ///
124 /// If this `ItemId` does not point to a type, then panic.
125 expected = expect_type_id,
126
127 /// Convert this `ItemId` into a `TypeId` without actually checking whether
128 /// this id actually points to a `Type`.
129 unchecked = as_type_id_unchecked;
130}
131
132item_id_newtype! {
133 /// An identifier for an `Item` whose `ItemKind` is known to be
134 /// `ItemKind::Module`.
135 pub struct ModuleId(ItemId)
136 where
137 /// Convert this `ItemId` into a `ModuleId` if its associated item is a
138 /// module, otherwise return `None`.
139 checked = as_module_id with is_module,
140
141 /// Convert this `ItemId` into a `ModuleId`.
142 ///
143 /// If this `ItemId` does not point to a module, then panic.
144 expected = expect_module_id,
145
146 /// Convert this `ItemId` into a `ModuleId` without actually checking
147 /// whether this id actually points to a `Module`.
148 unchecked = as_module_id_unchecked;
149}
150
151item_id_newtype! {
152 /// An identifier for an `Item` whose `ItemKind` is known to be
153 /// `ItemKind::Var`.
154 pub struct VarId(ItemId)
155 where
156 /// Convert this `ItemId` into a `VarId` if its associated item is a var,
157 /// otherwise return `None`.
158 checked = as_var_id with is_var,
159
160 /// Convert this `ItemId` into a `VarId`.
161 ///
162 /// If this `ItemId` does not point to a var, then panic.
163 expected = expect_var_id,
164
165 /// Convert this `ItemId` into a `VarId` without actually checking whether
166 /// this id actually points to a `Var`.
167 unchecked = as_var_id_unchecked;
168}
169
170item_id_newtype! {
171 /// An identifier for an `Item` whose `ItemKind` is known to be
172 /// `ItemKind::Function`.
173 pub struct FunctionId(ItemId)
174 where
175 /// Convert this `ItemId` into a `FunctionId` if its associated item is a function,
176 /// otherwise return `None`.
177 checked = as_function_id with is_function,
178
179 /// Convert this `ItemId` into a `FunctionId`.
180 ///
181 /// If this `ItemId` does not point to a function, then panic.
182 expected = expect_function_id,
183
184 /// Convert this `ItemId` into a `FunctionId` without actually checking whether
185 /// this id actually points to a `Function`.
186 unchecked = as_function_id_unchecked;
187}
188
189impl From<ItemId> for usize {
190 fn from(id: ItemId) -> usize {
191 id.0
192 }
193}
194
195impl ItemId {
196 /// Get a numeric representation of this id.
197 pub fn as_usize(&self) -> usize {
198 (*self).into()
199 }
200}
201
202impl<T> ::std::cmp::PartialEq<T> for ItemId
203where
204 T: Copy + Into<ItemId>,
205{
206 fn eq(&self, rhs: &T) -> bool {
207 let rhs: ItemId = (*rhs).into();
208 self.0 == rhs.0
209 }
210}
211
212impl<T> CanDeriveDebug for T
213where
214 T: Copy + Into<ItemId>,
215{
216 fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
217 ctx.options().derive_debug && ctx.lookup_can_derive_debug(*self)
218 }
219}
220
221impl<T> CanDeriveDefault for T
222where
223 T: Copy + Into<ItemId>,
224{
225 fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
226 ctx.options().derive_default && ctx.lookup_can_derive_default(*self)
227 }
228}
229
230impl<T> CanDeriveCopy for T
231where
232 T: Copy + Into<ItemId>,
233{
234 fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
235 ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self)
236 }
237}
238
239impl<T> CanDeriveHash for T
240where
241 T: Copy + Into<ItemId>,
242{
243 fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
244 ctx.options().derive_hash && ctx.lookup_can_derive_hash(*self)
245 }
246}
247
248impl<T> CanDerivePartialOrd for T
249where
250 T: Copy + Into<ItemId>,
251{
252 fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
253 ctx.options().derive_partialord &&
254 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
255 CanDerive::Yes
256 }
257}
258
259impl<T> CanDerivePartialEq for T
260where
261 T: Copy + Into<ItemId>,
262{
263 fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
264 ctx.options().derive_partialeq &&
265 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
266 CanDerive::Yes
267 }
268}
269
270impl<T> CanDeriveEq for T
271where
272 T: Copy + Into<ItemId>,
273{
274 fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
275 ctx.options().derive_eq &&
276 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
277 CanDerive::Yes &&
278 !ctx.lookup_has_float(*self)
279 }
280}
281
282impl<T> CanDeriveOrd for T
283where
284 T: Copy + Into<ItemId>,
285{
286 fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
287 ctx.options().derive_ord &&
288 ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
289 CanDerive::Yes &&
290 !ctx.lookup_has_float(*self)
291 }
292}
293
294/// A key used to index a resolved type, so we only process it once.
295///
296/// This is almost always a USR string (an unique identifier generated by
297/// clang), but it can also be the canonical declaration if the type is unnamed,
298/// in which case clang may generate the same USR for multiple nested unnamed
299/// types.
300#[derive(Eq, PartialEq, Hash, Debug)]
301enum TypeKey {
302 Usr(String),
303 Declaration(Cursor),
304}
305
306/// A context used during parsing and generation of structs.
307#[derive(Debug)]
308pub struct BindgenContext {
309 /// The map of all the items parsed so far, keyed off ItemId.
310 items: Vec<Option<Item>>,
311
312 /// Clang USR to type map. This is needed to be able to associate types with
313 /// item ids during parsing.
314 types: HashMap<TypeKey, TypeId>,
315
316 /// Maps from a cursor to the item id of the named template type parameter
317 /// for that cursor.
318 type_params: HashMap<clang::Cursor, TypeId>,
319
320 /// A cursor to module map. Similar reason than above.
321 modules: HashMap<Cursor, ModuleId>,
322
323 /// The root module, this is guaranteed to be an item of kind Module.
324 root_module: ModuleId,
325
326 /// Current module being traversed.
327 current_module: ModuleId,
328
329 /// A HashMap keyed on a type definition, and whose value is the parent id
330 /// of the declaration.
331 ///
332 /// This is used to handle the cases where the semantic and the lexical
333 /// parents of the cursor differ, like when a nested class is defined
334 /// outside of the parent class.
335 semantic_parents: HashMap<clang::Cursor, ItemId>,
336
337 /// A stack with the current type declarations and types we're parsing. This
338 /// is needed to avoid infinite recursion when parsing a type like:
339 ///
340 /// struct c { struct c* next; };
341 ///
342 /// This means effectively, that a type has a potential ID before knowing if
343 /// it's a correct type. But that's not important in practice.
344 ///
345 /// We could also use the `types` HashMap, but my intention with it is that
346 /// only valid types and declarations end up there, and this could
347 /// potentially break that assumption.
348 currently_parsed_types: Vec<PartialType>,
349
350 /// A map with all the already parsed macro names. This is done to avoid
351 /// hard errors while parsing duplicated macros, as well to allow macro
352 /// expression parsing.
353 ///
354 /// This needs to be an std::HashMap because the cexpr API requires it.
355 parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,
356
357 /// A set of all the included filenames.
358 deps: BTreeSet<String>,
359
360 /// The active replacements collected from replaces="xxx" annotations.
361 replacements: HashMap<Vec<String>, ItemId>,
362
363 collected_typerefs: bool,
364
365 in_codegen: bool,
366
367 /// The translation unit for parsing.
368 translation_unit: clang::TranslationUnit,
369
370 /// Target information that can be useful for some stuff.
371 target_info: clang::TargetInfo,
372
373 /// The options given by the user via cli or other medium.
374 options: BindgenOptions,
375
376 /// Whether a bindgen complex was generated
377 generated_bindgen_complex: Cell<bool>,
378
379 /// The set of `ItemId`s that are allowlisted. This the very first thing
380 /// computed after parsing our IR, and before running any of our analyses.
381 allowlisted: Option<ItemSet>,
382
383 /// Cache for calls to `ParseCallbacks::blocklisted_type_implements_trait`
384 blocklisted_types_implement_traits:
385 RefCell<HashMap<DeriveTrait, HashMap<ItemId, CanDerive>>>,
386
387 /// The set of `ItemId`s that are allowlisted for code generation _and_ that
388 /// we should generate accounting for the codegen options.
389 ///
390 /// It's computed right after computing the allowlisted items.
391 codegen_items: Option<ItemSet>,
392
393 /// Map from an item's id to the set of template parameter items that it
394 /// uses. See `ir::named` for more details. Always `Some` during the codegen
395 /// phase.
396 used_template_parameters: Option<HashMap<ItemId, ItemSet>>,
397
398 /// The set of `TypeKind::Comp` items found during parsing that need their
399 /// bitfield allocation units computed. Drained in `compute_bitfield_units`.
400 need_bitfield_allocation: Vec<ItemId>,
401
402 /// The set of enums that are defined by a pair of `enum` and `typedef`,
403 /// which is legal in C (but not C++).
404 ///
405 /// ```c++
406 /// // in either order
407 /// enum Enum { Variants... };
408 /// typedef int16_t Enum;
409 /// ```
410 ///
411 /// The stored `ItemId` is that of the `TypeKind::Enum`, not of the
412 /// `TypeKind::Alias`.
413 ///
414 /// This is populated when we enter codegen by `compute_enum_typedef_combos`
415 /// and is always `None` before that and `Some` after.
416 enum_typedef_combos: Option<HashSet<ItemId>>,
417
418 /// The set of (`ItemId`s of) types that can't derive debug.
419 ///
420 /// This is populated when we enter codegen by `compute_cannot_derive_debug`
421 /// and is always `None` before that and `Some` after.
422 cannot_derive_debug: Option<HashSet<ItemId>>,
423
424 /// The set of (`ItemId`s of) types that can't derive default.
425 ///
426 /// This is populated when we enter codegen by `compute_cannot_derive_default`
427 /// and is always `None` before that and `Some` after.
428 cannot_derive_default: Option<HashSet<ItemId>>,
429
430 /// The set of (`ItemId`s of) types that can't derive copy.
431 ///
432 /// This is populated when we enter codegen by `compute_cannot_derive_copy`
433 /// and is always `None` before that and `Some` after.
434 cannot_derive_copy: Option<HashSet<ItemId>>,
435
436 /// The set of (`ItemId`s of) types that can't derive hash.
437 ///
438 /// This is populated when we enter codegen by `compute_can_derive_hash`
439 /// and is always `None` before that and `Some` after.
440 cannot_derive_hash: Option<HashSet<ItemId>>,
441
442 /// The map why specified `ItemId`s of) types that can't derive hash.
443 ///
444 /// This is populated when we enter codegen by
445 /// `compute_cannot_derive_partialord_partialeq_or_eq` and is always `None`
446 /// before that and `Some` after.
447 cannot_derive_partialeq_or_partialord: Option<HashMap<ItemId, CanDerive>>,
448
449 /// The sizedness of types.
450 ///
451 /// This is populated by `compute_sizedness` and is always `None` before
452 /// that function is invoked and `Some` afterwards.
453 sizedness: Option<HashMap<TypeId, SizednessResult>>,
454
455 /// The set of (`ItemId's of`) types that has vtable.
456 ///
457 /// Populated when we enter codegen by `compute_has_vtable`; always `None`
458 /// before that and `Some` after.
459 have_vtable: Option<HashMap<ItemId, HasVtableResult>>,
460
461 /// The set of (`ItemId's of`) types that has destructor.
462 ///
463 /// Populated when we enter codegen by `compute_has_destructor`; always `None`
464 /// before that and `Some` after.
465 have_destructor: Option<HashSet<ItemId>>,
466
467 /// The set of (`ItemId's of`) types that has array.
468 ///
469 /// Populated when we enter codegen by `compute_has_type_param_in_array`; always `None`
470 /// before that and `Some` after.
471 has_type_param_in_array: Option<HashSet<ItemId>>,
472
473 /// The set of (`ItemId's of`) types that has float.
474 ///
475 /// Populated when we enter codegen by `compute_has_float`; always `None`
476 /// before that and `Some` after.
477 has_float: Option<HashSet<ItemId>>,
478
479 /// The set of warnings raised during binding generation.
480 warnings: Vec<String>,
481}
482
483/// A traversal of allowlisted items.
484struct AllowlistedItemsTraversal<'ctx> {
485 ctx: &'ctx BindgenContext,
486 traversal: ItemTraversal<'ctx, ItemSet, Vec<ItemId>>,
487}
488
489impl<'ctx> Iterator for AllowlistedItemsTraversal<'ctx> {
490 type Item = ItemId;
491
492 fn next(&mut self) -> Option<ItemId> {
493 loop {
494 let id: ItemId = self.traversal.next()?;
495
496 if self.ctx.resolve_item(item_id:id).is_blocklisted(self.ctx) {
497 continue;
498 }
499
500 return Some(id);
501 }
502 }
503}
504
505impl<'ctx> AllowlistedItemsTraversal<'ctx> {
506 /// Construct a new allowlisted items traversal.
507 pub fn new<R>(
508 ctx: &'ctx BindgenContext,
509 roots: R,
510 predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool,
511 ) -> Self
512 where
513 R: IntoIterator<Item = ItemId>,
514 {
515 AllowlistedItemsTraversal {
516 ctx,
517 traversal: ItemTraversal::new(ctx, roots, predicate),
518 }
519 }
520}
521
522impl BindgenContext {
523 /// Construct the context for the given `options`.
524 pub(crate) fn new(
525 options: BindgenOptions,
526 input_unsaved_files: &[clang::UnsavedFile],
527 ) -> Self {
528 // TODO(emilio): Use the CXTargetInfo here when available.
529 //
530 // see: https://reviews.llvm.org/D32389
531 let index = clang::Index::new(false, true);
532
533 let parse_options =
534 clang_sys::CXTranslationUnit_DetailedPreprocessingRecord;
535
536 let translation_unit = {
537 let _t =
538 Timer::new("translation_unit").with_output(options.time_phases);
539
540 clang::TranslationUnit::parse(
541 &index,
542 "",
543 &options.clang_args,
544 input_unsaved_files,
545 parse_options,
546 ).expect("libclang error; possible causes include:
547- Invalid flag syntax
548- Unrecognized flags
549- Invalid flag arguments
550- File I/O errors
551- Host vs. target architecture mismatch
552If you encounter an error missing from this list, please file an issue or a PR!")
553 };
554
555 let target_info = clang::TargetInfo::new(&translation_unit);
556 let root_module = Self::build_root_module(ItemId(0));
557 let root_module_id = root_module.id().as_module_id_unchecked();
558
559 // depfiles need to include the explicitly listed headers too
560 let deps = options.input_headers.iter().cloned().collect();
561
562 BindgenContext {
563 items: vec![Some(root_module)],
564 deps,
565 types: Default::default(),
566 type_params: Default::default(),
567 modules: Default::default(),
568 root_module: root_module_id,
569 current_module: root_module_id,
570 semantic_parents: Default::default(),
571 currently_parsed_types: vec![],
572 parsed_macros: Default::default(),
573 replacements: Default::default(),
574 collected_typerefs: false,
575 in_codegen: false,
576 translation_unit,
577 target_info,
578 options,
579 generated_bindgen_complex: Cell::new(false),
580 allowlisted: None,
581 blocklisted_types_implement_traits: Default::default(),
582 codegen_items: None,
583 used_template_parameters: None,
584 need_bitfield_allocation: Default::default(),
585 enum_typedef_combos: None,
586 cannot_derive_debug: None,
587 cannot_derive_default: None,
588 cannot_derive_copy: None,
589 cannot_derive_hash: None,
590 cannot_derive_partialeq_or_partialord: None,
591 sizedness: None,
592 have_vtable: None,
593 have_destructor: None,
594 has_type_param_in_array: None,
595 has_float: None,
596 warnings: Vec::new(),
597 }
598 }
599
600 /// Returns `true` if the target architecture is wasm32
601 pub fn is_target_wasm32(&self) -> bool {
602 self.target_info.triple.starts_with("wasm32-")
603 }
604
605 /// Creates a timer for the current bindgen phase. If time_phases is `true`,
606 /// the timer will print to stderr when it is dropped, otherwise it will do
607 /// nothing.
608 pub fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
609 Timer::new(name).with_output(self.options.time_phases)
610 }
611
612 /// Returns the pointer width to use for the target for the current
613 /// translation.
614 pub fn target_pointer_size(&self) -> usize {
615 self.target_info.pointer_width / 8
616 }
617
618 /// Get the stack of partially parsed types that we are in the middle of
619 /// parsing.
620 pub fn currently_parsed_types(&self) -> &[PartialType] {
621 &self.currently_parsed_types[..]
622 }
623
624 /// Begin parsing the given partial type, and push it onto the
625 /// `currently_parsed_types` stack so that we won't infinite recurse if we
626 /// run into a reference to it while parsing it.
627 pub fn begin_parsing(&mut self, partial_ty: PartialType) {
628 self.currently_parsed_types.push(partial_ty);
629 }
630
631 /// Finish parsing the current partial type, pop it off the
632 /// `currently_parsed_types` stack, and return it.
633 pub fn finish_parsing(&mut self) -> PartialType {
634 self.currently_parsed_types.pop().expect(
635 "should have been parsing a type, if we finished parsing a type",
636 )
637 }
638
639 /// Add another path to the set of included files.
640 pub fn include_file(&mut self, filename: String) {
641 for cb in &self.options().parse_callbacks {
642 cb.include_file(&filename);
643 }
644 self.deps.insert(filename);
645 }
646
647 /// Get any included files.
648 pub fn deps(&self) -> &BTreeSet<String> {
649 &self.deps
650 }
651
652 /// Define a new item.
653 ///
654 /// This inserts it into the internal items set, and its type into the
655 /// internal types set.
656 pub fn add_item(
657 &mut self,
658 item: Item,
659 declaration: Option<Cursor>,
660 location: Option<Cursor>,
661 ) {
662 debug!(
663 "BindgenContext::add_item({:?}, declaration: {:?}, loc: {:?}",
664 item, declaration, location
665 );
666 debug_assert!(
667 declaration.is_some() ||
668 !item.kind().is_type() ||
669 item.kind().expect_type().is_builtin_or_type_param() ||
670 item.kind().expect_type().is_opaque(self, &item) ||
671 item.kind().expect_type().is_unresolved_ref(),
672 "Adding a type without declaration?"
673 );
674
675 let id = item.id();
676 let is_type = item.kind().is_type();
677 let is_unnamed = is_type && item.expect_type().name().is_none();
678 let is_template_instantiation =
679 is_type && item.expect_type().is_template_instantiation();
680
681 if item.id() != self.root_module {
682 self.add_item_to_module(&item);
683 }
684
685 if is_type && item.expect_type().is_comp() {
686 self.need_bitfield_allocation.push(id);
687 }
688
689 let old_item = mem::replace(&mut self.items[id.0], Some(item));
690 assert!(
691 old_item.is_none(),
692 "should not have already associated an item with the given id"
693 );
694
695 // Unnamed items can have an USR, but they can't be referenced from
696 // other sites explicitly and the USR can match if the unnamed items are
697 // nested, so don't bother tracking them.
698 if !is_type || is_template_instantiation {
699 return;
700 }
701 if let Some(mut declaration) = declaration {
702 if !declaration.is_valid() {
703 if let Some(location) = location {
704 if location.is_template_like() {
705 declaration = location;
706 }
707 }
708 }
709 declaration = declaration.canonical();
710 if !declaration.is_valid() {
711 // This could happen, for example, with types like `int*` or
712 // similar.
713 //
714 // Fortunately, we don't care about those types being
715 // duplicated, so we can just ignore them.
716 debug!(
717 "Invalid declaration {:?} found for type {:?}",
718 declaration,
719 self.resolve_item_fallible(id)
720 .unwrap()
721 .kind()
722 .expect_type()
723 );
724 return;
725 }
726
727 let key = if is_unnamed {
728 TypeKey::Declaration(declaration)
729 } else if let Some(usr) = declaration.usr() {
730 TypeKey::Usr(usr)
731 } else {
732 warn!(
733 "Valid declaration with no USR: {:?}, {:?}",
734 declaration, location
735 );
736 TypeKey::Declaration(declaration)
737 };
738
739 let old = self.types.insert(key, id.as_type_id_unchecked());
740 debug_assert_eq!(old, None);
741 }
742 }
743
744 /// Ensure that every item (other than the root module) is in a module's
745 /// children list. This is to make sure that every allowlisted item get's
746 /// codegen'd, even if its parent is not allowlisted. See issue #769 for
747 /// details.
748 fn add_item_to_module(&mut self, item: &Item) {
749 assert!(item.id() != self.root_module);
750 assert!(self.resolve_item_fallible(item.id()).is_none());
751
752 if let Some(ref mut parent) = self.items[item.parent_id().0] {
753 if let Some(module) = parent.as_module_mut() {
754 debug!(
755 "add_item_to_module: adding {:?} as child of parent module {:?}",
756 item.id(),
757 item.parent_id()
758 );
759
760 module.children_mut().insert(item.id());
761 return;
762 }
763 }
764
765 debug!(
766 "add_item_to_module: adding {:?} as child of current module {:?}",
767 item.id(),
768 self.current_module
769 );
770
771 self.items[(self.current_module.0).0]
772 .as_mut()
773 .expect("Should always have an item for self.current_module")
774 .as_module_mut()
775 .expect("self.current_module should always be a module")
776 .children_mut()
777 .insert(item.id());
778 }
779
780 /// Add a new named template type parameter to this context's item set.
781 pub fn add_type_param(&mut self, item: Item, definition: clang::Cursor) {
782 debug!(
783 "BindgenContext::add_type_param: item = {:?}; definition = {:?}",
784 item, definition
785 );
786
787 assert!(
788 item.expect_type().is_type_param(),
789 "Should directly be a named type, not a resolved reference or anything"
790 );
791 assert_eq!(
792 definition.kind(),
793 clang_sys::CXCursor_TemplateTypeParameter
794 );
795
796 self.add_item_to_module(&item);
797
798 let id = item.id();
799 let old_item = mem::replace(&mut self.items[id.0], Some(item));
800 assert!(
801 old_item.is_none(),
802 "should not have already associated an item with the given id"
803 );
804
805 let old_named_ty = self
806 .type_params
807 .insert(definition, id.as_type_id_unchecked());
808 assert!(
809 old_named_ty.is_none(),
810 "should not have already associated a named type with this id"
811 );
812 }
813
814 /// Get the named type defined at the given cursor location, if we've
815 /// already added one.
816 pub fn get_type_param(&self, definition: &clang::Cursor) -> Option<TypeId> {
817 assert_eq!(
818 definition.kind(),
819 clang_sys::CXCursor_TemplateTypeParameter
820 );
821 self.type_params.get(definition).cloned()
822 }
823
824 // TODO: Move all this syntax crap to other part of the code.
825
826 /// Mangles a name so it doesn't conflict with any keyword.
827 #[rustfmt::skip]
828 pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
829 if name.contains('@') ||
830 name.contains('?') ||
831 name.contains('$') ||
832 matches!(
833 name,
834 "abstract" | "alignof" | "as" | "async" | "await" | "become" |
835 "box" | "break" | "const" | "continue" | "crate" | "do" |
836 "dyn" | "else" | "enum" | "extern" | "false" | "final" |
837 "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" |
838 "macro" | "match" | "mod" | "move" | "mut" | "offsetof" |
839 "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
840 "return" | "Self" | "self" | "sizeof" | "static" |
841 "struct" | "super" | "trait" | "true" | "try" | "type" | "typeof" |
842 "unsafe" | "unsized" | "use" | "virtual" | "where" |
843 "while" | "yield" | "str" | "bool" | "f32" | "f64" |
844 "usize" | "isize" | "u128" | "i128" | "u64" | "i64" |
845 "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "_"
846 )
847 {
848 let mut s = name.to_owned();
849 s = s.replace('@', "_");
850 s = s.replace('?', "_");
851 s = s.replace('$', "_");
852 s.push('_');
853 return Cow::Owned(s);
854 }
855 Cow::Borrowed(name)
856 }
857
858 /// Returns a mangled name as a rust identifier.
859 pub fn rust_ident<S>(&self, name: S) -> Ident
860 where
861 S: AsRef<str>,
862 {
863 self.rust_ident_raw(self.rust_mangle(name.as_ref()))
864 }
865
866 /// Returns a mangled name as a rust identifier.
867 pub fn rust_ident_raw<T>(&self, name: T) -> Ident
868 where
869 T: AsRef<str>,
870 {
871 Ident::new(name.as_ref(), Span::call_site())
872 }
873
874 /// Iterate over all items that have been defined.
875 pub fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
876 self.items.iter().enumerate().filter_map(|(index, item)| {
877 let item = item.as_ref()?;
878 Some((ItemId(index), item))
879 })
880 }
881
882 /// Have we collected all unresolved type references yet?
883 pub fn collected_typerefs(&self) -> bool {
884 self.collected_typerefs
885 }
886
887 /// Gather all the unresolved type references.
888 fn collect_typerefs(
889 &mut self,
890 ) -> Vec<(ItemId, clang::Type, clang::Cursor, Option<ItemId>)> {
891 debug_assert!(!self.collected_typerefs);
892 self.collected_typerefs = true;
893 let mut typerefs = vec![];
894
895 for (id, item) in self.items() {
896 let kind = item.kind();
897 let ty = match kind.as_type() {
898 Some(ty) => ty,
899 None => continue,
900 };
901
902 if let TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) =
903 *ty.kind()
904 {
905 typerefs.push((id, *ty, loc, parent_id));
906 };
907 }
908 typerefs
909 }
910
911 /// Collect all of our unresolved type references and resolve them.
912 fn resolve_typerefs(&mut self) {
913 let _t = self.timer("resolve_typerefs");
914
915 let typerefs = self.collect_typerefs();
916
917 for (id, ty, loc, parent_id) in typerefs {
918 let _resolved =
919 {
920 let resolved = Item::from_ty(&ty, loc, parent_id, self)
921 .unwrap_or_else(|_| {
922 warn!("Could not resolve type reference, falling back \
923 to opaque blob");
924 Item::new_opaque_type(self.next_item_id(), &ty, self)
925 });
926
927 let item = self.items[id.0].as_mut().unwrap();
928 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
929 TypeKind::ResolvedTypeRef(resolved);
930 resolved
931 };
932
933 // Something in the STL is trolling me. I don't need this assertion
934 // right now, but worth investigating properly once this lands.
935 //
936 // debug_assert!(self.items.get(&resolved).is_some(), "How?");
937 //
938 // if let Some(parent_id) = parent_id {
939 // assert_eq!(self.items[&resolved].parent_id(), parent_id);
940 // }
941 }
942 }
943
944 /// Temporarily loan `Item` with the given `ItemId`. This provides means to
945 /// mutably borrow `Item` while having a reference to `BindgenContext`.
946 ///
947 /// `Item` with the given `ItemId` is removed from the context, given
948 /// closure is executed and then `Item` is placed back.
949 ///
950 /// # Panics
951 ///
952 /// Panics if attempt to resolve given `ItemId` inside the given
953 /// closure is made.
954 fn with_loaned_item<F, T>(&mut self, id: ItemId, f: F) -> T
955 where
956 F: (FnOnce(&BindgenContext, &mut Item) -> T),
957 {
958 let mut item = self.items[id.0].take().unwrap();
959
960 let result = f(self, &mut item);
961
962 let existing = mem::replace(&mut self.items[id.0], Some(item));
963 assert!(existing.is_none());
964
965 result
966 }
967
968 /// Compute the bitfield allocation units for all `TypeKind::Comp` items we
969 /// parsed.
970 fn compute_bitfield_units(&mut self) {
971 let _t = self.timer("compute_bitfield_units");
972
973 assert!(self.collected_typerefs());
974
975 let need_bitfield_allocation =
976 mem::take(&mut self.need_bitfield_allocation);
977 for id in need_bitfield_allocation {
978 self.with_loaned_item(id, |ctx, item| {
979 let ty = item.kind_mut().as_type_mut().unwrap();
980 let layout = ty.layout(ctx);
981 ty.as_comp_mut()
982 .unwrap()
983 .compute_bitfield_units(ctx, layout.as_ref());
984 });
985 }
986 }
987
988 /// Assign a new generated name for each anonymous field.
989 fn deanonymize_fields(&mut self) {
990 let _t = self.timer("deanonymize_fields");
991
992 let comp_item_ids: Vec<ItemId> = self
993 .items()
994 .filter_map(|(id, item)| {
995 if item.kind().as_type()?.is_comp() {
996 return Some(id);
997 }
998 None
999 })
1000 .collect();
1001
1002 for id in comp_item_ids {
1003 self.with_loaned_item(id, |ctx, item| {
1004 item.kind_mut()
1005 .as_type_mut()
1006 .unwrap()
1007 .as_comp_mut()
1008 .unwrap()
1009 .deanonymize_fields(ctx);
1010 });
1011 }
1012 }
1013
1014 /// Iterate over all items and replace any item that has been named in a
1015 /// `replaces="SomeType"` annotation with the replacement type.
1016 fn process_replacements(&mut self) {
1017 let _t = self.timer("process_replacements");
1018 if self.replacements.is_empty() {
1019 debug!("No replacements to process");
1020 return;
1021 }
1022
1023 // FIXME: This is linear, but the replaces="xxx" annotation was already
1024 // there, and for better or worse it's useful, sigh...
1025 //
1026 // We leverage the ResolvedTypeRef thing, though, which is cool :P.
1027
1028 let mut replacements = vec![];
1029
1030 for (id, item) in self.items() {
1031 if item.annotations().use_instead_of().is_some() {
1032 continue;
1033 }
1034
1035 // Calls to `canonical_name` are expensive, so eagerly filter out
1036 // items that cannot be replaced.
1037 let ty = match item.kind().as_type() {
1038 Some(ty) => ty,
1039 None => continue,
1040 };
1041
1042 match *ty.kind() {
1043 TypeKind::Comp(..) |
1044 TypeKind::TemplateAlias(..) |
1045 TypeKind::Enum(..) |
1046 TypeKind::Alias(..) => {}
1047 _ => continue,
1048 }
1049
1050 let path = item.path_for_allowlisting(self);
1051 let replacement = self.replacements.get(&path[1..]);
1052
1053 if let Some(replacement) = replacement {
1054 if *replacement != id {
1055 // We set this just after parsing the annotation. It's
1056 // very unlikely, but this can happen.
1057 if self.resolve_item_fallible(*replacement).is_some() {
1058 replacements.push((
1059 id.expect_type_id(self),
1060 replacement.expect_type_id(self),
1061 ));
1062 }
1063 }
1064 }
1065 }
1066
1067 for (id, replacement_id) in replacements {
1068 debug!("Replacing {:?} with {:?}", id, replacement_id);
1069 let new_parent = {
1070 let item_id: ItemId = id.into();
1071 let item = self.items[item_id.0].as_mut().unwrap();
1072 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
1073 TypeKind::ResolvedTypeRef(replacement_id);
1074 item.parent_id()
1075 };
1076
1077 // Relocate the replacement item from where it was declared, to
1078 // where the thing it is replacing was declared.
1079 //
1080 // First, we'll make sure that its parent id is correct.
1081
1082 let old_parent = self.resolve_item(replacement_id).parent_id();
1083 if new_parent == old_parent {
1084 // Same parent and therefore also same containing
1085 // module. Nothing to do here.
1086 continue;
1087 }
1088
1089 let replacement_item_id: ItemId = replacement_id.into();
1090 self.items[replacement_item_id.0]
1091 .as_mut()
1092 .unwrap()
1093 .set_parent_for_replacement(new_parent);
1094
1095 // Second, make sure that it is in the correct module's children
1096 // set.
1097
1098 let old_module = {
1099 let immut_self = &*self;
1100 old_parent
1101 .ancestors(immut_self)
1102 .chain(Some(immut_self.root_module.into()))
1103 .find(|id| {
1104 let item = immut_self.resolve_item(*id);
1105 item.as_module().map_or(false, |m| {
1106 m.children().contains(&replacement_id.into())
1107 })
1108 })
1109 };
1110 let old_module = old_module
1111 .expect("Every replacement item should be in a module");
1112
1113 let new_module = {
1114 let immut_self = &*self;
1115 new_parent
1116 .ancestors(immut_self)
1117 .find(|id| immut_self.resolve_item(*id).is_module())
1118 };
1119 let new_module =
1120 new_module.unwrap_or_else(|| self.root_module.into());
1121
1122 if new_module == old_module {
1123 // Already in the correct module.
1124 continue;
1125 }
1126
1127 self.items[old_module.0]
1128 .as_mut()
1129 .unwrap()
1130 .as_module_mut()
1131 .unwrap()
1132 .children_mut()
1133 .remove(&replacement_id.into());
1134
1135 self.items[new_module.0]
1136 .as_mut()
1137 .unwrap()
1138 .as_module_mut()
1139 .unwrap()
1140 .children_mut()
1141 .insert(replacement_id.into());
1142 }
1143 }
1144
1145 /// Enter the code generation phase, invoke the given callback `cb`, and
1146 /// leave the code generation phase.
1147 pub(crate) fn gen<F, Out>(
1148 mut self,
1149 cb: F,
1150 ) -> Result<(Out, BindgenOptions, Vec<String>), CodegenError>
1151 where
1152 F: FnOnce(&Self) -> Result<Out, CodegenError>,
1153 {
1154 self.in_codegen = true;
1155
1156 self.resolve_typerefs();
1157 self.compute_bitfield_units();
1158 self.process_replacements();
1159
1160 self.deanonymize_fields();
1161
1162 self.assert_no_dangling_references();
1163
1164 // Compute the allowlisted set after processing replacements and
1165 // resolving type refs, as those are the final mutations of the IR
1166 // graph, and their completion means that the IR graph is now frozen.
1167 self.compute_allowlisted_and_codegen_items();
1168
1169 // Make sure to do this after processing replacements, since that messes
1170 // with the parentage and module children, and we want to assert that it
1171 // messes with them correctly.
1172 self.assert_every_item_in_a_module();
1173
1174 self.compute_has_vtable();
1175 self.compute_sizedness();
1176 self.compute_has_destructor();
1177 self.find_used_template_parameters();
1178 self.compute_enum_typedef_combos();
1179 self.compute_cannot_derive_debug();
1180 self.compute_cannot_derive_default();
1181 self.compute_cannot_derive_copy();
1182 self.compute_has_type_param_in_array();
1183 self.compute_has_float();
1184 self.compute_cannot_derive_hash();
1185 self.compute_cannot_derive_partialord_partialeq_or_eq();
1186
1187 let ret = cb(&self)?;
1188 Ok((ret, self.options, self.warnings))
1189 }
1190
1191 /// When the `testing_only_extra_assertions` feature is enabled, this
1192 /// function walks the IR graph and asserts that we do not have any edges
1193 /// referencing an ItemId for which we do not have an associated IR item.
1194 fn assert_no_dangling_references(&self) {
1195 if cfg!(feature = "testing_only_extra_assertions") {
1196 for _ in self.assert_no_dangling_item_traversal() {
1197 // The iterator's next method does the asserting for us.
1198 }
1199 }
1200 }
1201
1202 fn assert_no_dangling_item_traversal(
1203 &self,
1204 ) -> traversal::AssertNoDanglingItemsTraversal {
1205 assert!(self.in_codegen_phase());
1206 assert!(self.current_module == self.root_module);
1207
1208 let roots = self.items().map(|(id, _)| id);
1209 traversal::AssertNoDanglingItemsTraversal::new(
1210 self,
1211 roots,
1212 traversal::all_edges,
1213 )
1214 }
1215
1216 /// When the `testing_only_extra_assertions` feature is enabled, walk over
1217 /// every item and ensure that it is in the children set of one of its
1218 /// module ancestors.
1219 fn assert_every_item_in_a_module(&self) {
1220 if cfg!(feature = "testing_only_extra_assertions") {
1221 assert!(self.in_codegen_phase());
1222 assert!(self.current_module == self.root_module);
1223
1224 for (id, _item) in self.items() {
1225 if id == self.root_module {
1226 continue;
1227 }
1228
1229 assert!(
1230 {
1231 let id = id
1232 .into_resolver()
1233 .through_type_refs()
1234 .through_type_aliases()
1235 .resolve(self)
1236 .id();
1237 id.ancestors(self)
1238 .chain(Some(self.root_module.into()))
1239 .any(|ancestor| {
1240 debug!(
1241 "Checking if {:?} is a child of {:?}",
1242 id, ancestor
1243 );
1244 self.resolve_item(ancestor)
1245 .as_module()
1246 .map_or(false, |m| {
1247 m.children().contains(&id)
1248 })
1249 })
1250 },
1251 "{:?} should be in some ancestor module's children set",
1252 id
1253 );
1254 }
1255 }
1256 }
1257
1258 /// Compute for every type whether it is sized or not, and whether it is
1259 /// sized or not as a base class.
1260 fn compute_sizedness(&mut self) {
1261 let _t = self.timer("compute_sizedness");
1262 assert!(self.sizedness.is_none());
1263 self.sizedness = Some(analyze::<SizednessAnalysis>(self));
1264 }
1265
1266 /// Look up whether the type with the given id is sized or not.
1267 pub fn lookup_sizedness(&self, id: TypeId) -> SizednessResult {
1268 assert!(
1269 self.in_codegen_phase(),
1270 "We only compute sizedness after we've entered codegen"
1271 );
1272
1273 self.sizedness
1274 .as_ref()
1275 .unwrap()
1276 .get(&id)
1277 .cloned()
1278 .unwrap_or(SizednessResult::ZeroSized)
1279 }
1280
1281 /// Compute whether the type has vtable.
1282 fn compute_has_vtable(&mut self) {
1283 let _t = self.timer("compute_has_vtable");
1284 assert!(self.have_vtable.is_none());
1285 self.have_vtable = Some(analyze::<HasVtableAnalysis>(self));
1286 }
1287
1288 /// Look up whether the item with `id` has vtable or not.
1289 pub fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult {
1290 assert!(
1291 self.in_codegen_phase(),
1292 "We only compute vtables when we enter codegen"
1293 );
1294
1295 // Look up the computed value for whether the item with `id` has a
1296 // vtable or not.
1297 self.have_vtable
1298 .as_ref()
1299 .unwrap()
1300 .get(&id.into())
1301 .cloned()
1302 .unwrap_or(HasVtableResult::No)
1303 }
1304
1305 /// Compute whether the type has a destructor.
1306 fn compute_has_destructor(&mut self) {
1307 let _t = self.timer("compute_has_destructor");
1308 assert!(self.have_destructor.is_none());
1309 self.have_destructor = Some(analyze::<HasDestructorAnalysis>(self));
1310 }
1311
1312 /// Look up whether the item with `id` has a destructor.
1313 pub fn lookup_has_destructor(&self, id: TypeId) -> bool {
1314 assert!(
1315 self.in_codegen_phase(),
1316 "We only compute destructors when we enter codegen"
1317 );
1318
1319 self.have_destructor.as_ref().unwrap().contains(&id.into())
1320 }
1321
1322 fn find_used_template_parameters(&mut self) {
1323 let _t = self.timer("find_used_template_parameters");
1324 if self.options.allowlist_recursively {
1325 let used_params = analyze::<UsedTemplateParameters>(self);
1326 self.used_template_parameters = Some(used_params);
1327 } else {
1328 // If you aren't recursively allowlisting, then we can't really make
1329 // any sense of template parameter usage, and you're on your own.
1330 let mut used_params = HashMap::default();
1331 for &id in self.allowlisted_items() {
1332 used_params.entry(id).or_insert_with(|| {
1333 id.self_template_params(self)
1334 .into_iter()
1335 .map(|p| p.into())
1336 .collect()
1337 });
1338 }
1339 self.used_template_parameters = Some(used_params);
1340 }
1341 }
1342
1343 /// Return `true` if `item` uses the given `template_param`, `false`
1344 /// otherwise.
1345 ///
1346 /// This method may only be called during the codegen phase, because the
1347 /// template usage information is only computed as we enter the codegen
1348 /// phase.
1349 ///
1350 /// If the item is blocklisted, then we say that it always uses the template
1351 /// parameter. This is a little subtle. The template parameter usage
1352 /// analysis only considers allowlisted items, and if any blocklisted item
1353 /// shows up in the generated bindings, it is the user's responsibility to
1354 /// manually provide a definition for them. To give them the most
1355 /// flexibility when doing that, we assume that they use every template
1356 /// parameter and always pass template arguments through in instantiations.
1357 pub fn uses_template_parameter(
1358 &self,
1359 item: ItemId,
1360 template_param: TypeId,
1361 ) -> bool {
1362 assert!(
1363 self.in_codegen_phase(),
1364 "We only compute template parameter usage as we enter codegen"
1365 );
1366
1367 if self.resolve_item(item).is_blocklisted(self) {
1368 return true;
1369 }
1370
1371 let template_param = template_param
1372 .into_resolver()
1373 .through_type_refs()
1374 .through_type_aliases()
1375 .resolve(self)
1376 .id();
1377
1378 self.used_template_parameters
1379 .as_ref()
1380 .expect("should have found template parameter usage if we're in codegen")
1381 .get(&item)
1382 .map_or(false, |items_used_params| items_used_params.contains(&template_param))
1383 }
1384
1385 /// Return `true` if `item` uses any unbound, generic template parameters,
1386 /// `false` otherwise.
1387 ///
1388 /// Has the same restrictions that `uses_template_parameter` has.
1389 pub fn uses_any_template_parameters(&self, item: ItemId) -> bool {
1390 assert!(
1391 self.in_codegen_phase(),
1392 "We only compute template parameter usage as we enter codegen"
1393 );
1394
1395 self.used_template_parameters
1396 .as_ref()
1397 .expect(
1398 "should have template parameter usage info in codegen phase",
1399 )
1400 .get(&item)
1401 .map_or(false, |used| !used.is_empty())
1402 }
1403
1404 // This deserves a comment. Builtin types don't get a valid declaration, so
1405 // we can't add it to the cursor->type map.
1406 //
1407 // That being said, they're not generated anyway, and are few, so the
1408 // duplication and special-casing is fine.
1409 //
1410 // If at some point we care about the memory here, probably a map TypeKind
1411 // -> builtin type ItemId would be the best to improve that.
1412 fn add_builtin_item(&mut self, item: Item) {
1413 debug!("add_builtin_item: item = {:?}", item);
1414 debug_assert!(item.kind().is_type());
1415 self.add_item_to_module(&item);
1416 let id = item.id();
1417 let old_item = mem::replace(&mut self.items[id.0], Some(item));
1418 assert!(old_item.is_none(), "Inserted type twice?");
1419 }
1420
1421 fn build_root_module(id: ItemId) -> Item {
1422 let module = Module::new(Some("root".into()), ModuleKind::Normal);
1423 Item::new(id, None, None, id, ItemKind::Module(module), None)
1424 }
1425
1426 /// Get the root module.
1427 pub fn root_module(&self) -> ModuleId {
1428 self.root_module
1429 }
1430
1431 /// Resolve a type with the given id.
1432 ///
1433 /// Panics if there is no item for the given `TypeId` or if the resolved
1434 /// item is not a `Type`.
1435 pub fn resolve_type(&self, type_id: TypeId) -> &Type {
1436 self.resolve_item(type_id).kind().expect_type()
1437 }
1438
1439 /// Resolve a function with the given id.
1440 ///
1441 /// Panics if there is no item for the given `FunctionId` or if the resolved
1442 /// item is not a `Function`.
1443 pub fn resolve_func(&self, func_id: FunctionId) -> &Function {
1444 self.resolve_item(func_id).kind().expect_function()
1445 }
1446
1447 /// Resolve the given `ItemId` as a type, or `None` if there is no item with
1448 /// the given id.
1449 ///
1450 /// Panics if the id resolves to an item that is not a type.
1451 pub fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
1452 self.resolve_item_fallible(type_id)
1453 .map(|t| t.kind().expect_type())
1454 }
1455
1456 /// Resolve the given `ItemId` into an `Item`, or `None` if no such item
1457 /// exists.
1458 pub fn resolve_item_fallible<Id: Into<ItemId>>(
1459 &self,
1460 id: Id,
1461 ) -> Option<&Item> {
1462 self.items.get(id.into().0)?.as_ref()
1463 }
1464
1465 /// Resolve the given `ItemId` into an `Item`.
1466 ///
1467 /// Panics if the given id does not resolve to any item.
1468 pub fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
1469 let item_id = item_id.into();
1470 match self.resolve_item_fallible(item_id) {
1471 Some(item) => item,
1472 None => panic!("Not an item: {:?}", item_id),
1473 }
1474 }
1475
1476 /// Get the current module.
1477 pub fn current_module(&self) -> ModuleId {
1478 self.current_module
1479 }
1480
1481 /// Add a semantic parent for a given type definition.
1482 ///
1483 /// We do this from the type declaration, in order to be able to find the
1484 /// correct type definition afterwards.
1485 ///
1486 /// TODO(emilio): We could consider doing this only when
1487 /// declaration.lexical_parent() != definition.lexical_parent(), but it's
1488 /// not sure it's worth it.
1489 pub fn add_semantic_parent(
1490 &mut self,
1491 definition: clang::Cursor,
1492 parent_id: ItemId,
1493 ) {
1494 self.semantic_parents.insert(definition, parent_id);
1495 }
1496
1497 /// Returns a known semantic parent for a given definition.
1498 pub fn known_semantic_parent(
1499 &self,
1500 definition: clang::Cursor,
1501 ) -> Option<ItemId> {
1502 self.semantic_parents.get(&definition).cloned()
1503 }
1504
1505 /// Given a cursor pointing to the location of a template instantiation,
1506 /// return a tuple of the form `(declaration_cursor, declaration_id,
1507 /// num_expected_template_args)`.
1508 ///
1509 /// Note that `declaration_id` is not guaranteed to be in the context's item
1510 /// set! It is possible that it is a partial type that we are still in the
1511 /// middle of parsing.
1512 fn get_declaration_info_for_template_instantiation(
1513 &self,
1514 instantiation: &Cursor,
1515 ) -> Option<(Cursor, ItemId, usize)> {
1516 instantiation
1517 .cur_type()
1518 .canonical_declaration(Some(instantiation))
1519 .and_then(|canon_decl| {
1520 self.get_resolved_type(&canon_decl).and_then(
1521 |template_decl_id| {
1522 let num_params =
1523 template_decl_id.num_self_template_params(self);
1524 if num_params == 0 {
1525 None
1526 } else {
1527 Some((
1528 *canon_decl.cursor(),
1529 template_decl_id.into(),
1530 num_params,
1531 ))
1532 }
1533 },
1534 )
1535 })
1536 .or_else(|| {
1537 // If we haven't already parsed the declaration of
1538 // the template being instantiated, then it *must*
1539 // be on the stack of types we are currently
1540 // parsing. If it wasn't then clang would have
1541 // already errored out before we started
1542 // constructing our IR because you can't instantiate
1543 // a template until it is fully defined.
1544 instantiation
1545 .referenced()
1546 .and_then(|referenced| {
1547 self.currently_parsed_types()
1548 .iter()
1549 .find(|partial_ty| *partial_ty.decl() == referenced)
1550 .cloned()
1551 })
1552 .and_then(|template_decl| {
1553 let num_template_params =
1554 template_decl.num_self_template_params(self);
1555 if num_template_params == 0 {
1556 None
1557 } else {
1558 Some((
1559 *template_decl.decl(),
1560 template_decl.id(),
1561 num_template_params,
1562 ))
1563 }
1564 })
1565 })
1566 }
1567
1568 /// Parse a template instantiation, eg `Foo<int>`.
1569 ///
1570 /// This is surprisingly difficult to do with libclang, due to the fact that
1571 /// it doesn't provide explicit template argument information, except for
1572 /// function template declarations(!?!??!).
1573 ///
1574 /// The only way to do this is manually inspecting the AST and looking for
1575 /// TypeRefs and TemplateRefs inside. This, unfortunately, doesn't work for
1576 /// more complex cases, see the comment on the assertion below.
1577 ///
1578 /// To add insult to injury, the AST itself has structure that doesn't make
1579 /// sense. Sometimes `Foo<Bar<int>>` has an AST with nesting like you might
1580 /// expect: `(Foo (Bar (int)))`. Other times, the AST we get is completely
1581 /// flat: `(Foo Bar int)`.
1582 ///
1583 /// To see an example of what this method handles:
1584 ///
1585 /// ```c++
1586 /// template<typename T>
1587 /// class Incomplete {
1588 /// T p;
1589 /// };
1590 ///
1591 /// template<typename U>
1592 /// class Foo {
1593 /// Incomplete<U> bar;
1594 /// };
1595 /// ```
1596 ///
1597 /// Finally, template instantiations are always children of the current
1598 /// module. They use their template's definition for their name, so the
1599 /// parent is only useful for ensuring that their layout tests get
1600 /// codegen'd.
1601 fn instantiate_template(
1602 &mut self,
1603 with_id: ItemId,
1604 template: TypeId,
1605 ty: &clang::Type,
1606 location: clang::Cursor,
1607 ) -> Option<TypeId> {
1608 let num_expected_args =
1609 self.resolve_type(template).num_self_template_params(self);
1610 if num_expected_args == 0 {
1611 warn!(
1612 "Tried to instantiate a template for which we could not \
1613 determine any template parameters"
1614 );
1615 return None;
1616 }
1617
1618 let mut args = vec![];
1619 let mut found_const_arg = false;
1620 let mut children = location.collect_children();
1621
1622 if children.iter().all(|c| !c.has_children()) {
1623 // This is insanity... If clang isn't giving us a properly nested
1624 // AST for which template arguments belong to which template we are
1625 // instantiating, we'll need to construct it ourselves. However,
1626 // there is an extra `NamespaceRef, NamespaceRef, ..., TemplateRef`
1627 // representing a reference to the outermost template declaration
1628 // that we need to filter out of the children. We need to do this
1629 // filtering because we already know which template declaration is
1630 // being specialized via the `location`'s type, and if we do not
1631 // filter it out, we'll add an extra layer of template instantiation
1632 // on accident.
1633 let idx = children
1634 .iter()
1635 .position(|c| c.kind() == clang_sys::CXCursor_TemplateRef);
1636 if let Some(idx) = idx {
1637 if children
1638 .iter()
1639 .take(idx)
1640 .all(|c| c.kind() == clang_sys::CXCursor_NamespaceRef)
1641 {
1642 children = children.into_iter().skip(idx + 1).collect();
1643 }
1644 }
1645 }
1646
1647 for child in children.iter().rev() {
1648 match child.kind() {
1649 clang_sys::CXCursor_TypeRef |
1650 clang_sys::CXCursor_TypedefDecl |
1651 clang_sys::CXCursor_TypeAliasDecl => {
1652 // The `with_id` id will potentially end up unused if we give up
1653 // on this type (for example, because it has const value
1654 // template args), so if we pass `with_id` as the parent, it is
1655 // potentially a dangling reference. Instead, use the canonical
1656 // template declaration as the parent. It is already parsed and
1657 // has a known-resolvable `ItemId`.
1658 let ty = Item::from_ty_or_ref(
1659 child.cur_type(),
1660 *child,
1661 Some(template.into()),
1662 self,
1663 );
1664 args.push(ty);
1665 }
1666 clang_sys::CXCursor_TemplateRef => {
1667 let (
1668 template_decl_cursor,
1669 template_decl_id,
1670 num_expected_template_args,
1671 ) = self.get_declaration_info_for_template_instantiation(
1672 child,
1673 )?;
1674
1675 if num_expected_template_args == 0 ||
1676 child.has_at_least_num_children(
1677 num_expected_template_args,
1678 )
1679 {
1680 // Do a happy little parse. See comment in the TypeRef
1681 // match arm about parent IDs.
1682 let ty = Item::from_ty_or_ref(
1683 child.cur_type(),
1684 *child,
1685 Some(template.into()),
1686 self,
1687 );
1688 args.push(ty);
1689 } else {
1690 // This is the case mentioned in the doc comment where
1691 // clang gives us a flattened AST and we have to
1692 // reconstruct which template arguments go to which
1693 // instantiation :(
1694 let args_len = args.len();
1695 if args_len < num_expected_template_args {
1696 warn!(
1697 "Found a template instantiation without \
1698 enough template arguments"
1699 );
1700 return None;
1701 }
1702
1703 let mut sub_args: Vec<_> = args
1704 .drain(args_len - num_expected_template_args..)
1705 .collect();
1706 sub_args.reverse();
1707
1708 let sub_name = Some(template_decl_cursor.spelling());
1709 let sub_inst = TemplateInstantiation::new(
1710 // This isn't guaranteed to be a type that we've
1711 // already finished parsing yet.
1712 template_decl_id.as_type_id_unchecked(),
1713 sub_args,
1714 );
1715 let sub_kind =
1716 TypeKind::TemplateInstantiation(sub_inst);
1717 let sub_ty = Type::new(
1718 sub_name,
1719 template_decl_cursor
1720 .cur_type()
1721 .fallible_layout(self)
1722 .ok(),
1723 sub_kind,
1724 false,
1725 );
1726 let sub_id = self.next_item_id();
1727 let sub_item = Item::new(
1728 sub_id,
1729 None,
1730 None,
1731 self.current_module.into(),
1732 ItemKind::Type(sub_ty),
1733 Some(child.location()),
1734 );
1735
1736 // Bypass all the validations in add_item explicitly.
1737 debug!(
1738 "instantiate_template: inserting nested \
1739 instantiation item: {:?}",
1740 sub_item
1741 );
1742 self.add_item_to_module(&sub_item);
1743 debug_assert_eq!(sub_id, sub_item.id());
1744 self.items[sub_id.0] = Some(sub_item);
1745 args.push(sub_id.as_type_id_unchecked());
1746 }
1747 }
1748 _ => {
1749 warn!(
1750 "Found template arg cursor we can't handle: {:?}",
1751 child
1752 );
1753 found_const_arg = true;
1754 }
1755 }
1756 }
1757
1758 if found_const_arg {
1759 // This is a dependently typed template instantiation. That is, an
1760 // instantiation of a template with one or more const values as
1761 // template arguments, rather than only types as template
1762 // arguments. For example, `Foo<true, 5>` versus `Bar<bool, int>`.
1763 // We can't handle these instantiations, so just punt in this
1764 // situation...
1765 warn!(
1766 "Found template instantiated with a const value; \
1767 bindgen can't handle this kind of template instantiation!"
1768 );
1769 return None;
1770 }
1771
1772 if args.len() != num_expected_args {
1773 warn!(
1774 "Found a template with an unexpected number of template \
1775 arguments"
1776 );
1777 return None;
1778 }
1779
1780 args.reverse();
1781 let type_kind = TypeKind::TemplateInstantiation(
1782 TemplateInstantiation::new(template, args),
1783 );
1784 let name = ty.spelling();
1785 let name = if name.is_empty() { None } else { Some(name) };
1786 let ty = Type::new(
1787 name,
1788 ty.fallible_layout(self).ok(),
1789 type_kind,
1790 ty.is_const(),
1791 );
1792 let item = Item::new(
1793 with_id,
1794 None,
1795 None,
1796 self.current_module.into(),
1797 ItemKind::Type(ty),
1798 Some(location.location()),
1799 );
1800
1801 // Bypass all the validations in add_item explicitly.
1802 debug!("instantiate_template: inserting item: {:?}", item);
1803 self.add_item_to_module(&item);
1804 debug_assert_eq!(with_id, item.id());
1805 self.items[with_id.0] = Some(item);
1806 Some(with_id.as_type_id_unchecked())
1807 }
1808
1809 /// If we have already resolved the type for the given type declaration,
1810 /// return its `ItemId`. Otherwise, return `None`.
1811 pub fn get_resolved_type(
1812 &self,
1813 decl: &clang::CanonicalTypeDeclaration,
1814 ) -> Option<TypeId> {
1815 self.types
1816 .get(&TypeKey::Declaration(*decl.cursor()))
1817 .or_else(|| {
1818 decl.cursor()
1819 .usr()
1820 .and_then(|usr| self.types.get(&TypeKey::Usr(usr)))
1821 })
1822 .cloned()
1823 }
1824
1825 /// Looks up for an already resolved type, either because it's builtin, or
1826 /// because we already have it in the map.
1827 pub fn builtin_or_resolved_ty(
1828 &mut self,
1829 with_id: ItemId,
1830 parent_id: Option<ItemId>,
1831 ty: &clang::Type,
1832 location: Option<clang::Cursor>,
1833 ) -> Option<TypeId> {
1834 use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
1835 debug!(
1836 "builtin_or_resolved_ty: {:?}, {:?}, {:?}, {:?}",
1837 ty, location, with_id, parent_id
1838 );
1839
1840 if let Some(decl) = ty.canonical_declaration(location.as_ref()) {
1841 if let Some(id) = self.get_resolved_type(&decl) {
1842 debug!(
1843 "Already resolved ty {:?}, {:?}, {:?} {:?}",
1844 id, decl, ty, location
1845 );
1846 // If the declaration already exists, then either:
1847 //
1848 // * the declaration is a template declaration of some sort,
1849 // and we are looking at an instantiation or specialization
1850 // of it, or
1851 // * we have already parsed and resolved this type, and
1852 // there's nothing left to do.
1853 if let Some(location) = location {
1854 if decl.cursor().is_template_like() &&
1855 *ty != decl.cursor().cur_type()
1856 {
1857 // For specialized type aliases, there's no way to get the
1858 // template parameters as of this writing (for a struct
1859 // specialization we wouldn't be in this branch anyway).
1860 //
1861 // Explicitly return `None` if there aren't any
1862 // unspecialized parameters (contains any `TypeRef`) so we
1863 // resolve the canonical type if there is one and it's
1864 // exposed.
1865 //
1866 // This is _tricky_, I know :(
1867 if decl.cursor().kind() ==
1868 CXCursor_TypeAliasTemplateDecl &&
1869 !location.contains_cursor(CXCursor_TypeRef) &&
1870 ty.canonical_type().is_valid_and_exposed()
1871 {
1872 return None;
1873 }
1874
1875 return self
1876 .instantiate_template(with_id, id, ty, location)
1877 .or(Some(id));
1878 }
1879 }
1880
1881 return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
1882 }
1883 }
1884
1885 debug!("Not resolved, maybe builtin?");
1886 self.build_builtin_ty(ty)
1887 }
1888
1889 /// Make a new item that is a resolved type reference to the `wrapped_id`.
1890 ///
1891 /// This is unfortunately a lot of bloat, but is needed to properly track
1892 /// constness et al.
1893 ///
1894 /// We should probably make the constness tracking separate, so it doesn't
1895 /// bloat that much, but hey, we already bloat the heck out of builtin
1896 /// types.
1897 pub fn build_ty_wrapper(
1898 &mut self,
1899 with_id: ItemId,
1900 wrapped_id: TypeId,
1901 parent_id: Option<ItemId>,
1902 ty: &clang::Type,
1903 ) -> TypeId {
1904 self.build_wrapper(with_id, wrapped_id, parent_id, ty, ty.is_const())
1905 }
1906
1907 /// A wrapper over a type that adds a const qualifier explicitly.
1908 ///
1909 /// Needed to handle const methods in C++, wrapping the type .
1910 pub fn build_const_wrapper(
1911 &mut self,
1912 with_id: ItemId,
1913 wrapped_id: TypeId,
1914 parent_id: Option<ItemId>,
1915 ty: &clang::Type,
1916 ) -> TypeId {
1917 self.build_wrapper(
1918 with_id, wrapped_id, parent_id, ty, /* is_const = */ true,
1919 )
1920 }
1921
1922 fn build_wrapper(
1923 &mut self,
1924 with_id: ItemId,
1925 wrapped_id: TypeId,
1926 parent_id: Option<ItemId>,
1927 ty: &clang::Type,
1928 is_const: bool,
1929 ) -> TypeId {
1930 let spelling = ty.spelling();
1931 let layout = ty.fallible_layout(self).ok();
1932 let location = ty.declaration().location();
1933 let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
1934 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
1935 let item = Item::new(
1936 with_id,
1937 None,
1938 None,
1939 parent_id.unwrap_or_else(|| self.current_module.into()),
1940 ItemKind::Type(ty),
1941 Some(location),
1942 );
1943 self.add_builtin_item(item);
1944 with_id.as_type_id_unchecked()
1945 }
1946
1947 /// Returns the next item id to be used for an item.
1948 pub fn next_item_id(&mut self) -> ItemId {
1949 let ret = ItemId(self.items.len());
1950 self.items.push(None);
1951 ret
1952 }
1953
1954 fn build_builtin_ty(&mut self, ty: &clang::Type) -> Option<TypeId> {
1955 use clang_sys::*;
1956 let type_kind = match ty.kind() {
1957 CXType_NullPtr => TypeKind::NullPtr,
1958 CXType_Void => TypeKind::Void,
1959 CXType_Bool => TypeKind::Int(IntKind::Bool),
1960 CXType_Int => TypeKind::Int(IntKind::Int),
1961 CXType_UInt => TypeKind::Int(IntKind::UInt),
1962 CXType_Char_S => TypeKind::Int(IntKind::Char { is_signed: true }),
1963 CXType_Char_U => TypeKind::Int(IntKind::Char { is_signed: false }),
1964 CXType_SChar => TypeKind::Int(IntKind::SChar),
1965 CXType_UChar => TypeKind::Int(IntKind::UChar),
1966 CXType_Short => TypeKind::Int(IntKind::Short),
1967 CXType_UShort => TypeKind::Int(IntKind::UShort),
1968 CXType_WChar => TypeKind::Int(IntKind::WChar),
1969 CXType_Char16 => TypeKind::Int(IntKind::U16),
1970 CXType_Char32 => TypeKind::Int(IntKind::U32),
1971 CXType_Long => TypeKind::Int(IntKind::Long),
1972 CXType_ULong => TypeKind::Int(IntKind::ULong),
1973 CXType_LongLong => TypeKind::Int(IntKind::LongLong),
1974 CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
1975 CXType_Int128 => TypeKind::Int(IntKind::I128),
1976 CXType_UInt128 => TypeKind::Int(IntKind::U128),
1977 CXType_Float => TypeKind::Float(FloatKind::Float),
1978 CXType_Double => TypeKind::Float(FloatKind::Double),
1979 CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
1980 CXType_Float128 => TypeKind::Float(FloatKind::Float128),
1981 CXType_Complex => {
1982 let float_type =
1983 ty.elem_type().expect("Not able to resolve complex type?");
1984 let float_kind = match float_type.kind() {
1985 CXType_Float => FloatKind::Float,
1986 CXType_Double => FloatKind::Double,
1987 CXType_LongDouble => FloatKind::LongDouble,
1988 CXType_Float128 => FloatKind::Float128,
1989 _ => panic!(
1990 "Non floating-type complex? {:?}, {:?}",
1991 ty, float_type,
1992 ),
1993 };
1994 TypeKind::Complex(float_kind)
1995 }
1996 _ => return None,
1997 };
1998
1999 let spelling = ty.spelling();
2000 let is_const = ty.is_const();
2001 let layout = ty.fallible_layout(self).ok();
2002 let location = ty.declaration().location();
2003 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
2004 let id = self.next_item_id();
2005 let item = Item::new(
2006 id,
2007 None,
2008 None,
2009 self.root_module.into(),
2010 ItemKind::Type(ty),
2011 Some(location),
2012 );
2013 self.add_builtin_item(item);
2014 Some(id.as_type_id_unchecked())
2015 }
2016
2017 /// Get the current Clang translation unit that is being processed.
2018 pub fn translation_unit(&self) -> &clang::TranslationUnit {
2019 &self.translation_unit
2020 }
2021
2022 /// Have we parsed the macro named `macro_name` already?
2023 pub fn parsed_macro(&self, macro_name: &[u8]) -> bool {
2024 self.parsed_macros.contains_key(macro_name)
2025 }
2026
2027 /// Get the currently parsed macros.
2028 pub fn parsed_macros(
2029 &self,
2030 ) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult> {
2031 debug_assert!(!self.in_codegen_phase());
2032 &self.parsed_macros
2033 }
2034
2035 /// Mark the macro named `macro_name` as parsed.
2036 pub fn note_parsed_macro(
2037 &mut self,
2038 id: Vec<u8>,
2039 value: cexpr::expr::EvalResult,
2040 ) {
2041 self.parsed_macros.insert(id, value);
2042 }
2043
2044 /// Are we in the codegen phase?
2045 pub fn in_codegen_phase(&self) -> bool {
2046 self.in_codegen
2047 }
2048
2049 /// Mark the type with the given `name` as replaced by the type with id
2050 /// `potential_ty`.
2051 ///
2052 /// Replacement types are declared using the `replaces="xxx"` annotation,
2053 /// and implies that the original type is hidden.
2054 pub fn replace(&mut self, name: &[String], potential_ty: ItemId) {
2055 match self.replacements.entry(name.into()) {
2056 Entry::Vacant(entry) => {
2057 debug!(
2058 "Defining replacement for {:?} as {:?}",
2059 name, potential_ty
2060 );
2061 entry.insert(potential_ty);
2062 }
2063 Entry::Occupied(occupied) => {
2064 warn!(
2065 "Replacement for {:?} already defined as {:?}; \
2066 ignoring duplicate replacement definition as {:?}",
2067 name,
2068 occupied.get(),
2069 potential_ty
2070 );
2071 }
2072 }
2073 }
2074
2075 /// Has the item with the given `name` and `id` been replaced by another
2076 /// type?
2077 pub fn is_replaced_type<Id: Into<ItemId>>(
2078 &self,
2079 path: &[String],
2080 id: Id,
2081 ) -> bool {
2082 let id = id.into();
2083 matches!(self.replacements.get(path), Some(replaced_by) if *replaced_by != id)
2084 }
2085
2086 /// Is the type with the given `name` marked as opaque?
2087 pub fn opaque_by_name(&self, path: &[String]) -> bool {
2088 debug_assert!(
2089 self.in_codegen_phase(),
2090 "You're not supposed to call this yet"
2091 );
2092 self.options.opaque_types.matches(path[1..].join("::"))
2093 }
2094
2095 /// Get the options used to configure this bindgen context.
2096 pub(crate) fn options(&self) -> &BindgenOptions {
2097 &self.options
2098 }
2099
2100 /// Tokenizes a namespace cursor in order to get the name and kind of the
2101 /// namespace.
2102 fn tokenize_namespace(
2103 &self,
2104 cursor: &clang::Cursor,
2105 ) -> (Option<String>, ModuleKind) {
2106 assert_eq!(
2107 cursor.kind(),
2108 ::clang_sys::CXCursor_Namespace,
2109 "Be a nice person"
2110 );
2111
2112 let mut module_name = None;
2113 let spelling = cursor.spelling();
2114 if !spelling.is_empty() {
2115 module_name = Some(spelling)
2116 }
2117
2118 let mut kind = ModuleKind::Normal;
2119 let mut looking_for_name = false;
2120 for token in cursor.tokens().iter() {
2121 match token.spelling() {
2122 b"inline" => {
2123 debug_assert!(
2124 kind != ModuleKind::Inline,
2125 "Multiple inline keywords?"
2126 );
2127 kind = ModuleKind::Inline;
2128 // When hitting a nested inline namespace we get a spelling
2129 // that looks like ["inline", "foo"]. Deal with it properly.
2130 looking_for_name = true;
2131 }
2132 // The double colon allows us to handle nested namespaces like
2133 // namespace foo::bar { }
2134 //
2135 // libclang still gives us two namespace cursors, which is cool,
2136 // but the tokenization of the second begins with the double
2137 // colon. That's ok, so we only need to handle the weird
2138 // tokenization here.
2139 b"namespace" | b"::" => {
2140 looking_for_name = true;
2141 }
2142 b"{" => {
2143 // This should be an anonymous namespace.
2144 assert!(looking_for_name);
2145 break;
2146 }
2147 name => {
2148 if looking_for_name {
2149 if module_name.is_none() {
2150 module_name = Some(
2151 String::from_utf8_lossy(name).into_owned(),
2152 );
2153 }
2154 break;
2155 } else {
2156 // This is _likely_, but not certainly, a macro that's
2157 // been placed just before the namespace keyword.
2158 // Unfortunately, clang tokens don't let us easily see
2159 // through the ifdef tokens, so we don't know what this
2160 // token should really be. Instead of panicking though,
2161 // we warn the user that we assumed the token was blank,
2162 // and then move on.
2163 //
2164 // See also https://github.com/rust-lang/rust-bindgen/issues/1676.
2165 warn!(
2166 "Ignored unknown namespace prefix '{}' at {:?} in {:?}",
2167 String::from_utf8_lossy(name),
2168 token,
2169 cursor
2170 );
2171 }
2172 }
2173 }
2174 }
2175
2176 (module_name, kind)
2177 }
2178
2179 /// Given a CXCursor_Namespace cursor, return the item id of the
2180 /// corresponding module, or create one on the fly.
2181 pub fn module(&mut self, cursor: clang::Cursor) -> ModuleId {
2182 use clang_sys::*;
2183 assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person");
2184 let cursor = cursor.canonical();
2185 if let Some(id) = self.modules.get(&cursor) {
2186 return *id;
2187 }
2188
2189 let (module_name, kind) = self.tokenize_namespace(&cursor);
2190
2191 let module_id = self.next_item_id();
2192 let module = Module::new(module_name, kind);
2193 let module = Item::new(
2194 module_id,
2195 None,
2196 None,
2197 self.current_module.into(),
2198 ItemKind::Module(module),
2199 Some(cursor.location()),
2200 );
2201
2202 let module_id = module.id().as_module_id_unchecked();
2203 self.modules.insert(cursor, module_id);
2204
2205 self.add_item(module, None, None);
2206
2207 module_id
2208 }
2209
2210 /// Start traversing the module with the given `module_id`, invoke the
2211 /// callback `cb`, and then return to traversing the original module.
2212 pub fn with_module<F>(&mut self, module_id: ModuleId, cb: F)
2213 where
2214 F: FnOnce(&mut Self),
2215 {
2216 debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat");
2217
2218 let previous_id = self.current_module;
2219 self.current_module = module_id;
2220
2221 cb(self);
2222
2223 self.current_module = previous_id;
2224 }
2225
2226 /// Iterate over all (explicitly or transitively) allowlisted items.
2227 ///
2228 /// If no items are explicitly allowlisted, then all items are considered
2229 /// allowlisted.
2230 pub fn allowlisted_items(&self) -> &ItemSet {
2231 assert!(self.in_codegen_phase());
2232 assert!(self.current_module == self.root_module);
2233
2234 self.allowlisted.as_ref().unwrap()
2235 }
2236
2237 /// Check whether a particular blocklisted type implements a trait or not.
2238 /// Results may be cached.
2239 pub fn blocklisted_type_implements_trait(
2240 &self,
2241 item: &Item,
2242 derive_trait: DeriveTrait,
2243 ) -> CanDerive {
2244 assert!(self.in_codegen_phase());
2245 assert!(self.current_module == self.root_module);
2246
2247 *self
2248 .blocklisted_types_implement_traits
2249 .borrow_mut()
2250 .entry(derive_trait)
2251 .or_default()
2252 .entry(item.id())
2253 .or_insert_with(|| {
2254 item.expect_type()
2255 .name()
2256 .and_then(|name| {
2257 if self.options.parse_callbacks.is_empty() {
2258 // Sized integer types from <stdint.h> get mapped to Rust primitive
2259 // types regardless of whether they are blocklisted, so ensure that
2260 // standard traits are considered derivable for them too.
2261 if self.is_stdint_type(name) {
2262 Some(CanDerive::Yes)
2263 } else {
2264 Some(CanDerive::No)
2265 }
2266 } else {
2267 self.options.last_callback(|cb| {
2268 cb.blocklisted_type_implements_trait(
2269 name,
2270 derive_trait,
2271 )
2272 })
2273 }
2274 })
2275 .unwrap_or(CanDerive::No)
2276 })
2277 }
2278
2279 /// Is the given type a type from <stdint.h> that corresponds to a Rust primitive type?
2280 pub fn is_stdint_type(&self, name: &str) -> bool {
2281 match name {
2282 "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" |
2283 "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" |
2284 "intptr_t" | "ptrdiff_t" => true,
2285 "size_t" | "ssize_t" => self.options.size_t_is_usize,
2286 _ => false,
2287 }
2288 }
2289
2290 /// Get a reference to the set of items we should generate.
2291 pub fn codegen_items(&self) -> &ItemSet {
2292 assert!(self.in_codegen_phase());
2293 assert!(self.current_module == self.root_module);
2294 self.codegen_items.as_ref().unwrap()
2295 }
2296
2297 /// Compute the allowlisted items set and populate `self.allowlisted`.
2298 fn compute_allowlisted_and_codegen_items(&mut self) {
2299 assert!(self.in_codegen_phase());
2300 assert!(self.current_module == self.root_module);
2301 assert!(self.allowlisted.is_none());
2302 let _t = self.timer("compute_allowlisted_and_codegen_items");
2303
2304 let roots = {
2305 let mut roots = self
2306 .items()
2307 // Only consider roots that are enabled for codegen.
2308 .filter(|&(_, item)| item.is_enabled_for_codegen(self))
2309 .filter(|&(_, item)| {
2310 // If nothing is explicitly allowlisted, then everything is fair
2311 // game.
2312 if self.options().allowlisted_types.is_empty() &&
2313 self.options().allowlisted_functions.is_empty() &&
2314 self.options().allowlisted_vars.is_empty() &&
2315 self.options().allowlisted_files.is_empty()
2316 {
2317 return true;
2318 }
2319
2320 // If this is a type that explicitly replaces another, we assume
2321 // you know what you're doing.
2322 if item.annotations().use_instead_of().is_some() {
2323 return true;
2324 }
2325
2326 // Items with a source location in an explicitly allowlisted file
2327 // are always included.
2328 if !self.options().allowlisted_files.is_empty() {
2329 if let Some(location) = item.location() {
2330 let (file, _, _, _) = location.location();
2331 if let Some(filename) = file.name() {
2332 if self
2333 .options()
2334 .allowlisted_files
2335 .matches(filename)
2336 {
2337 return true;
2338 }
2339 }
2340 }
2341 }
2342
2343 let name = item.path_for_allowlisting(self)[1..].join("::");
2344 debug!("allowlisted_items: testing {:?}", name);
2345 match *item.kind() {
2346 ItemKind::Module(..) => true,
2347 ItemKind::Function(_) => {
2348 self.options().allowlisted_functions.matches(&name)
2349 }
2350 ItemKind::Var(_) => {
2351 self.options().allowlisted_vars.matches(&name)
2352 }
2353 ItemKind::Type(ref ty) => {
2354 if self.options().allowlisted_types.matches(&name) {
2355 return true;
2356 }
2357
2358 // Auto-allowlist types that don't need code
2359 // generation if not allowlisting recursively, to
2360 // make the #[derive] analysis not be lame.
2361 if !self.options().allowlist_recursively {
2362 match *ty.kind() {
2363 TypeKind::Void |
2364 TypeKind::NullPtr |
2365 TypeKind::Int(..) |
2366 TypeKind::Float(..) |
2367 TypeKind::Complex(..) |
2368 TypeKind::Array(..) |
2369 TypeKind::Vector(..) |
2370 TypeKind::Pointer(..) |
2371 TypeKind::Reference(..) |
2372 TypeKind::Function(..) |
2373 TypeKind::ResolvedTypeRef(..) |
2374 TypeKind::Opaque |
2375 TypeKind::TypeParam => return true,
2376 _ => {}
2377 }
2378 if self.is_stdint_type(&name) {
2379 return true;
2380 }
2381 }
2382
2383 // Unnamed top-level enums are special and we
2384 // allowlist them via the `allowlisted_vars` filter,
2385 // since they're effectively top-level constants,
2386 // and there's no way for them to be referenced
2387 // consistently.
2388 let parent = self.resolve_item(item.parent_id());
2389 if !parent.is_module() {
2390 return false;
2391 }
2392
2393 let enum_ = match *ty.kind() {
2394 TypeKind::Enum(ref e) => e,
2395 _ => return false,
2396 };
2397
2398 if ty.name().is_some() {
2399 return false;
2400 }
2401
2402 let mut prefix_path =
2403 parent.path_for_allowlisting(self).clone();
2404 enum_.variants().iter().any(|variant| {
2405 prefix_path.push(
2406 variant.name_for_allowlisting().into(),
2407 );
2408 let name = prefix_path[1..].join("::");
2409 prefix_path.pop().unwrap();
2410 self.options().allowlisted_vars.matches(name)
2411 })
2412 }
2413 }
2414 })
2415 .map(|(id, _)| id)
2416 .collect::<Vec<_>>();
2417
2418 // The reversal preserves the expected ordering of traversal,
2419 // resulting in more stable-ish bindgen-generated names for
2420 // anonymous types (like unions).
2421 roots.reverse();
2422 roots
2423 };
2424
2425 let allowlisted_items_predicate =
2426 if self.options().allowlist_recursively {
2427 traversal::all_edges
2428 } else {
2429 // Only follow InnerType edges from the allowlisted roots.
2430 // Such inner types (e.g. anonymous structs/unions) are
2431 // always emitted by codegen, and they need to be allowlisted
2432 // to make sure they are processed by e.g. the derive analysis.
2433 traversal::only_inner_type_edges
2434 };
2435
2436 let allowlisted = AllowlistedItemsTraversal::new(
2437 self,
2438 roots.clone(),
2439 allowlisted_items_predicate,
2440 )
2441 .collect::<ItemSet>();
2442
2443 let codegen_items = if self.options().allowlist_recursively {
2444 AllowlistedItemsTraversal::new(
2445 self,
2446 roots,
2447 traversal::codegen_edges,
2448 )
2449 .collect::<ItemSet>()
2450 } else {
2451 allowlisted.clone()
2452 };
2453
2454 self.allowlisted = Some(allowlisted);
2455 self.codegen_items = Some(codegen_items);
2456
2457 let mut warnings = Vec::new();
2458
2459 for item in self.options().allowlisted_functions.unmatched_items() {
2460 warnings
2461 .push(format!("unused option: --allowlist-function {}", item));
2462 }
2463
2464 for item in self.options().allowlisted_vars.unmatched_items() {
2465 warnings.push(format!("unused option: --allowlist-var {}", item));
2466 }
2467
2468 for item in self.options().allowlisted_types.unmatched_items() {
2469 warnings.push(format!("unused option: --allowlist-type {}", item));
2470 }
2471
2472 for msg in warnings {
2473 warn!("{}", msg);
2474 self.warnings.push(msg);
2475 }
2476 }
2477
2478 /// Convenient method for getting the prefix to use for most traits in
2479 /// codegen depending on the `use_core` option.
2480 pub fn trait_prefix(&self) -> Ident {
2481 if self.options().use_core {
2482 self.rust_ident_raw("core")
2483 } else {
2484 self.rust_ident_raw("std")
2485 }
2486 }
2487
2488 /// Call if a bindgen complex is generated
2489 pub fn generated_bindgen_complex(&self) {
2490 self.generated_bindgen_complex.set(true)
2491 }
2492
2493 /// Whether we need to generate the bindgen complex type
2494 pub fn need_bindgen_complex_type(&self) -> bool {
2495 self.generated_bindgen_complex.get()
2496 }
2497
2498 /// Compute which `enum`s have an associated `typedef` definition.
2499 fn compute_enum_typedef_combos(&mut self) {
2500 let _t = self.timer("compute_enum_typedef_combos");
2501 assert!(self.enum_typedef_combos.is_none());
2502
2503 let mut enum_typedef_combos = HashSet::default();
2504 for item in &self.items {
2505 if let Some(ItemKind::Module(module)) =
2506 item.as_ref().map(Item::kind)
2507 {
2508 // Find typedefs in this module, and build set of their names.
2509 let mut names_of_typedefs = HashSet::default();
2510 for child_id in module.children() {
2511 if let Some(ItemKind::Type(ty)) =
2512 self.items[child_id.0].as_ref().map(Item::kind)
2513 {
2514 if let (Some(name), TypeKind::Alias(type_id)) =
2515 (ty.name(), ty.kind())
2516 {
2517 // We disregard aliases that refer to the enum
2518 // itself, such as in `typedef enum { ... } Enum;`.
2519 if type_id
2520 .into_resolver()
2521 .through_type_refs()
2522 .through_type_aliases()
2523 .resolve(self)
2524 .expect_type()
2525 .is_int()
2526 {
2527 names_of_typedefs.insert(name);
2528 }
2529 }
2530 }
2531 }
2532
2533 // Find enums in this module, and record the id of each one that
2534 // has a typedef.
2535 for child_id in module.children() {
2536 if let Some(ItemKind::Type(ty)) =
2537 self.items[child_id.0].as_ref().map(Item::kind)
2538 {
2539 if let (Some(name), true) = (ty.name(), ty.is_enum()) {
2540 if names_of_typedefs.contains(name) {
2541 enum_typedef_combos.insert(*child_id);
2542 }
2543 }
2544 }
2545 }
2546 }
2547 }
2548
2549 self.enum_typedef_combos = Some(enum_typedef_combos);
2550 }
2551
2552 /// Look up whether `id` refers to an `enum` whose underlying type is
2553 /// defined by a `typedef`.
2554 pub fn is_enum_typedef_combo(&self, id: ItemId) -> bool {
2555 assert!(
2556 self.in_codegen_phase(),
2557 "We only compute enum_typedef_combos when we enter codegen",
2558 );
2559 self.enum_typedef_combos.as_ref().unwrap().contains(&id)
2560 }
2561
2562 /// Compute whether we can derive debug.
2563 fn compute_cannot_derive_debug(&mut self) {
2564 let _t = self.timer("compute_cannot_derive_debug");
2565 assert!(self.cannot_derive_debug.is_none());
2566 if self.options.derive_debug {
2567 self.cannot_derive_debug =
2568 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2569 self,
2570 DeriveTrait::Debug,
2571 ))));
2572 }
2573 }
2574
2575 /// Look up whether the item with `id` can
2576 /// derive debug or not.
2577 pub fn lookup_can_derive_debug<Id: Into<ItemId>>(&self, id: Id) -> bool {
2578 let id = id.into();
2579 assert!(
2580 self.in_codegen_phase(),
2581 "We only compute can_derive_debug when we enter codegen"
2582 );
2583
2584 // Look up the computed value for whether the item with `id` can
2585 // derive debug or not.
2586 !self.cannot_derive_debug.as_ref().unwrap().contains(&id)
2587 }
2588
2589 /// Compute whether we can derive default.
2590 fn compute_cannot_derive_default(&mut self) {
2591 let _t = self.timer("compute_cannot_derive_default");
2592 assert!(self.cannot_derive_default.is_none());
2593 if self.options.derive_default {
2594 self.cannot_derive_default =
2595 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2596 self,
2597 DeriveTrait::Default,
2598 ))));
2599 }
2600 }
2601
2602 /// Look up whether the item with `id` can
2603 /// derive default or not.
2604 pub fn lookup_can_derive_default<Id: Into<ItemId>>(&self, id: Id) -> bool {
2605 let id = id.into();
2606 assert!(
2607 self.in_codegen_phase(),
2608 "We only compute can_derive_default when we enter codegen"
2609 );
2610
2611 // Look up the computed value for whether the item with `id` can
2612 // derive default or not.
2613 !self.cannot_derive_default.as_ref().unwrap().contains(&id)
2614 }
2615
2616 /// Compute whether we can derive copy.
2617 fn compute_cannot_derive_copy(&mut self) {
2618 let _t = self.timer("compute_cannot_derive_copy");
2619 assert!(self.cannot_derive_copy.is_none());
2620 self.cannot_derive_copy =
2621 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2622 self,
2623 DeriveTrait::Copy,
2624 ))));
2625 }
2626
2627 /// Compute whether we can derive hash.
2628 fn compute_cannot_derive_hash(&mut self) {
2629 let _t = self.timer("compute_cannot_derive_hash");
2630 assert!(self.cannot_derive_hash.is_none());
2631 if self.options.derive_hash {
2632 self.cannot_derive_hash =
2633 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2634 self,
2635 DeriveTrait::Hash,
2636 ))));
2637 }
2638 }
2639
2640 /// Look up whether the item with `id` can
2641 /// derive hash or not.
2642 pub fn lookup_can_derive_hash<Id: Into<ItemId>>(&self, id: Id) -> bool {
2643 let id = id.into();
2644 assert!(
2645 self.in_codegen_phase(),
2646 "We only compute can_derive_debug when we enter codegen"
2647 );
2648
2649 // Look up the computed value for whether the item with `id` can
2650 // derive hash or not.
2651 !self.cannot_derive_hash.as_ref().unwrap().contains(&id)
2652 }
2653
2654 /// Compute whether we can derive PartialOrd, PartialEq or Eq.
2655 fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) {
2656 let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq");
2657 assert!(self.cannot_derive_partialeq_or_partialord.is_none());
2658 if self.options.derive_partialord ||
2659 self.options.derive_partialeq ||
2660 self.options.derive_eq
2661 {
2662 self.cannot_derive_partialeq_or_partialord =
2663 Some(analyze::<CannotDerive>((
2664 self,
2665 DeriveTrait::PartialEqOrPartialOrd,
2666 )));
2667 }
2668 }
2669
2670 /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`.
2671 pub fn lookup_can_derive_partialeq_or_partialord<Id: Into<ItemId>>(
2672 &self,
2673 id: Id,
2674 ) -> CanDerive {
2675 let id = id.into();
2676 assert!(
2677 self.in_codegen_phase(),
2678 "We only compute can_derive_partialeq_or_partialord when we enter codegen"
2679 );
2680
2681 // Look up the computed value for whether the item with `id` can
2682 // derive partialeq or not.
2683 self.cannot_derive_partialeq_or_partialord
2684 .as_ref()
2685 .unwrap()
2686 .get(&id)
2687 .cloned()
2688 .unwrap_or(CanDerive::Yes)
2689 }
2690
2691 /// Look up whether the item with `id` can derive `Copy` or not.
2692 pub fn lookup_can_derive_copy<Id: Into<ItemId>>(&self, id: Id) -> bool {
2693 assert!(
2694 self.in_codegen_phase(),
2695 "We only compute can_derive_debug when we enter codegen"
2696 );
2697
2698 // Look up the computed value for whether the item with `id` can
2699 // derive `Copy` or not.
2700 let id = id.into();
2701
2702 !self.lookup_has_type_param_in_array(id) &&
2703 !self.cannot_derive_copy.as_ref().unwrap().contains(&id)
2704 }
2705
2706 /// Compute whether the type has type parameter in array.
2707 fn compute_has_type_param_in_array(&mut self) {
2708 let _t = self.timer("compute_has_type_param_in_array");
2709 assert!(self.has_type_param_in_array.is_none());
2710 self.has_type_param_in_array =
2711 Some(analyze::<HasTypeParameterInArray>(self));
2712 }
2713
2714 /// Look up whether the item with `id` has type parameter in array or not.
2715 pub fn lookup_has_type_param_in_array<Id: Into<ItemId>>(
2716 &self,
2717 id: Id,
2718 ) -> bool {
2719 assert!(
2720 self.in_codegen_phase(),
2721 "We only compute has array when we enter codegen"
2722 );
2723
2724 // Look up the computed value for whether the item with `id` has
2725 // type parameter in array or not.
2726 self.has_type_param_in_array
2727 .as_ref()
2728 .unwrap()
2729 .contains(&id.into())
2730 }
2731
2732 /// Compute whether the type has float.
2733 fn compute_has_float(&mut self) {
2734 let _t = self.timer("compute_has_float");
2735 assert!(self.has_float.is_none());
2736 if self.options.derive_eq || self.options.derive_ord {
2737 self.has_float = Some(analyze::<HasFloat>(self));
2738 }
2739 }
2740
2741 /// Look up whether the item with `id` has array or not.
2742 pub fn lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool {
2743 assert!(
2744 self.in_codegen_phase(),
2745 "We only compute has float when we enter codegen"
2746 );
2747
2748 // Look up the computed value for whether the item with `id` has
2749 // float or not.
2750 self.has_float.as_ref().unwrap().contains(&id.into())
2751 }
2752
2753 /// Check if `--no-partialeq` flag is enabled for this item.
2754 pub fn no_partialeq_by_name(&self, item: &Item) -> bool {
2755 let name = item.path_for_allowlisting(self)[1..].join("::");
2756 self.options().no_partialeq_types.matches(name)
2757 }
2758
2759 /// Check if `--no-copy` flag is enabled for this item.
2760 pub fn no_copy_by_name(&self, item: &Item) -> bool {
2761 let name = item.path_for_allowlisting(self)[1..].join("::");
2762 self.options().no_copy_types.matches(name)
2763 }
2764
2765 /// Check if `--no-debug` flag is enabled for this item.
2766 pub fn no_debug_by_name(&self, item: &Item) -> bool {
2767 let name = item.path_for_allowlisting(self)[1..].join("::");
2768 self.options().no_debug_types.matches(name)
2769 }
2770
2771 /// Check if `--no-default` flag is enabled for this item.
2772 pub fn no_default_by_name(&self, item: &Item) -> bool {
2773 let name = item.path_for_allowlisting(self)[1..].join("::");
2774 self.options().no_default_types.matches(name)
2775 }
2776
2777 /// Check if `--no-hash` flag is enabled for this item.
2778 pub fn no_hash_by_name(&self, item: &Item) -> bool {
2779 let name = item.path_for_allowlisting(self)[1..].join("::");
2780 self.options().no_hash_types.matches(name)
2781 }
2782
2783 /// Check if `--must-use-type` flag is enabled for this item.
2784 pub fn must_use_type_by_name(&self, item: &Item) -> bool {
2785 let name = item.path_for_allowlisting(self)[1..].join("::");
2786 self.options().must_use_types.matches(name)
2787 }
2788
2789 pub(crate) fn wrap_unsafe_ops(&self, tokens: impl ToTokens) -> TokenStream {
2790 if self.options.wrap_unsafe_ops {
2791 quote!(unsafe { #tokens })
2792 } else {
2793 tokens.into_token_stream()
2794 }
2795 }
2796
2797 pub(crate) fn wrap_static_fns_suffix(&self) -> &str {
2798 self.options()
2799 .wrap_static_fns_suffix
2800 .as_deref()
2801 .unwrap_or(crate::DEFAULT_NON_EXTERN_FNS_SUFFIX)
2802 }
2803}
2804
2805/// A builder struct for configuring item resolution options.
2806#[derive(Debug, Copy, Clone)]
2807pub struct ItemResolver {
2808 id: ItemId,
2809 through_type_refs: bool,
2810 through_type_aliases: bool,
2811}
2812
2813impl ItemId {
2814 /// Create an `ItemResolver` from this item id.
2815 pub fn into_resolver(self) -> ItemResolver {
2816 self.into()
2817 }
2818}
2819
2820impl<T> From<T> for ItemResolver
2821where
2822 T: Into<ItemId>,
2823{
2824 fn from(id: T) -> ItemResolver {
2825 ItemResolver::new(id)
2826 }
2827}
2828
2829impl ItemResolver {
2830 /// Construct a new `ItemResolver` from the given id.
2831 pub fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
2832 let id = id.into();
2833 ItemResolver {
2834 id,
2835 through_type_refs: false,
2836 through_type_aliases: false,
2837 }
2838 }
2839
2840 /// Keep resolving through `Type::TypeRef` items.
2841 pub fn through_type_refs(mut self) -> ItemResolver {
2842 self.through_type_refs = true;
2843 self
2844 }
2845
2846 /// Keep resolving through `Type::Alias` items.
2847 pub fn through_type_aliases(mut self) -> ItemResolver {
2848 self.through_type_aliases = true;
2849 self
2850 }
2851
2852 /// Finish configuring and perform the actual item resolution.
2853 pub fn resolve(self, ctx: &BindgenContext) -> &Item {
2854 assert!(ctx.collected_typerefs());
2855
2856 let mut id = self.id;
2857 let mut seen_ids = HashSet::default();
2858 loop {
2859 let item = ctx.resolve_item(id);
2860
2861 // Detect cycles and bail out. These can happen in certain cases
2862 // involving incomplete qualified dependent types (#2085).
2863 if !seen_ids.insert(id) {
2864 return item;
2865 }
2866
2867 let ty_kind = item.as_type().map(|t| t.kind());
2868 match ty_kind {
2869 Some(&TypeKind::ResolvedTypeRef(next_id))
2870 if self.through_type_refs =>
2871 {
2872 id = next_id.into();
2873 }
2874 // We intentionally ignore template aliases here, as they are
2875 // more complicated, and don't represent a simple renaming of
2876 // some type.
2877 Some(&TypeKind::Alias(next_id))
2878 if self.through_type_aliases =>
2879 {
2880 id = next_id.into();
2881 }
2882 _ => return item,
2883 }
2884 }
2885 }
2886}
2887
2888/// A type that we are in the middle of parsing.
2889#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2890pub struct PartialType {
2891 decl: Cursor,
2892 // Just an ItemId, and not a TypeId, because we haven't finished this type
2893 // yet, so there's still time for things to go wrong.
2894 id: ItemId,
2895}
2896
2897impl PartialType {
2898 /// Construct a new `PartialType`.
2899 pub fn new(decl: Cursor, id: ItemId) -> PartialType {
2900 // assert!(decl == decl.canonical());
2901 PartialType { decl, id }
2902 }
2903
2904 /// The cursor pointing to this partial type's declaration location.
2905 pub fn decl(&self) -> &Cursor {
2906 &self.decl
2907 }
2908
2909 /// The item ID allocated for this type. This is *NOT* a key for an entry in
2910 /// the context's item set yet!
2911 pub fn id(&self) -> ItemId {
2912 self.id
2913 }
2914}
2915
2916impl TemplateParameters for PartialType {
2917 fn self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId> {
2918 // Maybe at some point we will eagerly parse named types, but for now we
2919 // don't and this information is unavailable.
2920 vec![]
2921 }
2922
2923 fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize {
2924 // Wouldn't it be nice if libclang would reliably give us this
2925 // information‽
2926 match self.decl().kind() {
2927 clang_sys::CXCursor_ClassTemplate |
2928 clang_sys::CXCursor_FunctionTemplate |
2929 clang_sys::CXCursor_TypeAliasTemplateDecl => {
2930 let mut num_params = 0;
2931 self.decl().visit(|c| {
2932 match c.kind() {
2933 clang_sys::CXCursor_TemplateTypeParameter |
2934 clang_sys::CXCursor_TemplateTemplateParameter |
2935 clang_sys::CXCursor_NonTypeTemplateParameter => {
2936 num_params += 1;
2937 }
2938 _ => {}
2939 };
2940 clang_sys::CXChildVisit_Continue
2941 });
2942 num_params
2943 }
2944 _ => 0,
2945 }
2946 }
2947}
2948