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