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