1//! Common context that is passed around during parsing and codegen.
2
3use super::super::time::Timer;
4use super::analysis::{
5 analyze, as_cannot_derive_set, CannotDerive, DeriveTrait,
6 HasDestructorAnalysis, HasFloat, HasTypeParameterInArray,
7 HasVtableAnalysis, HasVtableResult, SizednessAnalysis, SizednessResult,
8 UsedTemplateParameters,
9};
10use super::derive::{
11 CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
12 CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
13};
14use super::function::Function;
15use super::int::IntKind;
16use super::item::{IsOpaque, Item, ItemAncestors, ItemSet};
17use super::item_kind::ItemKind;
18use super::module::{Module, ModuleKind};
19use super::template::{TemplateInstantiation, TemplateParameters};
20use super::traversal::{self, Edge, ItemTraversal};
21use super::ty::{FloatKind, Type, TypeKind};
22use crate::clang::{self, ABIKind, Cursor};
23use crate::codegen::CodegenError;
24use crate::BindgenOptions;
25use crate::{Entry, HashMap, HashSet};
26
27use proc_macro2::{Ident, Span, TokenStream};
28use quote::ToTokens;
29use std::borrow::Cow;
30use std::cell::{Cell, RefCell};
31use std::collections::{BTreeSet, HashMap as StdHashMap};
32use std::fs::OpenOptions;
33use std::io::Write;
34use std::mem;
35use std::path::Path;
36
37/// An identifier for some kind of IR item.
38#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
39pub(crate) struct ItemId(usize);
40
41/// Declare a newtype around `ItemId` with conversion methods.
42macro_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
117item_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
136item_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
155item_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
174item_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
193impl From<ItemId> for usize {
194 fn from(id: ItemId) -> usize {
195 id.0
196 }
197}
198
199impl ItemId {
200 /// Get a numeric representation of this ID.
201 pub(crate) fn as_usize(&self) -> usize {
202 (*self).into()
203 }
204}
205
206impl<T> ::std::cmp::PartialEq<T> for ItemId
207where
208 T: Copy + Into<ItemId>,
209{
210 fn eq(&self, rhs: &T) -> bool {
211 let rhs: ItemId = (*rhs).into();
212 self.0 == rhs.0
213 }
214}
215
216impl<T> CanDeriveDebug for T
217where
218 T: Copy + Into<ItemId>,
219{
220 fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
221 ctx.options().derive_debug && ctx.lookup_can_derive_debug(*self)
222 }
223}
224
225impl<T> CanDeriveDefault for T
226where
227 T: Copy + Into<ItemId>,
228{
229 fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
230 ctx.options().derive_default && ctx.lookup_can_derive_default(*self)
231 }
232}
233
234impl<T> CanDeriveCopy for T
235where
236 T: Copy + Into<ItemId>,
237{
238 fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
239 ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self)
240 }
241}
242
243impl<T> CanDeriveHash for T
244where
245 T: Copy + Into<ItemId>,
246{
247 fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
248 ctx.options().derive_hash && ctx.lookup_can_derive_hash(*self)
249 }
250}
251
252impl<T> CanDerivePartialOrd for T
253where
254 T: Copy + Into<ItemId>,
255{
256 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
263impl<T> CanDerivePartialEq for T
264where
265 T: Copy + Into<ItemId>,
266{
267 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
274impl<T> CanDeriveEq for T
275where
276 T: Copy + Into<ItemId>,
277{
278 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
286impl<T> CanDeriveOrd for T
287where
288 T: Copy + Into<ItemId>,
289{
290 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)]
305enum TypeKey {
306 Usr(String),
307 Declaration(Cursor),
308}
309
310/// A context used during parsing and generation of structs.
311#[derive(Debug)]
312pub(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.
499struct AllowlistedItemsTraversal<'ctx> {
500 ctx: &'ctx BindgenContext,
501 traversal: ItemTraversal<'ctx, ItemSet, Vec<ItemId>>,
502}
503
504impl<'ctx> Iterator for AllowlistedItemsTraversal<'ctx> {
505 type Item = ItemId;
506
507 fn next(&mut self) -> Option<ItemId> {
508 loop {
509 let id: ItemId = 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
520impl<'ctx> AllowlistedItemsTraversal<'ctx> {
521 /// Construct a new allowlisted items traversal.
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
537impl BindgenContext {
538 /// Construct the context for the given `options`.
539 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
567If 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
618 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.
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.
631 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.
636 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.
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.
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.
655 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`.
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`.
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.
682 pub(crate) fn add_dep(&mut self, dep: Box<str>) {
683 self.deps.insert(dep);
684 }
685
686 /// Get any included files.
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.
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.
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.
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.
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]
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.
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.
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.
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?
929 pub(crate) fn collected_typerefs(&self) -> bool {
930 self.collected_typerefs
931 }
932
933 /// Gather all the unresolved type references.
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.
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.
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.
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.
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.
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.
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.
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
1248 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.
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.
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.
1313 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.
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.
1335 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.
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.
1359 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
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.
1403 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.
1435 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.
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
1467 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.
1473 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`.
1481 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`.
1489 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.
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.
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.
1514 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.
1523 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.
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.
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.
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.
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`.
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.
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.
1943 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 .
1956 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
1968 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.
1994 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
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.
2066 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.
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?
2178 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.
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.
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?
2200 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.
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?
2232 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?
2242 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.
2251 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.
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.
2336 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.
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.
2385 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.
2394 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?
2435 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.
2446 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`.
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.
2641 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
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
2655 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
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
2665 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.
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`.
2725 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.
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.
2748 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.
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.
2778 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.
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.
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.
2819 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.
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}`.
2851 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.
2874 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.
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.
2900 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.
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.
2927 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.
2939 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.
2945 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.
2951 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.
2957 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.
2963 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.
2969 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.
2975 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.
2985 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)]
2995pub(crate) struct ItemResolver {
2996 id: ItemId,
2997 through_type_refs: bool,
2998 through_type_aliases: bool,
2999}
3000
3001impl ItemId {
3002 /// Create an `ItemResolver` from this item ID.
3003 pub(crate) fn into_resolver(self) -> ItemResolver {
3004 self.into()
3005 }
3006}
3007
3008impl<T> From<T> for ItemResolver
3009where
3010 T: Into<ItemId>,
3011{
3012 fn from(id: T) -> ItemResolver {
3013 ItemResolver::new(id)
3014 }
3015}
3016
3017impl ItemResolver {
3018 /// Construct a new `ItemResolver` from the given ID.
3019 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.
3029 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.
3035 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.
3041 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)]
3078pub(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
3085impl PartialType {
3086 /// Construct a new `PartialType`.
3087 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.
3093 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!
3099 pub(crate) fn id(&self) -> ItemId {
3100 self.id
3101 }
3102}
3103
3104impl TemplateParameters for PartialType {
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
3111 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
3137fn unused_regex_diagnostic(item: &str, name: &str, _ctx: &BindgenContext) {
3138 warn!("unused option: {} {}", name, item);
3139
3140 #[cfg(feature = "experimental")]
3141 if _ctx.options().emit_diagnostics {
3142 use crate::diagnostics::{Diagnostic, Level};
3143
3144 Diagnostic::default()
3145 .with_title(
3146 format!("Unused regular expression: `{}`.", item),
3147 Level::Warn,
3148 )
3149 .add_annotation(
3150 format!("This regular expression was passed to `{}`.", name),
3151 Level::Note,
3152 )
3153 .display();
3154 }
3155}
3156