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