1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use std::io::Write; 6 7 use syn; 8 9 use crate::bindgen::config::{Config, Language, LayoutConfig}; 10 use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; 11 use crate::bindgen::dependencies::Dependencies; 12 use crate::bindgen::ir::{ 13 AnnotationSet, Cfg, ConditionWrite, Constant, Documentation, GenericParams, Item, 14 ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition, Type, Typedef, 15 }; 16 use crate::bindgen::library::Library; 17 use crate::bindgen::mangle; 18 use crate::bindgen::monomorph::Monomorphs; 19 use crate::bindgen::rename::{IdentifierType, RenameRule}; 20 use crate::bindgen::reserved; 21 use crate::bindgen::utilities::{find_first_some, IterHelpers}; 22 use crate::bindgen::writer::{ListType, Source, SourceWriter}; 23 24 #[derive(Debug, Clone)] 25 pub struct Struct { 26 pub path: Path, 27 pub export_name: String, 28 pub generic_params: GenericParams, 29 pub fields: Vec<(String, Type, Documentation)>, 30 /// Whether there's a tag field on the body of this struct. When this is 31 /// true, is_enum_variant_body is also guaranteed to be true. 32 pub is_tagged: bool, 33 /// Whether this is an enum variant body. 34 pub is_enum_variant_body: bool, 35 pub alignment: Option<ReprAlign>, 36 pub is_transparent: bool, 37 pub tuple_struct: bool, 38 pub cfg: Option<Cfg>, 39 pub annotations: AnnotationSet, 40 pub documentation: Documentation, 41 pub associated_constants: Vec<Constant>, 42 } 43 44 impl Struct { 45 /// Whether this struct can derive operator== / operator!=. can_derive_eq(&self) -> bool46 pub fn can_derive_eq(&self) -> bool { 47 !self.fields.is_empty() && self.fields.iter().all(|x| x.1.can_cmp_eq()) 48 } 49 add_associated_constant(&mut self, c: Constant)50 pub fn add_associated_constant(&mut self, c: Constant) { 51 self.associated_constants.push(c); 52 } 53 load( layout_config: &LayoutConfig, item: &syn::ItemStruct, mod_cfg: Option<&Cfg>, ) -> Result<Self, String>54 pub fn load( 55 layout_config: &LayoutConfig, 56 item: &syn::ItemStruct, 57 mod_cfg: Option<&Cfg>, 58 ) -> Result<Self, String> { 59 let repr = Repr::load(&item.attrs)?; 60 let is_transparent = match repr.style { 61 ReprStyle::C => false, 62 ReprStyle::Transparent => true, 63 _ => { 64 return Err("Struct is not marked #[repr(C)] or #[repr(transparent)].".to_owned()); 65 } 66 }; 67 68 let path = Path::new(item.ident.to_string()); 69 70 // Ensure we can safely represent the struct given the configuration. 71 if let Some(align) = repr.align { 72 layout_config.ensure_safe_to_represent(&align)?; 73 } 74 75 let (fields, tuple_struct) = match item.fields { 76 syn::Fields::Unit => (Vec::new(), false), 77 syn::Fields::Named(ref fields) => { 78 let out = fields 79 .named 80 .iter() 81 .try_skip_map(|x| x.as_ident_and_type(&path))?; 82 (out, false) 83 } 84 syn::Fields::Unnamed(ref fields) => { 85 let mut out = Vec::new(); 86 let mut current = 0; 87 for field in fields.unnamed.iter() { 88 if let Some(mut x) = Type::load(&field.ty)? { 89 x.replace_self_with(&path); 90 out.push((format!("{}", current), x, Documentation::load(&field.attrs))); 91 current += 1; 92 } 93 } 94 (out, true) 95 } 96 }; 97 98 let is_tagged = false; 99 let is_enum_variant_body = false; 100 101 Ok(Struct::new( 102 path, 103 GenericParams::new(&item.generics), 104 fields, 105 is_tagged, 106 is_enum_variant_body, 107 repr.align, 108 is_transparent, 109 tuple_struct, 110 Cfg::append(mod_cfg, Cfg::load(&item.attrs)), 111 AnnotationSet::load(&item.attrs)?, 112 Documentation::load(&item.attrs), 113 )) 114 } 115 new( path: Path, generic_params: GenericParams, fields: Vec<(String, Type, Documentation)>, is_tagged: bool, is_enum_variant_body: bool, alignment: Option<ReprAlign>, is_transparent: bool, tuple_struct: bool, cfg: Option<Cfg>, annotations: AnnotationSet, documentation: Documentation, ) -> Self116 pub fn new( 117 path: Path, 118 generic_params: GenericParams, 119 fields: Vec<(String, Type, Documentation)>, 120 is_tagged: bool, 121 is_enum_variant_body: bool, 122 alignment: Option<ReprAlign>, 123 is_transparent: bool, 124 tuple_struct: bool, 125 cfg: Option<Cfg>, 126 annotations: AnnotationSet, 127 documentation: Documentation, 128 ) -> Self { 129 let export_name = path.name().to_owned(); 130 Self { 131 path, 132 export_name, 133 generic_params, 134 fields, 135 is_tagged, 136 is_enum_variant_body, 137 alignment, 138 is_transparent, 139 tuple_struct, 140 cfg, 141 annotations, 142 documentation, 143 associated_constants: vec![], 144 } 145 } 146 simplify_standard_types(&mut self)147 pub fn simplify_standard_types(&mut self) { 148 for &mut (_, ref mut ty, _) in &mut self.fields { 149 ty.simplify_standard_types(); 150 } 151 } 152 is_generic(&self) -> bool153 pub fn is_generic(&self) -> bool { 154 self.generic_params.len() > 0 155 } 156 add_monomorphs(&self, library: &Library, out: &mut Monomorphs)157 pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) { 158 // Generic structs can instantiate monomorphs only once they've been 159 // instantiated. See `instantiate_monomorph` for more details. 160 if self.is_generic() { 161 return; 162 } 163 164 for &(_, ref ty, _) in &self.fields { 165 ty.add_monomorphs(library, out); 166 } 167 } 168 mangle_paths(&mut self, monomorphs: &Monomorphs)169 pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) { 170 for &mut (_, ref mut ty, _) in &mut self.fields { 171 ty.mangle_paths(monomorphs); 172 } 173 } 174 specialize(&self, generic_values: &[Type], mappings: &[(&Path, &Type)]) -> Self175 pub fn specialize(&self, generic_values: &[Type], mappings: &[(&Path, &Type)]) -> Self { 176 let mangled_path = mangle::mangle_path(&self.path, generic_values); 177 Struct::new( 178 mangled_path, 179 GenericParams::default(), 180 self.fields 181 .iter() 182 .map(|x| (x.0.clone(), x.1.specialize(mappings), x.2.clone())) 183 .collect(), 184 self.is_tagged, 185 self.is_enum_variant_body, 186 self.alignment, 187 self.is_transparent, 188 self.tuple_struct, 189 self.cfg.clone(), 190 self.annotations.clone(), 191 self.documentation.clone(), 192 ) 193 } 194 emit_bitflags_binop<F: Write>( &self, operator: char, other: &str, out: &mut SourceWriter<F>, )195 fn emit_bitflags_binop<F: Write>( 196 &self, 197 operator: char, 198 other: &str, 199 out: &mut SourceWriter<F>, 200 ) { 201 out.new_line(); 202 write!( 203 out, 204 "{} operator{}(const {}& {}) const", 205 self.export_name(), 206 operator, 207 self.export_name(), 208 other 209 ); 210 out.open_brace(); 211 write!( 212 out, 213 "return {{static_cast<decltype(bits)>(this->bits {} {}.bits)}};", 214 operator, other 215 ); 216 out.close_brace(false); 217 218 out.new_line(); 219 write!( 220 out, 221 "{}& operator{}=(const {}& {})", 222 self.export_name(), 223 operator, 224 self.export_name(), 225 other 226 ); 227 out.open_brace(); 228 write!(out, "*this = (*this {} {});", operator, other); 229 out.new_line(); 230 write!(out, "return *this;"); 231 out.close_brace(false); 232 } 233 } 234 235 impl Item for Struct { path(&self) -> &Path236 fn path(&self) -> &Path { 237 &self.path 238 } 239 export_name(&self) -> &str240 fn export_name(&self) -> &str { 241 &self.export_name 242 } 243 cfg(&self) -> Option<&Cfg>244 fn cfg(&self) -> Option<&Cfg> { 245 self.cfg.as_ref() 246 } 247 annotations(&self) -> &AnnotationSet248 fn annotations(&self) -> &AnnotationSet { 249 &self.annotations 250 } 251 annotations_mut(&mut self) -> &mut AnnotationSet252 fn annotations_mut(&mut self) -> &mut AnnotationSet { 253 &mut self.annotations 254 } 255 container(&self) -> ItemContainer256 fn container(&self) -> ItemContainer { 257 ItemContainer::Struct(self.clone()) 258 } 259 collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver)260 fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) { 261 if !self.is_transparent { 262 resolver.add_struct(&self.path); 263 } 264 } 265 resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver)266 fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) { 267 for &mut (_, ref mut ty, _) in &mut self.fields { 268 ty.resolve_declaration_types(resolver); 269 } 270 } 271 rename_for_config(&mut self, config: &Config)272 fn rename_for_config(&mut self, config: &Config) { 273 // Rename the name of the struct 274 if !self.is_tagged || config.language == Language::C { 275 config.export.rename(&mut self.export_name); 276 } 277 278 // Rename the types used in fields 279 { 280 let fields = self 281 .fields 282 .iter_mut() 283 .skip(if self.is_tagged { 1 } else { 0 }); 284 for &mut (_, ref mut ty, _) in fields { 285 ty.rename_for_config(config, &self.generic_params); 286 } 287 } 288 289 // Apply renaming rules to fields in the following order 290 // 1. `cbindgen::field-names` annotation 291 // 2. `cbindgen::rename-all` annotation 292 // 3. config struct rename rule 293 // If the struct is a tuple struct and we have not renamed the 294 // fields, then prefix each of them with an underscore. 295 // If any field is a reserved keyword, then postfix it with an 296 // underscore. 297 298 // Scope for mutable borrow of fields 299 { 300 let mut names = self.fields.iter_mut().map(|field| &mut field.0); 301 302 let field_rules = [ 303 self.annotations.parse_atom::<RenameRule>("rename-all"), 304 config.structure.rename_fields, 305 ]; 306 307 if let Some(o) = self.annotations.list("field-names") { 308 for (dest, src) in names.zip(o) { 309 *dest = src; 310 } 311 } else if let Some(r) = find_first_some(&field_rules) { 312 for name in names { 313 *name = r.apply(name, IdentifierType::StructMember); 314 } 315 } else if self.tuple_struct { 316 // If there is a tag field, skip it 317 if self.is_tagged { 318 names.next(); 319 } 320 321 // If we don't have any rules for a tuple struct, prefix them with 322 // an underscore so it still compiles 323 for name in names { 324 name.insert(0, '_'); 325 } 326 } 327 } 328 329 for field in &mut self.fields { 330 reserved::escape(&mut field.0); 331 } 332 333 for c in self.associated_constants.iter_mut() { 334 c.rename_for_config(config); 335 } 336 } 337 add_dependencies(&self, library: &Library, out: &mut Dependencies)338 fn add_dependencies(&self, library: &Library, out: &mut Dependencies) { 339 let mut fields = self.fields.iter(); 340 341 // If there is a tag field, skip it 342 if self.is_tagged { 343 fields.next(); 344 } 345 346 for &(_, ref ty, _) in fields { 347 ty.add_dependencies_ignoring_generics(&self.generic_params, library, out); 348 } 349 350 for c in &self.associated_constants { 351 c.add_dependencies(library, out); 352 } 353 } 354 instantiate_monomorph( &self, generic_values: &[Type], library: &Library, out: &mut Monomorphs, )355 fn instantiate_monomorph( 356 &self, 357 generic_values: &[Type], 358 library: &Library, 359 out: &mut Monomorphs, 360 ) { 361 assert!( 362 self.generic_params.len() > 0, 363 "{} is not generic", 364 self.path 365 ); 366 assert!( 367 self.generic_params.len() == generic_values.len(), 368 "{} has {} params but is being instantiated with {} values", 369 self.path, 370 self.generic_params.len(), 371 generic_values.len(), 372 ); 373 374 let mappings = self 375 .generic_params 376 .iter() 377 .zip(generic_values.iter()) 378 .collect::<Vec<_>>(); 379 380 let monomorph = self.specialize(generic_values, &mappings); 381 382 // Instantiate any monomorphs for any generic paths we may have just created. 383 monomorph.add_monomorphs(library, out); 384 385 out.insert_struct(self, monomorph, generic_values.to_owned()); 386 } 387 } 388 389 impl Source for Struct { write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>)390 fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) { 391 if self.is_transparent { 392 let typedef = Typedef { 393 path: self.path.clone(), 394 export_name: self.export_name.to_owned(), 395 generic_params: self.generic_params.clone(), 396 aliased: self.fields[0].1.clone(), 397 cfg: self.cfg.clone(), 398 annotations: self.annotations.clone(), 399 documentation: self.documentation.clone(), 400 }; 401 typedef.write(config, out); 402 for constant in &self.associated_constants { 403 out.new_line(); 404 constant.write(config, out, Some(self)); 405 } 406 return; 407 } 408 409 let condition = self.cfg.to_condition(config); 410 condition.write_before(config, out); 411 412 self.documentation.write(config, out); 413 414 if !self.is_enum_variant_body { 415 self.generic_params.write(config, out); 416 } 417 418 // The following results in 419 // C++ or C with Tag as style: 420 // struct Name { 421 // C with Type only style: 422 // typedef struct { 423 // C with Both as style: 424 // typedef struct Name { 425 if config.language == Language::C && config.style.generate_typedef() { 426 out.write("typedef "); 427 } 428 429 out.write("struct"); 430 431 if let Some(align) = self.alignment { 432 match align { 433 ReprAlign::Packed => { 434 if let Some(ref anno) = config.layout.packed { 435 write!(out, " {}", anno); 436 } 437 } 438 ReprAlign::Align(n) => { 439 if let Some(ref anno) = config.layout.aligned_n { 440 write!(out, " {}({})", anno, n); 441 } 442 } 443 } 444 } 445 446 if self.annotations.must_use { 447 if let Some(ref anno) = config.structure.must_use { 448 write!(out, " {}", anno); 449 } 450 } 451 452 if config.language == Language::Cxx || config.style.generate_tag() { 453 write!(out, " {}", self.export_name()); 454 } 455 456 out.open_brace(); 457 458 // Emit the pre_body section, if relevant 459 if let Some(body) = config.export.pre_body(&self.path) { 460 out.write_raw_block(body); 461 out.new_line(); 462 } 463 464 if config.documentation { 465 out.write_vertical_source_list(&self.fields, ListType::Cap(";")); 466 } else { 467 let vec: Vec<_> = self 468 .fields 469 .iter() 470 .map(|&(ref name, ref ty, _)| (name.clone(), ty.clone())) 471 .collect(); 472 out.write_vertical_source_list(&vec[..], ListType::Cap(";")); 473 } 474 475 if config.language == Language::Cxx { 476 let mut wrote_start_newline = false; 477 478 if config.structure.derive_constructor(&self.annotations) && !self.fields.is_empty() { 479 if !wrote_start_newline { 480 wrote_start_newline = true; 481 out.new_line(); 482 } 483 484 out.new_line(); 485 486 let arg_renamer = |name: &str| { 487 config 488 .function 489 .rename_args 490 .as_ref() 491 .unwrap_or(&RenameRule::GeckoCase) 492 .apply(name, IdentifierType::FunctionArg) 493 }; 494 write!(out, "{}(", self.export_name()); 495 let vec: Vec<_> = self 496 .fields 497 .iter() 498 .map(|&(ref name, ref ty, _)| { 499 // const-ref args to constructor 500 (format!("const& {}", arg_renamer(name)), ty.clone()) 501 }) 502 .collect(); 503 out.write_vertical_source_list(&vec[..], ListType::Join(",")); 504 write!(out, ")"); 505 out.new_line(); 506 write!(out, " : "); 507 let vec: Vec<_> = self 508 .fields 509 .iter() 510 .map(|x| format!("{}({})", x.0, arg_renamer(&x.0))) 511 .collect(); 512 out.write_vertical_source_list(&vec[..], ListType::Join(",")); 513 out.new_line(); 514 write!(out, "{{}}"); 515 out.new_line(); 516 } 517 518 let other = if let Some(r) = config.function.rename_args { 519 r.apply("other", IdentifierType::FunctionArg) 520 } else { 521 String::from("other") 522 }; 523 524 if self 525 .annotations 526 .bool("internal-derive-bitflags") 527 .unwrap_or(false) 528 { 529 if !wrote_start_newline { 530 wrote_start_newline = true; 531 out.new_line(); 532 } 533 out.new_line(); 534 write!(out, "explicit operator bool() const"); 535 out.open_brace(); 536 write!(out, "return !!bits;"); 537 out.close_brace(false); 538 539 out.new_line(); 540 write!(out, "{} operator~() const", self.export_name()); 541 out.open_brace(); 542 write!(out, "return {{static_cast<decltype(bits)>(~bits)}};"); 543 out.close_brace(false); 544 545 self.emit_bitflags_binop('|', &other, out); 546 self.emit_bitflags_binop('&', &other, out); 547 self.emit_bitflags_binop('^', &other, out); 548 } 549 550 let skip_fields = if self.is_tagged { 1 } else { 0 }; 551 552 macro_rules! emit_op { 553 ($op_name:expr, $op:expr, $conjuc:expr) => {{ 554 if !wrote_start_newline { 555 #[allow(unused_assignments)] 556 { 557 wrote_start_newline = true; 558 } 559 out.new_line(); 560 } 561 562 out.new_line(); 563 564 if let Some(Some(attrs)) = 565 self.annotations.atom(concat!($op_name, "-attributes")) 566 { 567 write!(out, "{} ", attrs); 568 } 569 570 write!( 571 out, 572 "bool operator{}(const {}& {}) const", 573 $op, 574 self.export_name(), 575 other 576 ); 577 out.open_brace(); 578 out.write("return "); 579 let vec: Vec<_> = self 580 .fields 581 .iter() 582 .skip(skip_fields) 583 .map(|x| format!("{} {} {}.{}", x.0, $op, other, x.0)) 584 .collect(); 585 out.write_vertical_source_list( 586 &vec[..], 587 ListType::Join(&format!(" {}", $conjuc)), 588 ); 589 out.write(";"); 590 out.close_brace(false); 591 }}; 592 }; 593 594 if config.structure.derive_eq(&self.annotations) && self.can_derive_eq() { 595 emit_op!("eq", "==", "&&"); 596 } 597 if config.structure.derive_neq(&self.annotations) && self.can_derive_eq() { 598 emit_op!("neq", "!=", "||"); 599 } 600 if config.structure.derive_lt(&self.annotations) 601 && self.fields.len() == 1 602 && self.fields[0].1.can_cmp_order() 603 { 604 emit_op!("lt", "<", "&&"); 605 } 606 if config.structure.derive_lte(&self.annotations) 607 && self.fields.len() == 1 608 && self.fields[0].1.can_cmp_order() 609 { 610 emit_op!("lte", "<=", "&&"); 611 } 612 if config.structure.derive_gt(&self.annotations) 613 && self.fields.len() == 1 614 && self.fields[0].1.can_cmp_order() 615 { 616 emit_op!("gt", ">", "&&"); 617 } 618 if config.structure.derive_gte(&self.annotations) 619 && self.fields.len() == 1 620 && self.fields[0].1.can_cmp_order() 621 { 622 emit_op!("gte", ">=", "&&"); 623 } 624 } 625 626 // Emit the post_body section, if relevant 627 if let Some(body) = config.export.post_body(&self.path) { 628 out.new_line(); 629 out.write_raw_block(body); 630 } 631 632 if config.language == Language::Cxx 633 && config.structure.associated_constants_in_body 634 && config.constant.allow_static_const 635 { 636 for constant in &self.associated_constants { 637 out.new_line(); 638 constant.write_declaration(config, out, self); 639 } 640 } 641 642 if config.language == Language::C && config.style.generate_typedef() { 643 out.close_brace(false); 644 write!(out, " {};", self.export_name()); 645 } else { 646 out.close_brace(true); 647 } 648 649 for constant in &self.associated_constants { 650 out.new_line(); 651 constant.write(config, out, Some(self)); 652 } 653 654 condition.write_after(config, out); 655 } 656 } 657 658 pub trait SynFieldHelpers { as_ident_and_type( &self, self_path: &Path, ) -> Result<Option<(String, Type, Documentation)>, String>659 fn as_ident_and_type( 660 &self, 661 self_path: &Path, 662 ) -> Result<Option<(String, Type, Documentation)>, String>; 663 } 664 665 impl SynFieldHelpers for syn::Field { as_ident_and_type( &self, self_path: &Path, ) -> Result<Option<(String, Type, Documentation)>, String>666 fn as_ident_and_type( 667 &self, 668 self_path: &Path, 669 ) -> Result<Option<(String, Type, Documentation)>, String> { 670 let ident = self 671 .ident 672 .as_ref() 673 .ok_or_else(|| "field is missing identifier".to_string())? 674 .clone(); 675 let converted_ty = Type::load(&self.ty)?; 676 677 if let Some(mut x) = converted_ty { 678 x.replace_self_with(self_path); 679 Ok(Some(( 680 ident.to_string(), 681 x, 682 Documentation::load(&self.attrs), 683 ))) 684 } else { 685 Ok(None) 686 } 687 } 688 } 689