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