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