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