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