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