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 callbacks::ParseCallbacks;
23 use cexpr;
24 use clang::{self, Cursor};
25 use clang_sys;
26 use parse::ClangItemParser;
27 use proc_macro2::{Ident, Span};
28 use std::borrow::Cow;
29 use std::cell::Cell;
30 use std::collections::HashMap as StdHashMap;
31 use std::iter::IntoIterator;
32 use std::mem;
33 use BindgenOptions;
34 use {Entry, HashMap, HashSet};
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 clang_args = if explicit_target {
557 Cow::Borrowed(&options.clang_args)
558 } else {
559 let mut args = Vec::with_capacity(options.clang_args.len() + 1);
560 args.push(format!("--target={}", effective_target));
561 args.extend_from_slice(&options.clang_args);
562 Cow::Owned(args)
563 };
564
565 clang::TranslationUnit::parse(
566 &index,
567 "",
568 &clang_args,
569 &options.input_unsaved_files,
570 parse_options,
571 ).expect("libclang error; possible causes include:
572 - Invalid flag syntax
573 - Unrecognized flags
574 - Invalid flag arguments
575 - File I/O errors
576 If you encounter an error missing from this list, please file an issue or a PR!")
577 };
578
579 let target_info = clang::TargetInfo::new(&translation_unit);
580
581 #[cfg(debug_assertions)]
582 {
583 if let Some(ref ti) = target_info {
584 if effective_target == HOST_TARGET {
585 assert_eq!(
586 ti.pointer_width / 8,
587 mem::size_of::<*mut ()>(),
588 "{:?} {:?}",
589 effective_target,
590 HOST_TARGET
591 );
592 }
593 }
594 }
595
596 let root_module = Self::build_root_module(ItemId(0));
597 let root_module_id = root_module.id().as_module_id_unchecked();
598
599 BindgenContext {
600 items: vec![Some(root_module)],
601 types: Default::default(),
602 type_params: Default::default(),
603 modules: Default::default(),
604 root_module: root_module_id,
605 current_module: root_module_id,
606 semantic_parents: Default::default(),
607 currently_parsed_types: vec![],
608 parsed_macros: Default::default(),
609 replacements: Default::default(),
610 collected_typerefs: false,
611 in_codegen: false,
612 index,
613 translation_unit,
614 target_info,
615 options,
616 generated_bindgen_complex: Cell::new(false),
617 whitelisted: None,
618 codegen_items: None,
619 used_template_parameters: None,
620 need_bitfield_allocation: Default::default(),
621 cannot_derive_debug: None,
622 cannot_derive_default: None,
623 cannot_derive_copy: None,
624 cannot_derive_copy_in_array: None,
625 cannot_derive_hash: None,
626 cannot_derive_partialeq_or_partialord: None,
627 sizedness: None,
628 have_vtable: None,
629 have_destructor: None,
630 has_type_param_in_array: None,
631 has_float: None,
632 }
633 }
634
635 /// Creates a timer for the current bindgen phase. If time_phases is `true`,
636 /// the timer will print to stderr when it is dropped, otherwise it will do
637 /// nothing.
timer<'a>(&self, name: &'a str) -> Timer<'a>638 pub fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
639 Timer::new(name).with_output(self.options.time_phases)
640 }
641
642 /// Returns the pointer width to use for the target for the current
643 /// translation.
target_pointer_size(&self) -> usize644 pub fn target_pointer_size(&self) -> usize {
645 if let Some(ref ti) = self.target_info {
646 return ti.pointer_width / 8;
647 }
648 mem::size_of::<*mut ()>()
649 }
650
651 /// Get the stack of partially parsed types that we are in the middle of
652 /// parsing.
currently_parsed_types(&self) -> &[PartialType]653 pub fn currently_parsed_types(&self) -> &[PartialType] {
654 &self.currently_parsed_types[..]
655 }
656
657 /// Begin parsing the given partial type, and push it onto the
658 /// `currently_parsed_types` stack so that we won't infinite recurse if we
659 /// run into a reference to it while parsing it.
begin_parsing(&mut self, partial_ty: PartialType)660 pub fn begin_parsing(&mut self, partial_ty: PartialType) {
661 self.currently_parsed_types.push(partial_ty);
662 }
663
664 /// Finish parsing the current partial type, pop it off the
665 /// `currently_parsed_types` stack, and return it.
finish_parsing(&mut self) -> PartialType666 pub fn finish_parsing(&mut self) -> PartialType {
667 self.currently_parsed_types.pop().expect(
668 "should have been parsing a type, if we finished parsing a type",
669 )
670 }
671
672 /// Get the user-provided callbacks by reference, if any.
parse_callbacks(&self) -> Option<&dyn ParseCallbacks>673 pub fn parse_callbacks(&self) -> Option<&dyn ParseCallbacks> {
674 self.options().parse_callbacks.as_ref().map(|t| &**t)
675 }
676
677 /// Define a new item.
678 ///
679 /// This inserts it into the internal items set, and its type into the
680 /// internal types set.
add_item( &mut self, item: Item, declaration: Option<Cursor>, location: Option<Cursor>, )681 pub fn add_item(
682 &mut self,
683 item: Item,
684 declaration: Option<Cursor>,
685 location: Option<Cursor>,
686 ) {
687 debug!(
688 "BindgenContext::add_item({:?}, declaration: {:?}, loc: {:?}",
689 item, declaration, location
690 );
691 debug_assert!(
692 declaration.is_some() ||
693 !item.kind().is_type() ||
694 item.kind().expect_type().is_builtin_or_type_param() ||
695 item.kind().expect_type().is_opaque(self, &item) ||
696 item.kind().expect_type().is_unresolved_ref(),
697 "Adding a type without declaration?"
698 );
699
700 let id = item.id();
701 let is_type = item.kind().is_type();
702 let is_unnamed = is_type && item.expect_type().name().is_none();
703 let is_template_instantiation =
704 is_type && item.expect_type().is_template_instantiation();
705
706 if item.id() != self.root_module {
707 self.add_item_to_module(&item);
708 }
709
710 if is_type && item.expect_type().is_comp() {
711 self.need_bitfield_allocation.push(id);
712 }
713
714 let old_item = mem::replace(&mut self.items[id.0], Some(item));
715 assert!(
716 old_item.is_none(),
717 "should not have already associated an item with the given id"
718 );
719
720 // Unnamed items can have an USR, but they can't be referenced from
721 // other sites explicitly and the USR can match if the unnamed items are
722 // nested, so don't bother tracking them.
723 if is_type && !is_template_instantiation && declaration.is_some() {
724 let mut declaration = declaration.unwrap();
725 if !declaration.is_valid() {
726 if let Some(location) = location {
727 if location.is_template_like() {
728 declaration = location;
729 }
730 }
731 }
732 declaration = declaration.canonical();
733 if !declaration.is_valid() {
734 // This could happen, for example, with types like `int*` or
735 // similar.
736 //
737 // Fortunately, we don't care about those types being
738 // duplicated, so we can just ignore them.
739 debug!(
740 "Invalid declaration {:?} found for type {:?}",
741 declaration,
742 self.resolve_item_fallible(id)
743 .unwrap()
744 .kind()
745 .expect_type()
746 );
747 return;
748 }
749
750 let key = if is_unnamed {
751 TypeKey::Declaration(declaration)
752 } else if let Some(usr) = declaration.usr() {
753 TypeKey::USR(usr)
754 } else {
755 warn!(
756 "Valid declaration with no USR: {:?}, {:?}",
757 declaration, location
758 );
759 TypeKey::Declaration(declaration)
760 };
761
762 let old = self.types.insert(key, id.as_type_id_unchecked());
763 debug_assert_eq!(old, None);
764 }
765 }
766
767 /// Ensure that every item (other than the root module) is in a module's
768 /// children list. This is to make sure that every whitelisted item get's
769 /// codegen'd, even if its parent is not whitelisted. See issue #769 for
770 /// details.
add_item_to_module(&mut self, item: &Item)771 fn add_item_to_module(&mut self, item: &Item) {
772 assert!(item.id() != self.root_module);
773 assert!(self.resolve_item_fallible(item.id()).is_none());
774
775 if let Some(ref mut parent) = self.items[item.parent_id().0] {
776 if let Some(module) = parent.as_module_mut() {
777 debug!(
778 "add_item_to_module: adding {:?} as child of parent module {:?}",
779 item.id(),
780 item.parent_id()
781 );
782
783 module.children_mut().insert(item.id());
784 return;
785 }
786 }
787
788 debug!(
789 "add_item_to_module: adding {:?} as child of current module {:?}",
790 item.id(),
791 self.current_module
792 );
793
794 self.items[(self.current_module.0).0]
795 .as_mut()
796 .expect("Should always have an item for self.current_module")
797 .as_module_mut()
798 .expect("self.current_module should always be a module")
799 .children_mut()
800 .insert(item.id());
801 }
802
803 /// Add a new named template type parameter to this context's item set.
add_type_param(&mut self, item: Item, definition: clang::Cursor)804 pub fn add_type_param(&mut self, item: Item, definition: clang::Cursor) {
805 debug!(
806 "BindgenContext::add_type_param: item = {:?}; definition = {:?}",
807 item, definition
808 );
809
810 assert!(
811 item.expect_type().is_type_param(),
812 "Should directly be a named type, not a resolved reference or anything"
813 );
814 assert_eq!(
815 definition.kind(),
816 clang_sys::CXCursor_TemplateTypeParameter
817 );
818
819 self.add_item_to_module(&item);
820
821 let id = item.id();
822 let old_item = mem::replace(&mut self.items[id.0], Some(item));
823 assert!(
824 old_item.is_none(),
825 "should not have already associated an item with the given id"
826 );
827
828 let old_named_ty = self
829 .type_params
830 .insert(definition, id.as_type_id_unchecked());
831 assert!(
832 old_named_ty.is_none(),
833 "should not have already associated a named type with this id"
834 );
835 }
836
837 /// Get the named type defined at the given cursor location, if we've
838 /// already added one.
get_type_param(&self, definition: &clang::Cursor) -> Option<TypeId>839 pub fn get_type_param(&self, definition: &clang::Cursor) -> Option<TypeId> {
840 assert_eq!(
841 definition.kind(),
842 clang_sys::CXCursor_TemplateTypeParameter
843 );
844 self.type_params.get(definition).cloned()
845 }
846
847 // TODO: Move all this syntax crap to other part of the code.
848
849 /// Mangles a name so it doesn't conflict with any keyword.
rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str>850 pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
851 if name.contains("@") ||
852 name.contains("?") ||
853 name.contains("$") ||
854 match name {
855 "abstract" | "alignof" | "as" | "async" | "become" |
856 "box" | "break" | "const" | "continue" | "crate" | "do" |
857 "else" | "enum" | "extern" | "false" | "final" | "fn" |
858 "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" |
859 "match" | "mod" | "move" | "mut" | "offsetof" |
860 "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
861 "return" | "Self" | "self" | "sizeof" | "static" |
862 "struct" | "super" | "trait" | "true" | "type" | "typeof" |
863 "unsafe" | "unsized" | "use" | "virtual" | "where" |
864 "while" | "yield" | "bool" | "_" => true,
865 _ => false,
866 }
867 {
868 let mut s = name.to_owned();
869 s = s.replace("@", "_");
870 s = s.replace("?", "_");
871 s = s.replace("$", "_");
872 s.push_str("_");
873 return Cow::Owned(s);
874 }
875 Cow::Borrowed(name)
876 }
877
878 /// Returns a mangled name as a rust identifier.
rust_ident<S>(&self, name: S) -> Ident where S: AsRef<str>,879 pub fn rust_ident<S>(&self, name: S) -> Ident
880 where
881 S: AsRef<str>,
882 {
883 self.rust_ident_raw(self.rust_mangle(name.as_ref()))
884 }
885
886 /// Returns a mangled name as a rust identifier.
rust_ident_raw<T>(&self, name: T) -> Ident where T: AsRef<str>,887 pub fn rust_ident_raw<T>(&self, name: T) -> Ident
888 where
889 T: AsRef<str>,
890 {
891 Ident::new(name.as_ref(), Span::call_site())
892 }
893
894 /// Iterate over all items that have been defined.
items(&self) -> impl Iterator<Item = (ItemId, &Item)>895 pub fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
896 self.items.iter().enumerate().filter_map(|(index, item)| {
897 let item = item.as_ref()?;
898 Some((ItemId(index), item))
899 })
900 }
901
902 /// Have we collected all unresolved type references yet?
collected_typerefs(&self) -> bool903 pub fn collected_typerefs(&self) -> bool {
904 self.collected_typerefs
905 }
906
907 /// Gather all the unresolved type references.
collect_typerefs( &mut self, ) -> Vec<(ItemId, clang::Type, clang::Cursor, Option<ItemId>)>908 fn collect_typerefs(
909 &mut self,
910 ) -> Vec<(ItemId, clang::Type, clang::Cursor, Option<ItemId>)> {
911 debug_assert!(!self.collected_typerefs);
912 self.collected_typerefs = true;
913 let mut typerefs = vec![];
914
915 for (id, item) in self.items() {
916 let kind = item.kind();
917 let ty = match kind.as_type() {
918 Some(ty) => ty,
919 None => continue,
920 };
921
922 match *ty.kind() {
923 TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) => {
924 typerefs.push((id, ty.clone(), loc, parent_id));
925 }
926 _ => {}
927 };
928 }
929 typerefs
930 }
931
932 /// Collect all of our unresolved type references and resolve them.
resolve_typerefs(&mut self)933 fn resolve_typerefs(&mut self) {
934 let typerefs = self.collect_typerefs();
935
936 for (id, ty, loc, parent_id) in typerefs {
937 let _resolved =
938 {
939 let resolved = Item::from_ty(&ty, loc, parent_id, self)
940 .unwrap_or_else(|_| {
941 warn!("Could not resolve type reference, falling back \
942 to opaque blob");
943 Item::new_opaque_type(self.next_item_id(), &ty, self)
944 });
945
946 let item = self.items[id.0].as_mut().unwrap();
947 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
948 TypeKind::ResolvedTypeRef(resolved);
949 resolved
950 };
951
952 // Something in the STL is trolling me. I don't need this assertion
953 // right now, but worth investigating properly once this lands.
954 //
955 // debug_assert!(self.items.get(&resolved).is_some(), "How?");
956 //
957 // if let Some(parent_id) = parent_id {
958 // assert_eq!(self.items[&resolved].parent_id(), parent_id);
959 // }
960 }
961 }
962
963 /// Temporarily loan `Item` with the given `ItemId`. This provides means to
964 /// mutably borrow `Item` while having a reference to `BindgenContext`.
965 ///
966 /// `Item` with the given `ItemId` is removed from the context, given
967 /// closure is executed and then `Item` is placed back.
968 ///
969 /// # Panics
970 ///
971 /// Panics if attempt to resolve given `ItemId` inside the given
972 /// closure is made.
with_loaned_item<F, T>(&mut self, id: ItemId, f: F) -> T where F: (FnOnce(&BindgenContext, &mut Item) -> T),973 fn with_loaned_item<F, T>(&mut self, id: ItemId, f: F) -> T
974 where
975 F: (FnOnce(&BindgenContext, &mut Item) -> T),
976 {
977 let mut item = self.items[id.0].take().unwrap();
978
979 let result = f(self, &mut item);
980
981 let existing = mem::replace(&mut self.items[id.0], Some(item));
982 assert!(existing.is_none());
983
984 result
985 }
986
987 /// Compute the bitfield allocation units for all `TypeKind::Comp` items we
988 /// parsed.
compute_bitfield_units(&mut self)989 fn compute_bitfield_units(&mut self) {
990 assert!(self.collected_typerefs());
991
992 let need_bitfield_allocation =
993 mem::replace(&mut self.need_bitfield_allocation, vec![]);
994 for id in need_bitfield_allocation {
995 self.with_loaned_item(id, |ctx, item| {
996 item.kind_mut()
997 .as_type_mut()
998 .unwrap()
999 .as_comp_mut()
1000 .unwrap()
1001 .compute_bitfield_units(ctx);
1002 });
1003 }
1004 }
1005
1006 /// Assign a new generated name for each anonymous field.
deanonymize_fields(&mut self)1007 fn deanonymize_fields(&mut self) {
1008 let _t = self.timer("deanonymize_fields");
1009
1010 let comp_item_ids: Vec<ItemId> = self
1011 .items()
1012 .filter_map(|(id, item)| {
1013 if item.kind().as_type()?.is_comp() {
1014 return Some(id);
1015 }
1016 None
1017 })
1018 .collect();
1019
1020 for id in comp_item_ids {
1021 self.with_loaned_item(id, |ctx, item| {
1022 item.kind_mut()
1023 .as_type_mut()
1024 .unwrap()
1025 .as_comp_mut()
1026 .unwrap()
1027 .deanonymize_fields(ctx);
1028 });
1029 }
1030 }
1031
1032 /// Iterate over all items and replace any item that has been named in a
1033 /// `replaces="SomeType"` annotation with the replacement type.
process_replacements(&mut self)1034 fn process_replacements(&mut self) {
1035 let _t = self.timer("process_replacements");
1036 if self.replacements.is_empty() {
1037 debug!("No replacements to process");
1038 return;
1039 }
1040
1041 // FIXME: This is linear, but the replaces="xxx" annotation was already
1042 // there, and for better or worse it's useful, sigh...
1043 //
1044 // We leverage the ResolvedTypeRef thing, though, which is cool :P.
1045
1046 let mut replacements = vec![];
1047
1048 for (id, item) in self.items() {
1049 if item.annotations().use_instead_of().is_some() {
1050 continue;
1051 }
1052
1053 // Calls to `canonical_name` are expensive, so eagerly filter out
1054 // items that cannot be replaced.
1055 let ty = match item.kind().as_type() {
1056 Some(ty) => ty,
1057 None => continue,
1058 };
1059
1060 match *ty.kind() {
1061 TypeKind::Comp(..) |
1062 TypeKind::TemplateAlias(..) |
1063 TypeKind::Enum(..) |
1064 TypeKind::Alias(..) => {}
1065 _ => continue,
1066 }
1067
1068 let path = item.path_for_whitelisting(self);
1069 let replacement = self.replacements.get(&path[1..]);
1070
1071 if let Some(replacement) = replacement {
1072 if *replacement != id {
1073 // We set this just after parsing the annotation. It's
1074 // very unlikely, but this can happen.
1075 if self.resolve_item_fallible(*replacement).is_some() {
1076 replacements.push((
1077 id.expect_type_id(self),
1078 replacement.expect_type_id(self),
1079 ));
1080 }
1081 }
1082 }
1083 }
1084
1085 for (id, replacement_id) in replacements {
1086 debug!("Replacing {:?} with {:?}", id, replacement_id);
1087 let new_parent = {
1088 let item_id: ItemId = id.into();
1089 let item = self.items[item_id.0].as_mut().unwrap();
1090 *item.kind_mut().as_type_mut().unwrap().kind_mut() =
1091 TypeKind::ResolvedTypeRef(replacement_id);
1092 item.parent_id()
1093 };
1094
1095 // Relocate the replacement item from where it was declared, to
1096 // where the thing it is replacing was declared.
1097 //
1098 // First, we'll make sure that its parent id is correct.
1099
1100 let old_parent = self.resolve_item(replacement_id).parent_id();
1101 if new_parent == old_parent {
1102 // Same parent and therefore also same containing
1103 // module. Nothing to do here.
1104 continue;
1105 }
1106
1107 let replacement_item_id: ItemId = replacement_id.into();
1108 self.items[replacement_item_id.0]
1109 .as_mut()
1110 .unwrap()
1111 .set_parent_for_replacement(new_parent);
1112
1113 // Second, make sure that it is in the correct module's children
1114 // set.
1115
1116 let old_module = {
1117 let immut_self = &*self;
1118 old_parent
1119 .ancestors(immut_self)
1120 .chain(Some(immut_self.root_module.into()))
1121 .find(|id| {
1122 let item = immut_self.resolve_item(*id);
1123 item.as_module().map_or(false, |m| {
1124 m.children().contains(&replacement_id.into())
1125 })
1126 })
1127 };
1128 let old_module = old_module
1129 .expect("Every replacement item should be in a module");
1130
1131 let new_module = {
1132 let immut_self = &*self;
1133 new_parent
1134 .ancestors(immut_self)
1135 .find(|id| immut_self.resolve_item(*id).is_module())
1136 };
1137 let new_module = new_module.unwrap_or(self.root_module.into());
1138
1139 if new_module == old_module {
1140 // Already in the correct module.
1141 continue;
1142 }
1143
1144 self.items[old_module.0]
1145 .as_mut()
1146 .unwrap()
1147 .as_module_mut()
1148 .unwrap()
1149 .children_mut()
1150 .remove(&replacement_id.into());
1151
1152 self.items[new_module.0]
1153 .as_mut()
1154 .unwrap()
1155 .as_module_mut()
1156 .unwrap()
1157 .children_mut()
1158 .insert(replacement_id.into());
1159 }
1160 }
1161
1162 /// Enter the code generation phase, invoke the given callback `cb`, and
1163 /// leave the code generation phase.
gen<F, Out>(mut self, cb: F) -> (Out, BindgenOptions) where F: FnOnce(&Self) -> Out,1164 pub(crate) fn gen<F, Out>(mut self, cb: F) -> (Out, BindgenOptions)
1165 where
1166 F: FnOnce(&Self) -> Out,
1167 {
1168 self.in_codegen = true;
1169
1170 self.resolve_typerefs();
1171 self.compute_bitfield_units();
1172 self.process_replacements();
1173
1174 self.deanonymize_fields();
1175
1176 self.assert_no_dangling_references();
1177
1178 // Compute the whitelisted set after processing replacements and
1179 // resolving type refs, as those are the final mutations of the IR
1180 // graph, and their completion means that the IR graph is now frozen.
1181 self.compute_whitelisted_and_codegen_items();
1182
1183 // Make sure to do this after processing replacements, since that messes
1184 // with the parentage and module children, and we want to assert that it
1185 // messes with them correctly.
1186 self.assert_every_item_in_a_module();
1187
1188 self.compute_has_vtable();
1189 self.compute_sizedness();
1190 self.compute_has_destructor();
1191 self.find_used_template_parameters();
1192 self.compute_cannot_derive_debug();
1193 self.compute_cannot_derive_default();
1194 self.compute_cannot_derive_copy();
1195 self.compute_has_type_param_in_array();
1196 self.compute_has_float();
1197 self.compute_cannot_derive_hash();
1198 self.compute_cannot_derive_partialord_partialeq_or_eq();
1199
1200 let ret = cb(&self);
1201 (ret, self.options)
1202 }
1203
1204 /// When the `testing_only_extra_assertions` feature is enabled, this
1205 /// function walks the IR graph and asserts that we do not have any edges
1206 /// referencing an ItemId for which we do not have an associated IR item.
assert_no_dangling_references(&self)1207 fn assert_no_dangling_references(&self) {
1208 if cfg!(feature = "testing_only_extra_assertions") {
1209 for _ in self.assert_no_dangling_item_traversal() {
1210 // The iterator's next method does the asserting for us.
1211 }
1212 }
1213 }
1214
assert_no_dangling_item_traversal( &self, ) -> traversal::AssertNoDanglingItemsTraversal1215 fn assert_no_dangling_item_traversal(
1216 &self,
1217 ) -> traversal::AssertNoDanglingItemsTraversal {
1218 assert!(self.in_codegen_phase());
1219 assert!(self.current_module == self.root_module);
1220
1221 let roots = self.items().map(|(id, _)| id);
1222 traversal::AssertNoDanglingItemsTraversal::new(
1223 self,
1224 roots,
1225 traversal::all_edges,
1226 )
1227 }
1228
1229 /// When the `testing_only_extra_assertions` feature is enabled, walk over
1230 /// every item and ensure that it is in the children set of one of its
1231 /// module ancestors.
assert_every_item_in_a_module(&self)1232 fn assert_every_item_in_a_module(&self) {
1233 if cfg!(feature = "testing_only_extra_assertions") {
1234 assert!(self.in_codegen_phase());
1235 assert!(self.current_module == self.root_module);
1236
1237 for (id, _item) in self.items() {
1238 if id == self.root_module {
1239 continue;
1240 }
1241
1242 assert!(
1243 {
1244 let id = id
1245 .into_resolver()
1246 .through_type_refs()
1247 .through_type_aliases()
1248 .resolve(self)
1249 .id();
1250 id.ancestors(self)
1251 .chain(Some(self.root_module.into()))
1252 .any(|ancestor| {
1253 debug!(
1254 "Checking if {:?} is a child of {:?}",
1255 id, ancestor
1256 );
1257 self.resolve_item(ancestor)
1258 .as_module()
1259 .map_or(false, |m| {
1260 m.children().contains(&id)
1261 })
1262 })
1263 },
1264 "{:?} should be in some ancestor module's children set",
1265 id
1266 );
1267 }
1268 }
1269 }
1270
1271 /// Compute for every type whether it is sized or not, and whether it is
1272 /// sized or not as a base class.
compute_sizedness(&mut self)1273 fn compute_sizedness(&mut self) {
1274 let _t = self.timer("compute_sizedness");
1275 assert!(self.sizedness.is_none());
1276 self.sizedness = Some(analyze::<SizednessAnalysis>(self));
1277 }
1278
1279 /// Look up whether the type with the given id is sized or not.
lookup_sizedness(&self, id: TypeId) -> SizednessResult1280 pub fn lookup_sizedness(&self, id: TypeId) -> SizednessResult {
1281 assert!(
1282 self.in_codegen_phase(),
1283 "We only compute sizedness after we've entered codegen"
1284 );
1285
1286 self.sizedness
1287 .as_ref()
1288 .unwrap()
1289 .get(&id)
1290 .cloned()
1291 .unwrap_or(SizednessResult::ZeroSized)
1292 }
1293
1294 /// Compute whether the type has vtable.
compute_has_vtable(&mut self)1295 fn compute_has_vtable(&mut self) {
1296 let _t = self.timer("compute_has_vtable");
1297 assert!(self.have_vtable.is_none());
1298 self.have_vtable = Some(analyze::<HasVtableAnalysis>(self));
1299 }
1300
1301 /// Look up whether the item with `id` has vtable or not.
lookup_has_vtable(&self, id: TypeId) -> HasVtableResult1302 pub fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult {
1303 assert!(
1304 self.in_codegen_phase(),
1305 "We only compute vtables when we enter codegen"
1306 );
1307
1308 // Look up the computed value for whether the item with `id` has a
1309 // vtable or not.
1310 self.have_vtable
1311 .as_ref()
1312 .unwrap()
1313 .get(&id.into())
1314 .cloned()
1315 .unwrap_or(HasVtableResult::No)
1316 }
1317
1318 /// Compute whether the type has a destructor.
compute_has_destructor(&mut self)1319 fn compute_has_destructor(&mut self) {
1320 let _t = self.timer("compute_has_destructor");
1321 assert!(self.have_destructor.is_none());
1322 self.have_destructor = Some(analyze::<HasDestructorAnalysis>(self));
1323 }
1324
1325 /// Look up whether the item with `id` has a destructor.
lookup_has_destructor(&self, id: TypeId) -> bool1326 pub fn lookup_has_destructor(&self, id: TypeId) -> bool {
1327 assert!(
1328 self.in_codegen_phase(),
1329 "We only compute destructors when we enter codegen"
1330 );
1331
1332 self.have_destructor.as_ref().unwrap().contains(&id.into())
1333 }
1334
find_used_template_parameters(&mut self)1335 fn find_used_template_parameters(&mut self) {
1336 let _t = self.timer("find_used_template_parameters");
1337 if self.options.whitelist_recursively {
1338 let used_params = analyze::<UsedTemplateParameters>(self);
1339 self.used_template_parameters = Some(used_params);
1340 } else {
1341 // If you aren't recursively whitelisting, then we can't really make
1342 // any sense of template parameter usage, and you're on your own.
1343 let mut used_params = HashMap::default();
1344 for &id in self.whitelisted_items() {
1345 used_params.entry(id).or_insert(
1346 id.self_template_params(self)
1347 .into_iter()
1348 .map(|p| p.into())
1349 .collect(),
1350 );
1351 }
1352 self.used_template_parameters = Some(used_params);
1353 }
1354 }
1355
1356 /// Return `true` if `item` uses the given `template_param`, `false`
1357 /// otherwise.
1358 ///
1359 /// This method may only be called during the codegen phase, because the
1360 /// template usage information is only computed as we enter the codegen
1361 /// phase.
1362 ///
1363 /// If the item is blacklisted, then we say that it always uses the template
1364 /// parameter. This is a little subtle. The template parameter usage
1365 /// analysis only considers whitelisted items, and if any blacklisted item
1366 /// shows up in the generated bindings, it is the user's responsibility to
1367 /// manually provide a definition for them. To give them the most
1368 /// flexibility when doing that, we assume that they use every template
1369 /// parameter and always pass template arguments through in instantiations.
uses_template_parameter( &self, item: ItemId, template_param: TypeId, ) -> bool1370 pub fn uses_template_parameter(
1371 &self,
1372 item: ItemId,
1373 template_param: TypeId,
1374 ) -> bool {
1375 assert!(
1376 self.in_codegen_phase(),
1377 "We only compute template parameter usage as we enter codegen"
1378 );
1379
1380 if self.resolve_item(item).is_blacklisted(self) {
1381 return true;
1382 }
1383
1384 let template_param = template_param
1385 .into_resolver()
1386 .through_type_refs()
1387 .through_type_aliases()
1388 .resolve(self)
1389 .id();
1390
1391 self.used_template_parameters
1392 .as_ref()
1393 .expect("should have found template parameter usage if we're in codegen")
1394 .get(&item)
1395 .map_or(false, |items_used_params| items_used_params.contains(&template_param))
1396 }
1397
1398 /// Return `true` if `item` uses any unbound, generic template parameters,
1399 /// `false` otherwise.
1400 ///
1401 /// Has the same restrictions that `uses_template_parameter` has.
uses_any_template_parameters(&self, item: ItemId) -> bool1402 pub fn uses_any_template_parameters(&self, item: ItemId) -> bool {
1403 assert!(
1404 self.in_codegen_phase(),
1405 "We only compute template parameter usage as we enter codegen"
1406 );
1407
1408 self.used_template_parameters
1409 .as_ref()
1410 .expect(
1411 "should have template parameter usage info in codegen phase",
1412 )
1413 .get(&item)
1414 .map_or(false, |used| !used.is_empty())
1415 }
1416
1417 // This deserves a comment. Builtin types don't get a valid declaration, so
1418 // we can't add it to the cursor->type map.
1419 //
1420 // That being said, they're not generated anyway, and are few, so the
1421 // duplication and special-casing is fine.
1422 //
1423 // If at some point we care about the memory here, probably a map TypeKind
1424 // -> builtin type ItemId would be the best to improve that.
add_builtin_item(&mut self, item: Item)1425 fn add_builtin_item(&mut self, item: Item) {
1426 debug!("add_builtin_item: item = {:?}", item);
1427 debug_assert!(item.kind().is_type());
1428 self.add_item_to_module(&item);
1429 let id = item.id();
1430 let old_item = mem::replace(&mut self.items[id.0], Some(item));
1431 assert!(old_item.is_none(), "Inserted type twice?");
1432 }
1433
build_root_module(id: ItemId) -> Item1434 fn build_root_module(id: ItemId) -> Item {
1435 let module = Module::new(Some("root".into()), ModuleKind::Normal);
1436 Item::new(id, None, None, id, ItemKind::Module(module))
1437 }
1438
1439 /// Get the root module.
root_module(&self) -> ModuleId1440 pub fn root_module(&self) -> ModuleId {
1441 self.root_module
1442 }
1443
1444 /// Resolve a type with the given id.
1445 ///
1446 /// Panics if there is no item for the given `TypeId` or if the resolved
1447 /// item is not a `Type`.
resolve_type(&self, type_id: TypeId) -> &Type1448 pub fn resolve_type(&self, type_id: TypeId) -> &Type {
1449 self.resolve_item(type_id).kind().expect_type()
1450 }
1451
1452 /// Resolve a function with the given id.
1453 ///
1454 /// Panics if there is no item for the given `FunctionId` or if the resolved
1455 /// item is not a `Function`.
resolve_func(&self, func_id: FunctionId) -> &Function1456 pub fn resolve_func(&self, func_id: FunctionId) -> &Function {
1457 self.resolve_item(func_id).kind().expect_function()
1458 }
1459
1460 /// Resolve the given `ItemId` as a type, or `None` if there is no item with
1461 /// the given id.
1462 ///
1463 /// Panics if the id resolves to an item that is not a type.
safe_resolve_type(&self, type_id: TypeId) -> Option<&Type>1464 pub fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
1465 self.resolve_item_fallible(type_id)
1466 .map(|t| t.kind().expect_type())
1467 }
1468
1469 /// Resolve the given `ItemId` into an `Item`, or `None` if no such item
1470 /// exists.
resolve_item_fallible<Id: Into<ItemId>>( &self, id: Id, ) -> Option<&Item>1471 pub fn resolve_item_fallible<Id: Into<ItemId>>(
1472 &self,
1473 id: Id,
1474 ) -> Option<&Item> {
1475 self.items.get(id.into().0)?.as_ref()
1476 }
1477
1478 /// Resolve the given `ItemId` into an `Item`.
1479 ///
1480 /// Panics if the given id does not resolve to any item.
resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item1481 pub fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
1482 let item_id = item_id.into();
1483 match self.resolve_item_fallible(item_id) {
1484 Some(item) => item,
1485 None => panic!("Not an item: {:?}", item_id),
1486 }
1487 }
1488
1489 /// Get the current module.
current_module(&self) -> ModuleId1490 pub fn current_module(&self) -> ModuleId {
1491 self.current_module
1492 }
1493
1494 /// Add a semantic parent for a given type definition.
1495 ///
1496 /// We do this from the type declaration, in order to be able to find the
1497 /// correct type definition afterwards.
1498 ///
1499 /// TODO(emilio): We could consider doing this only when
1500 /// declaration.lexical_parent() != definition.lexical_parent(), but it's
1501 /// not sure it's worth it.
add_semantic_parent( &mut self, definition: clang::Cursor, parent_id: ItemId, )1502 pub fn add_semantic_parent(
1503 &mut self,
1504 definition: clang::Cursor,
1505 parent_id: ItemId,
1506 ) {
1507 self.semantic_parents.insert(definition, parent_id);
1508 }
1509
1510 /// Returns a known semantic parent for a given definition.
known_semantic_parent( &self, definition: clang::Cursor, ) -> Option<ItemId>1511 pub fn known_semantic_parent(
1512 &self,
1513 definition: clang::Cursor,
1514 ) -> Option<ItemId> {
1515 self.semantic_parents.get(&definition).cloned()
1516 }
1517
1518 /// Given a cursor pointing to the location of a template instantiation,
1519 /// return a tuple of the form `(declaration_cursor, declaration_id,
1520 /// num_expected_template_args)`.
1521 ///
1522 /// Note that `declaration_id` is not guaranteed to be in the context's item
1523 /// set! It is possible that it is a partial type that we are still in the
1524 /// middle of parsing.
get_declaration_info_for_template_instantiation( &self, instantiation: &Cursor, ) -> Option<(Cursor, ItemId, usize)>1525 fn get_declaration_info_for_template_instantiation(
1526 &self,
1527 instantiation: &Cursor,
1528 ) -> Option<(Cursor, ItemId, usize)> {
1529 instantiation
1530 .cur_type()
1531 .canonical_declaration(Some(instantiation))
1532 .and_then(|canon_decl| {
1533 self.get_resolved_type(&canon_decl).and_then(
1534 |template_decl_id| {
1535 let num_params =
1536 template_decl_id.num_self_template_params(self);
1537 if num_params == 0 {
1538 None
1539 } else {
1540 Some((
1541 *canon_decl.cursor(),
1542 template_decl_id.into(),
1543 num_params,
1544 ))
1545 }
1546 },
1547 )
1548 })
1549 .or_else(|| {
1550 // If we haven't already parsed the declaration of
1551 // the template being instantiated, then it *must*
1552 // be on the stack of types we are currently
1553 // parsing. If it wasn't then clang would have
1554 // already errored out before we started
1555 // constructing our IR because you can't instantiate
1556 // a template until it is fully defined.
1557 instantiation
1558 .referenced()
1559 .and_then(|referenced| {
1560 self.currently_parsed_types()
1561 .iter()
1562 .find(|partial_ty| *partial_ty.decl() == referenced)
1563 .cloned()
1564 })
1565 .and_then(|template_decl| {
1566 let num_template_params =
1567 template_decl.num_self_template_params(self);
1568 if num_template_params == 0 {
1569 None
1570 } else {
1571 Some((
1572 *template_decl.decl(),
1573 template_decl.id(),
1574 num_template_params,
1575 ))
1576 }
1577 })
1578 })
1579 }
1580
1581 /// Parse a template instantiation, eg `Foo<int>`.
1582 ///
1583 /// This is surprisingly difficult to do with libclang, due to the fact that
1584 /// it doesn't provide explicit template argument information, except for
1585 /// function template declarations(!?!??!).
1586 ///
1587 /// The only way to do this is manually inspecting the AST and looking for
1588 /// TypeRefs and TemplateRefs inside. This, unfortunately, doesn't work for
1589 /// more complex cases, see the comment on the assertion below.
1590 ///
1591 /// To add insult to injury, the AST itself has structure that doesn't make
1592 /// sense. Sometimes `Foo<Bar<int>>` has an AST with nesting like you might
1593 /// expect: `(Foo (Bar (int)))`. Other times, the AST we get is completely
1594 /// flat: `(Foo Bar int)`.
1595 ///
1596 /// To see an example of what this method handles:
1597 ///
1598 /// ```c++
1599 /// template<typename T>
1600 /// class Incomplete {
1601 /// T p;
1602 /// };
1603 ///
1604 /// template<typename U>
1605 /// class Foo {
1606 /// Incomplete<U> bar;
1607 /// };
1608 /// ```
1609 ///
1610 /// Finally, template instantiations are always children of the current
1611 /// module. They use their template's definition for their name, so the
1612 /// parent is only useful for ensuring that their layout tests get
1613 /// codegen'd.
instantiate_template( &mut self, with_id: ItemId, template: TypeId, ty: &clang::Type, location: clang::Cursor, ) -> Option<TypeId>1614 fn instantiate_template(
1615 &mut self,
1616 with_id: ItemId,
1617 template: TypeId,
1618 ty: &clang::Type,
1619 location: clang::Cursor,
1620 ) -> Option<TypeId> {
1621 let num_expected_args =
1622 self.resolve_type(template).num_self_template_params(self);
1623 if num_expected_args == 0 {
1624 warn!(
1625 "Tried to instantiate a template for which we could not \
1626 determine any template parameters"
1627 );
1628 return None;
1629 }
1630
1631 let mut args = vec![];
1632 let mut found_const_arg = false;
1633 let mut children = location.collect_children();
1634
1635 if children.iter().all(|c| !c.has_children()) {
1636 // This is insanity... If clang isn't giving us a properly nested
1637 // AST for which template arguments belong to which template we are
1638 // instantiating, we'll need to construct it ourselves. However,
1639 // there is an extra `NamespaceRef, NamespaceRef, ..., TemplateRef`
1640 // representing a reference to the outermost template declaration
1641 // that we need to filter out of the children. We need to do this
1642 // filtering because we already know which template declaration is
1643 // being specialized via the `location`'s type, and if we do not
1644 // filter it out, we'll add an extra layer of template instantiation
1645 // on accident.
1646 let idx = children
1647 .iter()
1648 .position(|c| c.kind() == clang_sys::CXCursor_TemplateRef);
1649 if let Some(idx) = idx {
1650 if children
1651 .iter()
1652 .take(idx)
1653 .all(|c| c.kind() == clang_sys::CXCursor_NamespaceRef)
1654 {
1655 children = children.into_iter().skip(idx + 1).collect();
1656 }
1657 }
1658 }
1659
1660 for child in children.iter().rev() {
1661 match child.kind() {
1662 clang_sys::CXCursor_TypeRef |
1663 clang_sys::CXCursor_TypedefDecl |
1664 clang_sys::CXCursor_TypeAliasDecl => {
1665 // The `with_id` id will potentially end up unused if we give up
1666 // on this type (for example, because it has const value
1667 // template args), so if we pass `with_id` as the parent, it is
1668 // potentially a dangling reference. Instead, use the canonical
1669 // template declaration as the parent. It is already parsed and
1670 // has a known-resolvable `ItemId`.
1671 let ty = Item::from_ty_or_ref(
1672 child.cur_type(),
1673 *child,
1674 Some(template.into()),
1675 self,
1676 );
1677 args.push(ty);
1678 }
1679 clang_sys::CXCursor_TemplateRef => {
1680 let (
1681 template_decl_cursor,
1682 template_decl_id,
1683 num_expected_template_args,
1684 ) = self.get_declaration_info_for_template_instantiation(
1685 child,
1686 )?;
1687
1688 if num_expected_template_args == 0 ||
1689 child.has_at_least_num_children(
1690 num_expected_template_args,
1691 )
1692 {
1693 // Do a happy little parse. See comment in the TypeRef
1694 // match arm about parent IDs.
1695 let ty = Item::from_ty_or_ref(
1696 child.cur_type(),
1697 *child,
1698 Some(template.into()),
1699 self,
1700 );
1701 args.push(ty);
1702 } else {
1703 // This is the case mentioned in the doc comment where
1704 // clang gives us a flattened AST and we have to
1705 // reconstruct which template arguments go to which
1706 // instantiation :(
1707 let args_len = args.len();
1708 if args_len < num_expected_template_args {
1709 warn!(
1710 "Found a template instantiation without \
1711 enough template arguments"
1712 );
1713 return None;
1714 }
1715
1716 let mut sub_args: Vec<_> = args
1717 .drain(args_len - num_expected_template_args..)
1718 .collect();
1719 sub_args.reverse();
1720
1721 let sub_name = Some(template_decl_cursor.spelling());
1722 let sub_inst = TemplateInstantiation::new(
1723 // This isn't guaranteed to be a type that we've
1724 // already finished parsing yet.
1725 template_decl_id.as_type_id_unchecked(),
1726 sub_args,
1727 );
1728 let sub_kind =
1729 TypeKind::TemplateInstantiation(sub_inst);
1730 let sub_ty = Type::new(
1731 sub_name,
1732 template_decl_cursor
1733 .cur_type()
1734 .fallible_layout(self)
1735 .ok(),
1736 sub_kind,
1737 false,
1738 );
1739 let sub_id = self.next_item_id();
1740 let sub_item = Item::new(
1741 sub_id,
1742 None,
1743 None,
1744 self.current_module.into(),
1745 ItemKind::Type(sub_ty),
1746 );
1747
1748 // Bypass all the validations in add_item explicitly.
1749 debug!(
1750 "instantiate_template: inserting nested \
1751 instantiation item: {:?}",
1752 sub_item
1753 );
1754 self.add_item_to_module(&sub_item);
1755 debug_assert_eq!(sub_id, sub_item.id());
1756 self.items[sub_id.0] = Some(sub_item);
1757 args.push(sub_id.as_type_id_unchecked());
1758 }
1759 }
1760 _ => {
1761 warn!(
1762 "Found template arg cursor we can't handle: {:?}",
1763 child
1764 );
1765 found_const_arg = true;
1766 }
1767 }
1768 }
1769
1770 if found_const_arg {
1771 // This is a dependently typed template instantiation. That is, an
1772 // instantiation of a template with one or more const values as
1773 // template arguments, rather than only types as template
1774 // arguments. For example, `Foo<true, 5>` versus `Bar<bool, int>`.
1775 // We can't handle these instantiations, so just punt in this
1776 // situation...
1777 warn!(
1778 "Found template instantiated with a const value; \
1779 bindgen can't handle this kind of template instantiation!"
1780 );
1781 return None;
1782 }
1783
1784 if args.len() != num_expected_args {
1785 warn!(
1786 "Found a template with an unexpected number of template \
1787 arguments"
1788 );
1789 return None;
1790 }
1791
1792 args.reverse();
1793 let type_kind = TypeKind::TemplateInstantiation(
1794 TemplateInstantiation::new(template, args),
1795 );
1796 let name = ty.spelling();
1797 let name = if name.is_empty() { None } else { Some(name) };
1798 let ty = Type::new(
1799 name,
1800 ty.fallible_layout(self).ok(),
1801 type_kind,
1802 ty.is_const(),
1803 );
1804 let item = Item::new(
1805 with_id,
1806 None,
1807 None,
1808 self.current_module.into(),
1809 ItemKind::Type(ty),
1810 );
1811
1812 // Bypass all the validations in add_item explicitly.
1813 debug!("instantiate_template: inserting item: {:?}", item);
1814 self.add_item_to_module(&item);
1815 debug_assert_eq!(with_id, item.id());
1816 self.items[with_id.0] = Some(item);
1817 Some(with_id.as_type_id_unchecked())
1818 }
1819
1820 /// If we have already resolved the type for the given type declaration,
1821 /// return its `ItemId`. Otherwise, return `None`.
get_resolved_type( &self, decl: &clang::CanonicalTypeDeclaration, ) -> Option<TypeId>1822 pub fn get_resolved_type(
1823 &self,
1824 decl: &clang::CanonicalTypeDeclaration,
1825 ) -> Option<TypeId> {
1826 self.types
1827 .get(&TypeKey::Declaration(*decl.cursor()))
1828 .or_else(|| {
1829 decl.cursor()
1830 .usr()
1831 .and_then(|usr| self.types.get(&TypeKey::USR(usr)))
1832 })
1833 .cloned()
1834 }
1835
1836 /// Looks up for an already resolved type, either because it's builtin, or
1837 /// 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>1838 pub fn builtin_or_resolved_ty(
1839 &mut self,
1840 with_id: ItemId,
1841 parent_id: Option<ItemId>,
1842 ty: &clang::Type,
1843 location: Option<clang::Cursor>,
1844 ) -> Option<TypeId> {
1845 use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
1846 debug!(
1847 "builtin_or_resolved_ty: {:?}, {:?}, {:?}",
1848 ty, location, parent_id
1849 );
1850
1851 if let Some(decl) = ty.canonical_declaration(location.as_ref()) {
1852 if let Some(id) = self.get_resolved_type(&decl) {
1853 debug!(
1854 "Already resolved ty {:?}, {:?}, {:?} {:?}",
1855 id, decl, ty, location
1856 );
1857 // If the declaration already exists, then either:
1858 //
1859 // * the declaration is a template declaration of some sort,
1860 // and we are looking at an instantiation or specialization
1861 // of it, or
1862 // * we have already parsed and resolved this type, and
1863 // there's nothing left to do.
1864 if decl.cursor().is_template_like() &&
1865 *ty != decl.cursor().cur_type() &&
1866 location.is_some()
1867 {
1868 let location = location.unwrap();
1869
1870 // For specialized type aliases, there's no way to get the
1871 // template parameters as of this writing (for a struct
1872 // specialization we wouldn't be in this branch anyway).
1873 //
1874 // Explicitly return `None` if there aren't any
1875 // unspecialized parameters (contains any `TypeRef`) so we
1876 // resolve the canonical type if there is one and it's
1877 // exposed.
1878 //
1879 // This is _tricky_, I know :(
1880 if decl.cursor().kind() == CXCursor_TypeAliasTemplateDecl &&
1881 !location.contains_cursor(CXCursor_TypeRef) &&
1882 ty.canonical_type().is_valid_and_exposed()
1883 {
1884 return None;
1885 }
1886
1887 return self
1888 .instantiate_template(with_id, id, ty, location)
1889 .or_else(|| Some(id));
1890 }
1891
1892 return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
1893 }
1894 }
1895
1896 debug!("Not resolved, maybe builtin?");
1897 self.build_builtin_ty(ty)
1898 }
1899
1900 /// Make a new item that is a resolved type reference to the `wrapped_id`.
1901 ///
1902 /// This is unfortunately a lot of bloat, but is needed to properly track
1903 /// constness et al.
1904 ///
1905 /// We should probably make the constness tracking separate, so it doesn't
1906 /// bloat that much, but hey, we already bloat the heck out of builtin
1907 /// types.
build_ty_wrapper( &mut self, with_id: ItemId, wrapped_id: TypeId, parent_id: Option<ItemId>, ty: &clang::Type, ) -> TypeId1908 pub fn build_ty_wrapper(
1909 &mut self,
1910 with_id: ItemId,
1911 wrapped_id: TypeId,
1912 parent_id: Option<ItemId>,
1913 ty: &clang::Type,
1914 ) -> TypeId {
1915 self.build_wrapper(with_id, wrapped_id, parent_id, ty, ty.is_const())
1916 }
1917
1918 /// A wrapper over a type that adds a const qualifier explicitly.
1919 ///
1920 /// 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, ) -> TypeId1921 pub fn build_const_wrapper(
1922 &mut self,
1923 with_id: ItemId,
1924 wrapped_id: TypeId,
1925 parent_id: Option<ItemId>,
1926 ty: &clang::Type,
1927 ) -> TypeId {
1928 self.build_wrapper(
1929 with_id, wrapped_id, parent_id, ty, /* is_const = */ true,
1930 )
1931 }
1932
build_wrapper( &mut self, with_id: ItemId, wrapped_id: TypeId, parent_id: Option<ItemId>, ty: &clang::Type, is_const: bool, ) -> TypeId1933 fn build_wrapper(
1934 &mut self,
1935 with_id: ItemId,
1936 wrapped_id: TypeId,
1937 parent_id: Option<ItemId>,
1938 ty: &clang::Type,
1939 is_const: bool,
1940 ) -> TypeId {
1941 let spelling = ty.spelling();
1942 let layout = ty.fallible_layout(self).ok();
1943 let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
1944 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
1945 let item = Item::new(
1946 with_id,
1947 None,
1948 None,
1949 parent_id.unwrap_or(self.current_module.into()),
1950 ItemKind::Type(ty),
1951 );
1952 self.add_builtin_item(item);
1953 with_id.as_type_id_unchecked()
1954 }
1955
1956 /// Returns the next item id to be used for an item.
next_item_id(&mut self) -> ItemId1957 pub fn next_item_id(&mut self) -> ItemId {
1958 let ret = ItemId(self.items.len());
1959 self.items.push(None);
1960 ret
1961 }
1962
build_builtin_ty(&mut self, ty: &clang::Type) -> Option<TypeId>1963 fn build_builtin_ty(&mut self, ty: &clang::Type) -> Option<TypeId> {
1964 use clang_sys::*;
1965 let type_kind = match ty.kind() {
1966 CXType_NullPtr => TypeKind::NullPtr,
1967 CXType_Void => TypeKind::Void,
1968 CXType_Bool => TypeKind::Int(IntKind::Bool),
1969 CXType_Int => TypeKind::Int(IntKind::Int),
1970 CXType_UInt => TypeKind::Int(IntKind::UInt),
1971 CXType_Char_S => TypeKind::Int(IntKind::Char { is_signed: true }),
1972 CXType_Char_U => TypeKind::Int(IntKind::Char { is_signed: false }),
1973 CXType_SChar => TypeKind::Int(IntKind::SChar),
1974 CXType_UChar => TypeKind::Int(IntKind::UChar),
1975 CXType_Short => TypeKind::Int(IntKind::Short),
1976 CXType_UShort => TypeKind::Int(IntKind::UShort),
1977 CXType_WChar => TypeKind::Int(IntKind::WChar),
1978 CXType_Char16 => TypeKind::Int(IntKind::U16),
1979 CXType_Char32 => TypeKind::Int(IntKind::U32),
1980 CXType_Long => TypeKind::Int(IntKind::Long),
1981 CXType_ULong => TypeKind::Int(IntKind::ULong),
1982 CXType_LongLong => TypeKind::Int(IntKind::LongLong),
1983 CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
1984 CXType_Int128 => TypeKind::Int(IntKind::I128),
1985 CXType_UInt128 => TypeKind::Int(IntKind::U128),
1986 CXType_Float => TypeKind::Float(FloatKind::Float),
1987 CXType_Double => TypeKind::Float(FloatKind::Double),
1988 CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
1989 CXType_Float128 => TypeKind::Float(FloatKind::Float128),
1990 CXType_Complex => {
1991 let float_type =
1992 ty.elem_type().expect("Not able to resolve complex type?");
1993 let float_kind = match float_type.kind() {
1994 CXType_Float => FloatKind::Float,
1995 CXType_Double => FloatKind::Double,
1996 CXType_LongDouble => FloatKind::LongDouble,
1997 CXType_Float128 => FloatKind::Float128,
1998 _ => panic!(
1999 "Non floating-type complex? {:?}, {:?}",
2000 ty, float_type,
2001 ),
2002 };
2003 TypeKind::Complex(float_kind)
2004 }
2005 _ => return None,
2006 };
2007
2008 let spelling = ty.spelling();
2009 let is_const = ty.is_const();
2010 let layout = ty.fallible_layout(self).ok();
2011 let ty = Type::new(Some(spelling), layout, type_kind, is_const);
2012 let id = self.next_item_id();
2013 let item = Item::new(
2014 id,
2015 None,
2016 None,
2017 self.root_module.into(),
2018 ItemKind::Type(ty),
2019 );
2020 self.add_builtin_item(item);
2021 Some(id.as_type_id_unchecked())
2022 }
2023
2024 /// Get the current Clang translation unit that is being processed.
translation_unit(&self) -> &clang::TranslationUnit2025 pub fn translation_unit(&self) -> &clang::TranslationUnit {
2026 &self.translation_unit
2027 }
2028
2029 /// Have we parsed the macro named `macro_name` already?
parsed_macro(&self, macro_name: &[u8]) -> bool2030 pub fn parsed_macro(&self, macro_name: &[u8]) -> bool {
2031 self.parsed_macros.contains_key(macro_name)
2032 }
2033
2034 /// Get the currently parsed macros.
parsed_macros( &self, ) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult>2035 pub fn parsed_macros(
2036 &self,
2037 ) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult> {
2038 debug_assert!(!self.in_codegen_phase());
2039 &self.parsed_macros
2040 }
2041
2042 /// Mark the macro named `macro_name` as parsed.
note_parsed_macro( &mut self, id: Vec<u8>, value: cexpr::expr::EvalResult, )2043 pub fn note_parsed_macro(
2044 &mut self,
2045 id: Vec<u8>,
2046 value: cexpr::expr::EvalResult,
2047 ) {
2048 self.parsed_macros.insert(id, value);
2049 }
2050
2051 /// Are we in the codegen phase?
in_codegen_phase(&self) -> bool2052 pub fn in_codegen_phase(&self) -> bool {
2053 self.in_codegen
2054 }
2055
2056 /// Mark the type with the given `name` as replaced by the type with id
2057 /// `potential_ty`.
2058 ///
2059 /// Replacement types are declared using the `replaces="xxx"` annotation,
2060 /// and implies that the original type is hidden.
replace(&mut self, name: &[String], potential_ty: ItemId)2061 pub fn replace(&mut self, name: &[String], potential_ty: ItemId) {
2062 match self.replacements.entry(name.into()) {
2063 Entry::Vacant(entry) => {
2064 debug!(
2065 "Defining replacement for {:?} as {:?}",
2066 name, potential_ty
2067 );
2068 entry.insert(potential_ty);
2069 }
2070 Entry::Occupied(occupied) => {
2071 warn!(
2072 "Replacement for {:?} already defined as {:?}; \
2073 ignoring duplicate replacement definition as {:?}",
2074 name,
2075 occupied.get(),
2076 potential_ty
2077 );
2078 }
2079 }
2080 }
2081
2082 /// Has the item with the given `name` and `id` been replaced by another
2083 /// type?
is_replaced_type<Id: Into<ItemId>>( &self, path: &[String], id: Id, ) -> bool2084 pub fn is_replaced_type<Id: Into<ItemId>>(
2085 &self,
2086 path: &[String],
2087 id: Id,
2088 ) -> bool {
2089 let id = id.into();
2090 match self.replacements.get(path) {
2091 Some(replaced_by) if *replaced_by != id => true,
2092 _ => false,
2093 }
2094 }
2095
2096 /// Is the type with the given `name` marked as opaque?
opaque_by_name(&self, path: &[String]) -> bool2097 pub fn opaque_by_name(&self, path: &[String]) -> bool {
2098 debug_assert!(
2099 self.in_codegen_phase(),
2100 "You're not supposed to call this yet"
2101 );
2102 self.options.opaque_types.matches(&path[1..].join("::"))
2103 }
2104
2105 /// Get the options used to configure this bindgen context.
options(&self) -> &BindgenOptions2106 pub(crate) fn options(&self) -> &BindgenOptions {
2107 &self.options
2108 }
2109
2110 /// Tokenizes a namespace cursor in order to get the name and kind of the
2111 /// namespace.
tokenize_namespace( &self, cursor: &clang::Cursor, ) -> (Option<String>, ModuleKind)2112 fn tokenize_namespace(
2113 &self,
2114 cursor: &clang::Cursor,
2115 ) -> (Option<String>, ModuleKind) {
2116 assert_eq!(
2117 cursor.kind(),
2118 ::clang_sys::CXCursor_Namespace,
2119 "Be a nice person"
2120 );
2121
2122 let mut module_name = None;
2123 let spelling = cursor.spelling();
2124 if !spelling.is_empty() {
2125 module_name = Some(spelling)
2126 }
2127
2128 let tokens = cursor.tokens();
2129 let mut iter = tokens.iter();
2130 let mut kind = ModuleKind::Normal;
2131 let mut found_namespace_keyword = false;
2132 while let Some(token) = iter.next() {
2133 match token.spelling() {
2134 b"inline" => {
2135 assert!(!found_namespace_keyword);
2136 assert!(kind != ModuleKind::Inline);
2137 kind = ModuleKind::Inline;
2138 }
2139 // The double colon allows us to handle nested namespaces like
2140 // namespace foo::bar { }
2141 //
2142 // libclang still gives us two namespace cursors, which is cool,
2143 // but the tokenization of the second begins with the double
2144 // colon. That's ok, so we only need to handle the weird
2145 // tokenization here.
2146 //
2147 // Fortunately enough, inline nested namespace specifiers aren't
2148 // a thing, and are invalid C++ :)
2149 b"namespace" | b"::" => {
2150 found_namespace_keyword = true;
2151 }
2152 b"{" => {
2153 assert!(found_namespace_keyword);
2154 break;
2155 }
2156 name if found_namespace_keyword => {
2157 if module_name.is_none() {
2158 module_name =
2159 Some(String::from_utf8_lossy(name).into_owned());
2160 }
2161 break;
2162 }
2163 _ => {
2164 panic!(
2165 "Unknown token while processing namespace: {:?}",
2166 token
2167 );
2168 }
2169 }
2170 }
2171
2172 (module_name, kind)
2173 }
2174
2175 /// Given a CXCursor_Namespace cursor, return the item id of the
2176 /// corresponding module, or create one on the fly.
module(&mut self, cursor: clang::Cursor) -> ModuleId2177 pub fn module(&mut self, cursor: clang::Cursor) -> ModuleId {
2178 use clang_sys::*;
2179 assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person");
2180 let cursor = cursor.canonical();
2181 if let Some(id) = self.modules.get(&cursor) {
2182 return *id;
2183 }
2184
2185 let (module_name, kind) = self.tokenize_namespace(&cursor);
2186
2187 let module_id = self.next_item_id();
2188 let module = Module::new(module_name, kind);
2189 let module = Item::new(
2190 module_id,
2191 None,
2192 None,
2193 self.current_module.into(),
2194 ItemKind::Module(module),
2195 );
2196
2197 let module_id = module.id().as_module_id_unchecked();
2198 self.modules.insert(cursor, module_id);
2199
2200 self.add_item(module, None, None);
2201
2202 module_id
2203 }
2204
2205 /// Start traversing the module with the given `module_id`, invoke the
2206 /// 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),2207 pub fn with_module<F>(&mut self, module_id: ModuleId, cb: F)
2208 where
2209 F: FnOnce(&mut Self),
2210 {
2211 debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat");
2212
2213 let previous_id = self.current_module;
2214 self.current_module = module_id;
2215
2216 cb(self);
2217
2218 self.current_module = previous_id;
2219 }
2220
2221 /// Iterate over all (explicitly or transitively) whitelisted items.
2222 ///
2223 /// If no items are explicitly whitelisted, then all items are considered
2224 /// whitelisted.
whitelisted_items(&self) -> &ItemSet2225 pub fn whitelisted_items(&self) -> &ItemSet {
2226 assert!(self.in_codegen_phase());
2227 assert!(self.current_module == self.root_module);
2228
2229 self.whitelisted.as_ref().unwrap()
2230 }
2231
2232 /// Get a reference to the set of items we should generate.
codegen_items(&self) -> &ItemSet2233 pub fn codegen_items(&self) -> &ItemSet {
2234 assert!(self.in_codegen_phase());
2235 assert!(self.current_module == self.root_module);
2236 self.codegen_items.as_ref().unwrap()
2237 }
2238
2239 /// Compute the whitelisted items set and populate `self.whitelisted`.
compute_whitelisted_and_codegen_items(&mut self)2240 fn compute_whitelisted_and_codegen_items(&mut self) {
2241 assert!(self.in_codegen_phase());
2242 assert!(self.current_module == self.root_module);
2243 assert!(self.whitelisted.is_none());
2244 let _t = self.timer("compute_whitelisted_and_codegen_items");
2245
2246 let roots = {
2247 let mut roots = self
2248 .items()
2249 // Only consider roots that are enabled for codegen.
2250 .filter(|&(_, item)| item.is_enabled_for_codegen(self))
2251 .filter(|&(_, item)| {
2252 // If nothing is explicitly whitelisted, then everything is fair
2253 // game.
2254 if self.options().whitelisted_types.is_empty() &&
2255 self.options().whitelisted_functions.is_empty() &&
2256 self.options().whitelisted_vars.is_empty()
2257 {
2258 return true;
2259 }
2260
2261 // If this is a type that explicitly replaces another, we assume
2262 // you know what you're doing.
2263 if item.annotations().use_instead_of().is_some() {
2264 return true;
2265 }
2266
2267 let name = item.path_for_whitelisting(self)[1..].join("::");
2268 debug!("whitelisted_items: testing {:?}", name);
2269 match *item.kind() {
2270 ItemKind::Module(..) => true,
2271 ItemKind::Function(_) => {
2272 self.options().whitelisted_functions.matches(&name)
2273 }
2274 ItemKind::Var(_) => {
2275 self.options().whitelisted_vars.matches(&name)
2276 }
2277 ItemKind::Type(ref ty) => {
2278 if self.options().whitelisted_types.matches(&name) {
2279 return true;
2280 }
2281
2282 // Auto-whitelist types that don't need code
2283 // generation if not whitelisting recursively, to
2284 // make the #[derive] analysis not be lame.
2285 if !self.options().whitelist_recursively {
2286 match *ty.kind() {
2287 TypeKind::Void |
2288 TypeKind::NullPtr |
2289 TypeKind::Int(..) |
2290 TypeKind::Float(..) |
2291 TypeKind::Complex(..) |
2292 TypeKind::Array(..) |
2293 TypeKind::Vector(..) |
2294 TypeKind::Pointer(..) |
2295 TypeKind::Reference(..) |
2296 TypeKind::Function(..) |
2297 TypeKind::ResolvedTypeRef(..) |
2298 TypeKind::Opaque |
2299 TypeKind::TypeParam => return true,
2300 _ => {}
2301 };
2302 }
2303
2304 // Unnamed top-level enums are special and we
2305 // whitelist them via the `whitelisted_vars` filter,
2306 // since they're effectively top-level constants,
2307 // and there's no way for them to be referenced
2308 // consistently.
2309 let parent = self.resolve_item(item.parent_id());
2310 if !parent.is_module() {
2311 return false;
2312 }
2313
2314 let enum_ = match *ty.kind() {
2315 TypeKind::Enum(ref e) => e,
2316 _ => return false,
2317 };
2318
2319 if ty.name().is_some() {
2320 return false;
2321 }
2322
2323 let mut prefix_path =
2324 parent.path_for_whitelisting(self);
2325 enum_.variants().iter().any(|variant| {
2326 prefix_path.push(variant.name().into());
2327 let name = prefix_path[1..].join("::");
2328 prefix_path.pop().unwrap();
2329 self.options().whitelisted_vars.matches(&name)
2330 })
2331 }
2332 }
2333 })
2334 .map(|(id, _)| id)
2335 .collect::<Vec<_>>();
2336
2337 // The reversal preserves the expected ordering of traversal,
2338 // resulting in more stable-ish bindgen-generated names for
2339 // anonymous types (like unions).
2340 roots.reverse();
2341 roots
2342 };
2343
2344 let whitelisted_items_predicate =
2345 if self.options().whitelist_recursively {
2346 traversal::all_edges
2347 } else {
2348 // Only follow InnerType edges from the whitelisted roots.
2349 // Such inner types (e.g. anonymous structs/unions) are
2350 // always emitted by codegen, and they need to be whitelisted
2351 // to make sure they are processed by e.g. the derive analysis.
2352 traversal::only_inner_type_edges
2353 };
2354
2355 let whitelisted = WhitelistedItemsTraversal::new(
2356 self,
2357 roots.clone(),
2358 whitelisted_items_predicate,
2359 )
2360 .collect::<ItemSet>();
2361
2362 let codegen_items = if self.options().whitelist_recursively {
2363 WhitelistedItemsTraversal::new(
2364 self,
2365 roots.clone(),
2366 traversal::codegen_edges,
2367 )
2368 .collect::<ItemSet>()
2369 } else {
2370 whitelisted.clone()
2371 };
2372
2373 self.whitelisted = Some(whitelisted);
2374 self.codegen_items = Some(codegen_items);
2375
2376 for item in self.options().whitelisted_functions.unmatched_items() {
2377 error!("unused option: --whitelist-function {}", item);
2378 }
2379
2380 for item in self.options().whitelisted_vars.unmatched_items() {
2381 error!("unused option: --whitelist-var {}", item);
2382 }
2383
2384 for item in self.options().whitelisted_types.unmatched_items() {
2385 error!("unused option: --whitelist-type {}", item);
2386 }
2387 }
2388
2389 /// Convenient method for getting the prefix to use for most traits in
2390 /// codegen depending on the `use_core` option.
trait_prefix(&self) -> Ident2391 pub fn trait_prefix(&self) -> Ident {
2392 if self.options().use_core {
2393 self.rust_ident_raw("core")
2394 } else {
2395 self.rust_ident_raw("std")
2396 }
2397 }
2398
2399 /// Call if a bindgen complex is generated
generated_bindgen_complex(&self)2400 pub fn generated_bindgen_complex(&self) {
2401 self.generated_bindgen_complex.set(true)
2402 }
2403
2404 /// Whether we need to generate the bindgen complex type
need_bindgen_complex_type(&self) -> bool2405 pub fn need_bindgen_complex_type(&self) -> bool {
2406 self.generated_bindgen_complex.get()
2407 }
2408
2409 /// Compute whether we can derive debug.
compute_cannot_derive_debug(&mut self)2410 fn compute_cannot_derive_debug(&mut self) {
2411 let _t = self.timer("compute_cannot_derive_debug");
2412 assert!(self.cannot_derive_debug.is_none());
2413 if self.options.derive_debug {
2414 self.cannot_derive_debug =
2415 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2416 self,
2417 DeriveTrait::Debug,
2418 ))));
2419 }
2420 }
2421
2422 /// Look up whether the item with `id` can
2423 /// derive debug or not.
lookup_can_derive_debug<Id: Into<ItemId>>(&self, id: Id) -> bool2424 pub fn lookup_can_derive_debug<Id: Into<ItemId>>(&self, id: Id) -> bool {
2425 let id = id.into();
2426 assert!(
2427 self.in_codegen_phase(),
2428 "We only compute can_derive_debug when we enter codegen"
2429 );
2430
2431 // Look up the computed value for whether the item with `id` can
2432 // derive debug or not.
2433 !self.cannot_derive_debug.as_ref().unwrap().contains(&id)
2434 }
2435
2436 /// Compute whether we can derive default.
compute_cannot_derive_default(&mut self)2437 fn compute_cannot_derive_default(&mut self) {
2438 let _t = self.timer("compute_cannot_derive_default");
2439 assert!(self.cannot_derive_default.is_none());
2440 if self.options.derive_default {
2441 self.cannot_derive_default =
2442 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2443 self,
2444 DeriveTrait::Default,
2445 ))));
2446 }
2447 }
2448
2449 /// Look up whether the item with `id` can
2450 /// derive default or not.
lookup_can_derive_default<Id: Into<ItemId>>(&self, id: Id) -> bool2451 pub fn lookup_can_derive_default<Id: Into<ItemId>>(&self, id: Id) -> bool {
2452 let id = id.into();
2453 assert!(
2454 self.in_codegen_phase(),
2455 "We only compute can_derive_default when we enter codegen"
2456 );
2457
2458 // Look up the computed value for whether the item with `id` can
2459 // derive default or not.
2460 !self.cannot_derive_default.as_ref().unwrap().contains(&id)
2461 }
2462
2463 /// Compute whether we can derive copy.
compute_cannot_derive_copy(&mut self)2464 fn compute_cannot_derive_copy(&mut self) {
2465 let _t = self.timer("compute_cannot_derive_copy");
2466 assert!(self.cannot_derive_copy.is_none());
2467 self.cannot_derive_copy =
2468 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2469 self,
2470 DeriveTrait::Copy,
2471 ))));
2472 }
2473
2474 /// Compute whether we can derive hash.
compute_cannot_derive_hash(&mut self)2475 fn compute_cannot_derive_hash(&mut self) {
2476 let _t = self.timer("compute_cannot_derive_hash");
2477 assert!(self.cannot_derive_hash.is_none());
2478 if self.options.derive_hash {
2479 self.cannot_derive_hash =
2480 Some(as_cannot_derive_set(analyze::<CannotDerive>((
2481 self,
2482 DeriveTrait::Hash,
2483 ))));
2484 }
2485 }
2486
2487 /// Look up whether the item with `id` can
2488 /// derive hash or not.
lookup_can_derive_hash<Id: Into<ItemId>>(&self, id: Id) -> bool2489 pub fn lookup_can_derive_hash<Id: Into<ItemId>>(&self, id: Id) -> bool {
2490 let id = id.into();
2491 assert!(
2492 self.in_codegen_phase(),
2493 "We only compute can_derive_debug when we enter codegen"
2494 );
2495
2496 // Look up the computed value for whether the item with `id` can
2497 // derive hash or not.
2498 !self.cannot_derive_hash.as_ref().unwrap().contains(&id)
2499 }
2500
2501 /// Compute whether we can derive PartialOrd, PartialEq or Eq.
compute_cannot_derive_partialord_partialeq_or_eq(&mut self)2502 fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) {
2503 let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq");
2504 assert!(self.cannot_derive_partialeq_or_partialord.is_none());
2505 if self.options.derive_partialord ||
2506 self.options.derive_partialeq ||
2507 self.options.derive_eq
2508 {
2509 self.cannot_derive_partialeq_or_partialord =
2510 Some(analyze::<CannotDerive>((
2511 self,
2512 DeriveTrait::PartialEqOrPartialOrd,
2513 )));
2514 }
2515 }
2516
2517 /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`.
lookup_can_derive_partialeq_or_partialord<Id: Into<ItemId>>( &self, id: Id, ) -> CanDerive2518 pub fn lookup_can_derive_partialeq_or_partialord<Id: Into<ItemId>>(
2519 &self,
2520 id: Id,
2521 ) -> CanDerive {
2522 let id = id.into();
2523 assert!(
2524 self.in_codegen_phase(),
2525 "We only compute can_derive_partialeq_or_partialord when we enter codegen"
2526 );
2527
2528 // Look up the computed value for whether the item with `id` can
2529 // derive partialeq or not.
2530 self.cannot_derive_partialeq_or_partialord
2531 .as_ref()
2532 .unwrap()
2533 .get(&id)
2534 .cloned()
2535 .unwrap_or(CanDerive::Yes)
2536 }
2537
2538 /// Look up whether the item with `id` can derive `Copy` or not.
lookup_can_derive_copy<Id: Into<ItemId>>(&self, id: Id) -> bool2539 pub fn lookup_can_derive_copy<Id: Into<ItemId>>(&self, id: Id) -> bool {
2540 assert!(
2541 self.in_codegen_phase(),
2542 "We only compute can_derive_debug when we enter codegen"
2543 );
2544
2545 // Look up the computed value for whether the item with `id` can
2546 // derive `Copy` or not.
2547 let id = id.into();
2548
2549 !self.lookup_has_type_param_in_array(id) &&
2550 !self.cannot_derive_copy.as_ref().unwrap().contains(&id)
2551 }
2552
2553 /// Compute whether the type has type parameter in array.
compute_has_type_param_in_array(&mut self)2554 fn compute_has_type_param_in_array(&mut self) {
2555 let _t = self.timer("compute_has_type_param_in_array");
2556 assert!(self.has_type_param_in_array.is_none());
2557 self.has_type_param_in_array =
2558 Some(analyze::<HasTypeParameterInArray>(self));
2559 }
2560
2561 /// 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, ) -> bool2562 pub fn lookup_has_type_param_in_array<Id: Into<ItemId>>(
2563 &self,
2564 id: Id,
2565 ) -> bool {
2566 assert!(
2567 self.in_codegen_phase(),
2568 "We only compute has array when we enter codegen"
2569 );
2570
2571 // Look up the computed value for whether the item with `id` has
2572 // type parameter in array or not.
2573 self.has_type_param_in_array
2574 .as_ref()
2575 .unwrap()
2576 .contains(&id.into())
2577 }
2578
2579 /// Compute whether the type has float.
compute_has_float(&mut self)2580 fn compute_has_float(&mut self) {
2581 let _t = self.timer("compute_has_float");
2582 assert!(self.has_float.is_none());
2583 if self.options.derive_eq || self.options.derive_ord {
2584 self.has_float = Some(analyze::<HasFloat>(self));
2585 }
2586 }
2587
2588 /// Look up whether the item with `id` has array or not.
lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool2589 pub fn lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool {
2590 assert!(
2591 self.in_codegen_phase(),
2592 "We only compute has float when we enter codegen"
2593 );
2594
2595 // Look up the computed value for whether the item with `id` has
2596 // float or not.
2597 self.has_float.as_ref().unwrap().contains(&id.into())
2598 }
2599
2600 /// Check if `--no-partialeq` flag is enabled for this item.
no_partialeq_by_name(&self, item: &Item) -> bool2601 pub fn no_partialeq_by_name(&self, item: &Item) -> bool {
2602 let name = item.path_for_whitelisting(self)[1..].join("::");
2603 self.options().no_partialeq_types.matches(&name)
2604 }
2605
2606 /// Check if `--no-copy` flag is enabled for this item.
no_copy_by_name(&self, item: &Item) -> bool2607 pub fn no_copy_by_name(&self, item: &Item) -> bool {
2608 let name = item.path_for_whitelisting(self)[1..].join("::");
2609 self.options().no_copy_types.matches(&name)
2610 }
2611
2612 /// Check if `--no-hash` flag is enabled for this item.
no_hash_by_name(&self, item: &Item) -> bool2613 pub fn no_hash_by_name(&self, item: &Item) -> bool {
2614 let name = item.path_for_whitelisting(self)[1..].join("::");
2615 self.options().no_hash_types.matches(&name)
2616 }
2617 }
2618
2619 /// A builder struct for configuring item resolution options.
2620 #[derive(Debug, Copy, Clone)]
2621 pub struct ItemResolver {
2622 id: ItemId,
2623 through_type_refs: bool,
2624 through_type_aliases: bool,
2625 }
2626
2627 impl ItemId {
2628 /// Create an `ItemResolver` from this item id.
into_resolver(self) -> ItemResolver2629 pub fn into_resolver(self) -> ItemResolver {
2630 self.into()
2631 }
2632 }
2633
2634 impl<T> From<T> for ItemResolver
2635 where
2636 T: Into<ItemId>,
2637 {
from(id: T) -> ItemResolver2638 fn from(id: T) -> ItemResolver {
2639 ItemResolver::new(id)
2640 }
2641 }
2642
2643 impl ItemResolver {
2644 /// Construct a new `ItemResolver` from the given id.
new<Id: Into<ItemId>>(id: Id) -> ItemResolver2645 pub fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
2646 let id = id.into();
2647 ItemResolver {
2648 id: id,
2649 through_type_refs: false,
2650 through_type_aliases: false,
2651 }
2652 }
2653
2654 /// Keep resolving through `Type::TypeRef` items.
through_type_refs(mut self) -> ItemResolver2655 pub fn through_type_refs(mut self) -> ItemResolver {
2656 self.through_type_refs = true;
2657 self
2658 }
2659
2660 /// Keep resolving through `Type::Alias` items.
through_type_aliases(mut self) -> ItemResolver2661 pub fn through_type_aliases(mut self) -> ItemResolver {
2662 self.through_type_aliases = true;
2663 self
2664 }
2665
2666 /// Finish configuring and perform the actual item resolution.
resolve(self, ctx: &BindgenContext) -> &Item2667 pub fn resolve(self, ctx: &BindgenContext) -> &Item {
2668 assert!(ctx.collected_typerefs());
2669
2670 let mut id = self.id;
2671 loop {
2672 let item = ctx.resolve_item(id);
2673 let ty_kind = item.as_type().map(|t| t.kind());
2674 match ty_kind {
2675 Some(&TypeKind::ResolvedTypeRef(next_id))
2676 if self.through_type_refs =>
2677 {
2678 id = next_id.into();
2679 }
2680 // We intentionally ignore template aliases here, as they are
2681 // more complicated, and don't represent a simple renaming of
2682 // some type.
2683 Some(&TypeKind::Alias(next_id))
2684 if self.through_type_aliases =>
2685 {
2686 id = next_id.into();
2687 }
2688 _ => return item,
2689 }
2690 }
2691 }
2692 }
2693
2694 /// A type that we are in the middle of parsing.
2695 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
2696 pub struct PartialType {
2697 decl: Cursor,
2698 // Just an ItemId, and not a TypeId, because we haven't finished this type
2699 // yet, so there's still time for things to go wrong.
2700 id: ItemId,
2701 }
2702
2703 impl PartialType {
2704 /// Construct a new `PartialType`.
new(decl: Cursor, id: ItemId) -> PartialType2705 pub fn new(decl: Cursor, id: ItemId) -> PartialType {
2706 // assert!(decl == decl.canonical());
2707 PartialType { decl: decl, id: id }
2708 }
2709
2710 /// The cursor pointing to this partial type's declaration location.
decl(&self) -> &Cursor2711 pub fn decl(&self) -> &Cursor {
2712 &self.decl
2713 }
2714
2715 /// The item ID allocated for this type. This is *NOT* a key for an entry in
2716 /// the context's item set yet!
id(&self) -> ItemId2717 pub fn id(&self) -> ItemId {
2718 self.id
2719 }
2720 }
2721
2722 impl TemplateParameters for PartialType {
self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId>2723 fn self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId> {
2724 // Maybe at some point we will eagerly parse named types, but for now we
2725 // don't and this information is unavailable.
2726 vec![]
2727 }
2728
num_self_template_params(&self, _ctx: &BindgenContext) -> usize2729 fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize {
2730 // Wouldn't it be nice if libclang would reliably give us this
2731 // information‽
2732 match self.decl().kind() {
2733 clang_sys::CXCursor_ClassTemplate |
2734 clang_sys::CXCursor_FunctionTemplate |
2735 clang_sys::CXCursor_TypeAliasTemplateDecl => {
2736 let mut num_params = 0;
2737 self.decl().visit(|c| {
2738 match c.kind() {
2739 clang_sys::CXCursor_TemplateTypeParameter |
2740 clang_sys::CXCursor_TemplateTemplateParameter |
2741 clang_sys::CXCursor_NonTypeTemplateParameter => {
2742 num_params += 1;
2743 }
2744 _ => {}
2745 };
2746 clang_sys::CXChildVisit_Continue
2747 });
2748 num_params
2749 }
2750 _ => 0,
2751 }
2752 }
2753 }
2754