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