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