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