1//! Compound types (unions and structs) in our intermediate representation.
2
3use super::analysis::Sizedness;
4use super::annotations::Annotations;
5use super::context::{BindgenContext, FunctionId, ItemId, TypeId, VarId};
6use super::dot::DotAttributes;
7use super::item::{IsOpaque, Item};
8use super::layout::Layout;
9use super::template::TemplateParameters;
10use super::traversal::{EdgeKind, Trace, Tracer};
11use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
12use crate::clang;
13use crate::codegen::struct_layout::{align_to, bytes_from_bits_pow2};
14use crate::ir::derive::CanDeriveCopy;
15use crate::parse::ParseError;
16use crate::HashMap;
17use crate::NonCopyUnionStyle;
18use peeking_take_while::PeekableExt;
19use std::cmp;
20use std::io;
21use std::mem;
22
23/// The kind of compound type.
24#[derive(Debug, Copy, Clone, PartialEq, Eq)]
25pub enum CompKind {
26 /// A struct.
27 Struct,
28 /// A union.
29 Union,
30}
31
32/// The kind of C++ method.
33#[derive(Debug, Copy, Clone, PartialEq, Eq)]
34pub enum MethodKind {
35 /// A constructor. We represent it as method for convenience, to avoid code
36 /// duplication.
37 Constructor,
38 /// A destructor.
39 Destructor,
40 /// A virtual destructor.
41 VirtualDestructor {
42 /// Whether it's pure virtual.
43 pure_virtual: bool,
44 },
45 /// A static method.
46 Static,
47 /// A normal method.
48 Normal,
49 /// A virtual method.
50 Virtual {
51 /// Whether it's pure virtual.
52 pure_virtual: bool,
53 },
54}
55
56impl MethodKind {
57 /// Is this a destructor method?
58 pub fn is_destructor(&self) -> bool {
59 matches!(
60 *self,
61 MethodKind::Destructor | MethodKind::VirtualDestructor { .. }
62 )
63 }
64
65 /// Is this a pure virtual method?
66 pub fn is_pure_virtual(&self) -> bool {
67 match *self {
68 MethodKind::Virtual { pure_virtual: bool } |
69 MethodKind::VirtualDestructor { pure_virtual: bool } => pure_virtual,
70 _ => false,
71 }
72 }
73}
74
75/// A struct representing a C++ method, either static, normal, or virtual.
76#[derive(Debug)]
77pub struct Method {
78 kind: MethodKind,
79 /// The signature of the method. Take into account this is not a `Type`
80 /// item, but a `Function` one.
81 ///
82 /// This is tricky and probably this field should be renamed.
83 signature: FunctionId,
84 is_const: bool,
85}
86
87impl Method {
88 /// Construct a new `Method`.
89 pub fn new(
90 kind: MethodKind,
91 signature: FunctionId,
92 is_const: bool,
93 ) -> Self {
94 Method {
95 kind,
96 signature,
97 is_const,
98 }
99 }
100
101 /// What kind of method is this?
102 pub fn kind(&self) -> MethodKind {
103 self.kind
104 }
105
106 /// Is this a constructor?
107 pub fn is_constructor(&self) -> bool {
108 self.kind == MethodKind::Constructor
109 }
110
111 /// Is this a virtual method?
112 pub fn is_virtual(&self) -> bool {
113 matches!(
114 self.kind,
115 MethodKind::Virtual { .. } | MethodKind::VirtualDestructor { .. }
116 )
117 }
118
119 /// Is this a static method?
120 pub fn is_static(&self) -> bool {
121 self.kind == MethodKind::Static
122 }
123
124 /// Get the id for the `Function` signature for this method.
125 pub fn signature(&self) -> FunctionId {
126 self.signature
127 }
128
129 /// Is this a const qualified method?
130 pub fn is_const(&self) -> bool {
131 self.is_const
132 }
133}
134
135/// Methods common to the various field types.
136pub trait FieldMethods {
137 /// Get the name of this field.
138 fn name(&self) -> Option<&str>;
139
140 /// Get the type of this field.
141 fn ty(&self) -> TypeId;
142
143 /// Get the comment for this field.
144 fn comment(&self) -> Option<&str>;
145
146 /// If this is a bitfield, how many bits does it need?
147 fn bitfield_width(&self) -> Option<u32>;
148
149 /// Is this feild declared public?
150 fn is_public(&self) -> bool;
151
152 /// Get the annotations for this field.
153 fn annotations(&self) -> &Annotations;
154
155 /// The offset of the field (in bits)
156 fn offset(&self) -> Option<usize>;
157}
158
159/// A contiguous set of logical bitfields that live within the same physical
160/// allocation unit. See 9.2.4 [class.bit] in the C++ standard and [section
161/// 2.4.II.1 in the Itanium C++
162/// ABI](http://itanium-cxx-abi.github.io/cxx-abi/abi.html#class-types).
163#[derive(Debug)]
164pub struct BitfieldUnit {
165 nth: usize,
166 layout: Layout,
167 bitfields: Vec<Bitfield>,
168}
169
170impl BitfieldUnit {
171 /// Get the 1-based index of this bitfield unit within its containing
172 /// struct. Useful for generating a Rust struct's field name for this unit
173 /// of bitfields.
174 pub fn nth(&self) -> usize {
175 self.nth
176 }
177
178 /// Get the layout within which these bitfields reside.
179 pub fn layout(&self) -> Layout {
180 self.layout
181 }
182
183 /// Get the bitfields within this unit.
184 pub fn bitfields(&self) -> &[Bitfield] {
185 &self.bitfields
186 }
187}
188
189/// A struct representing a C++ field.
190#[derive(Debug)]
191pub enum Field {
192 /// A normal data member.
193 DataMember(FieldData),
194
195 /// A physical allocation unit containing many logical bitfields.
196 Bitfields(BitfieldUnit),
197}
198
199impl Field {
200 /// Get this field's layout.
201 pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
202 match *self {
203 Field::Bitfields(BitfieldUnit { layout: Layout, .. }) => Some(layout),
204 Field::DataMember(ref data: &FieldData) => {
205 ctx.resolve_type(type_id:data.ty).layout(ctx)
206 }
207 }
208 }
209}
210
211impl Trace for Field {
212 type Extra = ();
213
214 fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
215 where
216 T: Tracer,
217 {
218 match *self {
219 Field::DataMember(ref data: &FieldData) => {
220 tracer.visit_kind(item:data.ty.into(), kind:EdgeKind::Field);
221 }
222 Field::Bitfields(BitfieldUnit { ref bitfields: &Vec, .. }) => {
223 for bf: &Bitfield in bitfields {
224 tracer.visit_kind(item:bf.ty().into(), kind:EdgeKind::Field);
225 }
226 }
227 }
228 }
229}
230
231impl DotAttributes for Field {
232 fn dot_attributes<W>(
233 &self,
234 ctx: &BindgenContext,
235 out: &mut W,
236 ) -> io::Result<()>
237 where
238 W: io::Write,
239 {
240 match *self {
241 Field::DataMember(ref data) => data.dot_attributes(ctx, out),
242 Field::Bitfields(BitfieldUnit {
243 layout,
244 ref bitfields,
245 ..
246 }) => {
247 writeln!(
248 out,
249 r#"<tr>
250 <td>bitfield unit</td>
251 <td>
252 <table border="0">
253 <tr>
254 <td>unit.size</td><td>{}</td>
255 </tr>
256 <tr>
257 <td>unit.align</td><td>{}</td>
258 </tr>
259 "#,
260 layout.size, layout.align
261 )?;
262 for bf in bitfields {
263 bf.dot_attributes(ctx, out)?;
264 }
265 writeln!(out, "</table></td></tr>")
266 }
267 }
268 }
269}
270
271impl DotAttributes for FieldData {
272 fn dot_attributes<W>(
273 &self,
274 _ctx: &BindgenContext,
275 out: &mut W,
276 ) -> io::Result<()>
277 where
278 W: io::Write,
279 {
280 writeln!(
281 out,
282 "<tr><td>{}</td><td>{:?}</td></tr>",
283 self.name().unwrap_or("(anonymous)"),
284 self.ty()
285 )
286 }
287}
288
289impl DotAttributes for Bitfield {
290 fn dot_attributes<W>(
291 &self,
292 _ctx: &BindgenContext,
293 out: &mut W,
294 ) -> io::Result<()>
295 where
296 W: io::Write,
297 {
298 writeln!(
299 out,
300 "<tr><td>{} : {}</td><td>{:?}</td></tr>",
301 self.name().unwrap_or("(anonymous)"),
302 self.width(),
303 self.ty()
304 )
305 }
306}
307
308/// A logical bitfield within some physical bitfield allocation unit.
309#[derive(Debug)]
310pub struct Bitfield {
311 /// Index of the bit within this bitfield's allocation unit where this
312 /// bitfield's bits begin.
313 offset_into_unit: usize,
314
315 /// The field data for this bitfield.
316 data: FieldData,
317
318 /// Name of the generated Rust getter for this bitfield.
319 ///
320 /// Should be assigned before codegen.
321 getter_name: Option<String>,
322
323 /// Name of the generated Rust setter for this bitfield.
324 ///
325 /// Should be assigned before codegen.
326 setter_name: Option<String>,
327}
328
329impl Bitfield {
330 /// Construct a new bitfield.
331 fn new(offset_into_unit: usize, raw: RawField) -> Bitfield {
332 assert!(raw.bitfield_width().is_some());
333
334 Bitfield {
335 offset_into_unit,
336 data: raw.0,
337 getter_name: None,
338 setter_name: None,
339 }
340 }
341
342 /// Get the index of the bit within this bitfield's allocation unit where
343 /// this bitfield begins.
344 pub fn offset_into_unit(&self) -> usize {
345 self.offset_into_unit
346 }
347
348 /// Get the mask value that when &'ed with this bitfield's allocation unit
349 /// produces this bitfield's value.
350 pub fn mask(&self) -> u64 {
351 use std::u64;
352
353 let unoffseted_mask =
354 if self.width() as u64 == mem::size_of::<u64>() as u64 * 8 {
355 u64::MAX
356 } else {
357 (1u64 << self.width()) - 1u64
358 };
359
360 unoffseted_mask << self.offset_into_unit()
361 }
362
363 /// Get the bit width of this bitfield.
364 pub fn width(&self) -> u32 {
365 self.data.bitfield_width().unwrap()
366 }
367
368 /// Name of the generated Rust getter for this bitfield.
369 ///
370 /// Panics if called before assigning bitfield accessor names or if
371 /// this bitfield have no name.
372 pub fn getter_name(&self) -> &str {
373 assert!(
374 self.name().is_some(),
375 "`Bitfield::getter_name` called on anonymous field"
376 );
377 self.getter_name.as_ref().expect(
378 "`Bitfield::getter_name` should only be called after\
379 assigning bitfield accessor names",
380 )
381 }
382
383 /// Name of the generated Rust setter for this bitfield.
384 ///
385 /// Panics if called before assigning bitfield accessor names or if
386 /// this bitfield have no name.
387 pub fn setter_name(&self) -> &str {
388 assert!(
389 self.name().is_some(),
390 "`Bitfield::setter_name` called on anonymous field"
391 );
392 self.setter_name.as_ref().expect(
393 "`Bitfield::setter_name` should only be called\
394 after assigning bitfield accessor names",
395 )
396 }
397}
398
399impl FieldMethods for Bitfield {
400 fn name(&self) -> Option<&str> {
401 self.data.name()
402 }
403
404 fn ty(&self) -> TypeId {
405 self.data.ty()
406 }
407
408 fn comment(&self) -> Option<&str> {
409 self.data.comment()
410 }
411
412 fn bitfield_width(&self) -> Option<u32> {
413 self.data.bitfield_width()
414 }
415
416 fn is_public(&self) -> bool {
417 self.data.is_public()
418 }
419
420 fn annotations(&self) -> &Annotations {
421 self.data.annotations()
422 }
423
424 fn offset(&self) -> Option<usize> {
425 self.data.offset()
426 }
427}
428
429/// A raw field might be either of a plain data member or a bitfield within a
430/// bitfield allocation unit, but we haven't processed it and determined which
431/// yet (which would involve allocating it into a bitfield unit if it is a
432/// bitfield).
433#[derive(Debug)]
434struct RawField(FieldData);
435
436impl RawField {
437 /// Construct a new `RawField`.
438 fn new(
439 name: Option<String>,
440 ty: TypeId,
441 comment: Option<String>,
442 annotations: Option<Annotations>,
443 bitfield_width: Option<u32>,
444 public: bool,
445 offset: Option<usize>,
446 ) -> RawField {
447 RawField(FieldData {
448 name,
449 ty,
450 comment,
451 annotations: annotations.unwrap_or_default(),
452 bitfield_width,
453 public,
454 offset,
455 })
456 }
457}
458
459impl FieldMethods for RawField {
460 fn name(&self) -> Option<&str> {
461 self.0.name()
462 }
463
464 fn ty(&self) -> TypeId {
465 self.0.ty()
466 }
467
468 fn comment(&self) -> Option<&str> {
469 self.0.comment()
470 }
471
472 fn bitfield_width(&self) -> Option<u32> {
473 self.0.bitfield_width()
474 }
475
476 fn is_public(&self) -> bool {
477 self.0.is_public()
478 }
479
480 fn annotations(&self) -> &Annotations {
481 self.0.annotations()
482 }
483
484 fn offset(&self) -> Option<usize> {
485 self.0.offset()
486 }
487}
488
489/// Convert the given ordered set of raw fields into a list of either plain data
490/// members, and/or bitfield units containing multiple bitfields.
491///
492/// If we do not have the layout for a bitfield's type, then we can't reliably
493/// compute its allocation unit. In such cases, we return an error.
494fn raw_fields_to_fields_and_bitfield_units<I>(
495 ctx: &BindgenContext,
496 raw_fields: I,
497 packed: bool,
498) -> Result<(Vec<Field>, bool), ()>
499where
500 I: IntoIterator<Item = RawField>,
501{
502 let mut raw_fields = raw_fields.into_iter().fuse().peekable();
503 let mut fields = vec![];
504 let mut bitfield_unit_count = 0;
505
506 loop {
507 // While we have plain old data members, just keep adding them to our
508 // resulting fields. We introduce a scope here so that we can use
509 // `raw_fields` again after the `by_ref` iterator adaptor is dropped.
510 {
511 let non_bitfields = raw_fields
512 .by_ref()
513 .peeking_take_while(|f| f.bitfield_width().is_none())
514 .map(|f| Field::DataMember(f.0));
515 fields.extend(non_bitfields);
516 }
517
518 // Now gather all the consecutive bitfields. Only consecutive bitfields
519 // may potentially share a bitfield allocation unit with each other in
520 // the Itanium C++ ABI.
521 let mut bitfields = raw_fields
522 .by_ref()
523 .peeking_take_while(|f| f.bitfield_width().is_some())
524 .peekable();
525
526 if bitfields.peek().is_none() {
527 break;
528 }
529
530 bitfields_to_allocation_units(
531 ctx,
532 &mut bitfield_unit_count,
533 &mut fields,
534 bitfields,
535 packed,
536 )?;
537 }
538
539 assert!(
540 raw_fields.next().is_none(),
541 "The above loop should consume all items in `raw_fields`"
542 );
543
544 Ok((fields, bitfield_unit_count != 0))
545}
546
547/// Given a set of contiguous raw bitfields, group and allocate them into
548/// (potentially multiple) bitfield units.
549fn bitfields_to_allocation_units<E, I>(
550 ctx: &BindgenContext,
551 bitfield_unit_count: &mut usize,
552 fields: &mut E,
553 raw_bitfields: I,
554 packed: bool,
555) -> Result<(), ()>
556where
557 E: Extend<Field>,
558 I: IntoIterator<Item = RawField>,
559{
560 assert!(ctx.collected_typerefs());
561
562 // NOTE: What follows is reverse-engineered from LLVM's
563 // lib/AST/RecordLayoutBuilder.cpp
564 //
565 // FIXME(emilio): There are some differences between Microsoft and the
566 // Itanium ABI, but we'll ignore those and stick to Itanium for now.
567 //
568 // Also, we need to handle packed bitfields and stuff.
569 //
570 // TODO(emilio): Take into account C++'s wide bitfields, and
571 // packing, sigh.
572
573 fn flush_allocation_unit<E>(
574 fields: &mut E,
575 bitfield_unit_count: &mut usize,
576 unit_size_in_bits: usize,
577 unit_align_in_bits: usize,
578 bitfields: Vec<Bitfield>,
579 packed: bool,
580 ) where
581 E: Extend<Field>,
582 {
583 *bitfield_unit_count += 1;
584 let align = if packed {
585 1
586 } else {
587 bytes_from_bits_pow2(unit_align_in_bits)
588 };
589 let size = align_to(unit_size_in_bits, 8) / 8;
590 let layout = Layout::new(size, align);
591 fields.extend(Some(Field::Bitfields(BitfieldUnit {
592 nth: *bitfield_unit_count,
593 layout,
594 bitfields,
595 })));
596 }
597
598 let mut max_align = 0;
599 let mut unfilled_bits_in_unit = 0;
600 let mut unit_size_in_bits = 0;
601 let mut unit_align = 0;
602 let mut bitfields_in_unit = vec![];
603
604 // TODO(emilio): Determine this from attributes or pragma ms_struct
605 // directives. Also, perhaps we should check if the target is MSVC?
606 const is_ms_struct: bool = false;
607
608 for bitfield in raw_bitfields {
609 let bitfield_width = bitfield.bitfield_width().unwrap() as usize;
610 let bitfield_layout =
611 ctx.resolve_type(bitfield.ty()).layout(ctx).ok_or(())?;
612 let bitfield_size = bitfield_layout.size;
613 let bitfield_align = bitfield_layout.align;
614
615 let mut offset = unit_size_in_bits;
616 if !packed {
617 if is_ms_struct {
618 if unit_size_in_bits != 0 &&
619 (bitfield_width == 0 ||
620 bitfield_width > unfilled_bits_in_unit)
621 {
622 // We've reached the end of this allocation unit, so flush it
623 // and its bitfields.
624 unit_size_in_bits =
625 align_to(unit_size_in_bits, unit_align * 8);
626 flush_allocation_unit(
627 fields,
628 bitfield_unit_count,
629 unit_size_in_bits,
630 unit_align,
631 mem::take(&mut bitfields_in_unit),
632 packed,
633 );
634
635 // Now we're working on a fresh bitfield allocation unit, so reset
636 // the current unit size and alignment.
637 offset = 0;
638 unit_align = 0;
639 }
640 } else if offset != 0 &&
641 (bitfield_width == 0 ||
642 (offset & (bitfield_align * 8 - 1)) + bitfield_width >
643 bitfield_size * 8)
644 {
645 offset = align_to(offset, bitfield_align * 8);
646 }
647 }
648
649 // According to the x86[-64] ABI spec: "Unnamed bit-fields’ types do not
650 // affect the alignment of a structure or union". This makes sense: such
651 // bit-fields are only used for padding, and we can't perform an
652 // un-aligned read of something we can't read because we can't even name
653 // it.
654 if bitfield.name().is_some() {
655 max_align = cmp::max(max_align, bitfield_align);
656
657 // NB: The `bitfield_width` here is completely, absolutely
658 // intentional. Alignment of the allocation unit is based on the
659 // maximum bitfield width, not (directly) on the bitfields' types'
660 // alignment.
661 unit_align = cmp::max(unit_align, bitfield_width);
662 }
663
664 // Always keep all bitfields around. While unnamed bitifields are used
665 // for padding (and usually not needed hereafter), large unnamed
666 // bitfields over their types size cause weird allocation size behavior from clang.
667 // Therefore, all bitfields needed to be kept around in order to check for this
668 // and make the struct opaque in this case
669 bitfields_in_unit.push(Bitfield::new(offset, bitfield));
670
671 unit_size_in_bits = offset + bitfield_width;
672
673 // Compute what the physical unit's final size would be given what we
674 // have seen so far, and use that to compute how many bits are still
675 // available in the unit.
676 let data_size = align_to(unit_size_in_bits, bitfield_align * 8);
677 unfilled_bits_in_unit = data_size - unit_size_in_bits;
678 }
679
680 if unit_size_in_bits != 0 {
681 // Flush the last allocation unit and its bitfields.
682 flush_allocation_unit(
683 fields,
684 bitfield_unit_count,
685 unit_size_in_bits,
686 unit_align,
687 bitfields_in_unit,
688 packed,
689 );
690 }
691
692 Ok(())
693}
694
695/// A compound structure's fields are initially raw, and have bitfields that
696/// have not been grouped into allocation units. During this time, the fields
697/// are mutable and we build them up during parsing.
698///
699/// Then, once resolving typerefs is completed, we compute all structs' fields'
700/// bitfield allocation units, and they remain frozen and immutable forever
701/// after.
702#[derive(Debug)]
703enum CompFields {
704 Before(Vec<RawField>),
705 After {
706 fields: Vec<Field>,
707 has_bitfield_units: bool,
708 },
709 Error,
710}
711
712impl Default for CompFields {
713 fn default() -> CompFields {
714 CompFields::Before(vec![])
715 }
716}
717
718impl CompFields {
719 fn append_raw_field(&mut self, raw: RawField) {
720 match *self {
721 CompFields::Before(ref mut raws) => {
722 raws.push(raw);
723 }
724 _ => {
725 panic!(
726 "Must not append new fields after computing bitfield allocation units"
727 );
728 }
729 }
730 }
731
732 fn compute_bitfield_units(&mut self, ctx: &BindgenContext, packed: bool) {
733 let raws = match *self {
734 CompFields::Before(ref mut raws) => mem::take(raws),
735 _ => {
736 panic!("Already computed bitfield units");
737 }
738 };
739
740 let result = raw_fields_to_fields_and_bitfield_units(ctx, raws, packed);
741
742 match result {
743 Ok((fields, has_bitfield_units)) => {
744 *self = CompFields::After {
745 fields,
746 has_bitfield_units,
747 };
748 }
749 Err(()) => {
750 *self = CompFields::Error;
751 }
752 }
753 }
754
755 fn deanonymize_fields(&mut self, ctx: &BindgenContext, methods: &[Method]) {
756 let fields = match *self {
757 CompFields::After { ref mut fields, .. } => fields,
758 // Nothing to do here.
759 CompFields::Error => return,
760 CompFields::Before(_) => {
761 panic!("Not yet computed bitfield units.");
762 }
763 };
764
765 fn has_method(
766 methods: &[Method],
767 ctx: &BindgenContext,
768 name: &str,
769 ) -> bool {
770 methods.iter().any(|method| {
771 let method_name = ctx.resolve_func(method.signature()).name();
772 method_name == name || ctx.rust_mangle(method_name) == name
773 })
774 }
775
776 struct AccessorNamesPair {
777 getter: String,
778 setter: String,
779 }
780
781 let mut accessor_names: HashMap<String, AccessorNamesPair> = fields
782 .iter()
783 .flat_map(|field| match *field {
784 Field::Bitfields(ref bu) => &*bu.bitfields,
785 Field::DataMember(_) => &[],
786 })
787 .filter_map(|bitfield| bitfield.name())
788 .map(|bitfield_name| {
789 let bitfield_name = bitfield_name.to_string();
790 let getter = {
791 let mut getter =
792 ctx.rust_mangle(&bitfield_name).to_string();
793 if has_method(methods, ctx, &getter) {
794 getter.push_str("_bindgen_bitfield");
795 }
796 getter
797 };
798 let setter = {
799 let setter = format!("set_{}", bitfield_name);
800 let mut setter = ctx.rust_mangle(&setter).to_string();
801 if has_method(methods, ctx, &setter) {
802 setter.push_str("_bindgen_bitfield");
803 }
804 setter
805 };
806 (bitfield_name, AccessorNamesPair { getter, setter })
807 })
808 .collect();
809
810 let mut anon_field_counter = 0;
811 for field in fields.iter_mut() {
812 match *field {
813 Field::DataMember(FieldData { ref mut name, .. }) => {
814 if name.is_some() {
815 continue;
816 }
817
818 anon_field_counter += 1;
819 *name = Some(format!(
820 "{}{}",
821 ctx.options().anon_fields_prefix,
822 anon_field_counter
823 ));
824 }
825 Field::Bitfields(ref mut bu) => {
826 for bitfield in &mut bu.bitfields {
827 if bitfield.name().is_none() {
828 continue;
829 }
830
831 if let Some(AccessorNamesPair { getter, setter }) =
832 accessor_names.remove(bitfield.name().unwrap())
833 {
834 bitfield.getter_name = Some(getter);
835 bitfield.setter_name = Some(setter);
836 }
837 }
838 }
839 }
840 }
841 }
842}
843
844impl Trace for CompFields {
845 type Extra = ();
846
847 fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, _: &())
848 where
849 T: Tracer,
850 {
851 match *self {
852 CompFields::Error => {}
853 CompFields::Before(ref fields: &Vec) => {
854 for f: &RawField in fields {
855 tracer.visit_kind(item:f.ty().into(), kind:EdgeKind::Field);
856 }
857 }
858 CompFields::After { ref fields: &Vec, .. } => {
859 for f: &Field in fields {
860 f.trace(context, tracer, &());
861 }
862 }
863 }
864 }
865}
866
867/// Common data shared across different field types.
868#[derive(Clone, Debug)]
869pub struct FieldData {
870 /// The name of the field, empty if it's an unnamed bitfield width.
871 name: Option<String>,
872
873 /// The inner type.
874 ty: TypeId,
875
876 /// The doc comment on the field if any.
877 comment: Option<String>,
878
879 /// Annotations for this field, or the default.
880 annotations: Annotations,
881
882 /// If this field is a bitfield, and how many bits does it contain if it is.
883 bitfield_width: Option<u32>,
884
885 /// If the C++ field is declared `public`
886 public: bool,
887
888 /// The offset of the field (in bits)
889 offset: Option<usize>,
890}
891
892impl FieldMethods for FieldData {
893 fn name(&self) -> Option<&str> {
894 self.name.as_deref()
895 }
896
897 fn ty(&self) -> TypeId {
898 self.ty
899 }
900
901 fn comment(&self) -> Option<&str> {
902 self.comment.as_deref()
903 }
904
905 fn bitfield_width(&self) -> Option<u32> {
906 self.bitfield_width
907 }
908
909 fn is_public(&self) -> bool {
910 self.public
911 }
912
913 fn annotations(&self) -> &Annotations {
914 &self.annotations
915 }
916
917 fn offset(&self) -> Option<usize> {
918 self.offset
919 }
920}
921
922/// The kind of inheritance a base class is using.
923#[derive(Clone, Debug, PartialEq, Eq)]
924pub enum BaseKind {
925 /// Normal inheritance, like:
926 ///
927 /// ```cpp
928 /// class A : public B {};
929 /// ```
930 Normal,
931 /// Virtual inheritance, like:
932 ///
933 /// ```cpp
934 /// class A: public virtual B {};
935 /// ```
936 Virtual,
937}
938
939/// A base class.
940#[derive(Clone, Debug)]
941pub struct Base {
942 /// The type of this base class.
943 pub ty: TypeId,
944 /// The kind of inheritance we're doing.
945 pub kind: BaseKind,
946 /// Name of the field in which this base should be stored.
947 pub field_name: String,
948 /// Whether this base is inherited from publically.
949 pub is_pub: bool,
950}
951
952impl Base {
953 /// Whether this base class is inheriting virtually.
954 pub fn is_virtual(&self) -> bool {
955 self.kind == BaseKind::Virtual
956 }
957
958 /// Whether this base class should have it's own field for storage.
959 pub fn requires_storage(&self, ctx: &BindgenContext) -> bool {
960 // Virtual bases are already taken into account by the vtable
961 // pointer.
962 //
963 // FIXME(emilio): Is this always right?
964 if self.is_virtual() {
965 return false;
966 }
967
968 // NB: We won't include zero-sized types in our base chain because they
969 // would contribute to our size given the dummy field we insert for
970 // zero-sized types.
971 if self.ty.is_zero_sized(ctx) {
972 return false;
973 }
974
975 true
976 }
977
978 /// Whether this base is inherited from publically.
979 pub fn is_public(&self) -> bool {
980 self.is_pub
981 }
982}
983
984/// A compound type.
985///
986/// Either a struct or union, a compound type is built up from the combination
987/// of fields which also are associated with their own (potentially compound)
988/// type.
989#[derive(Debug)]
990pub struct CompInfo {
991 /// Whether this is a struct or a union.
992 kind: CompKind,
993
994 /// The members of this struct or union.
995 fields: CompFields,
996
997 /// The abstract template parameters of this class. Note that these are NOT
998 /// concrete template arguments, and should always be a
999 /// `Type(TypeKind::TypeParam(name))`. For concrete template arguments, see
1000 /// `TypeKind::TemplateInstantiation`.
1001 template_params: Vec<TypeId>,
1002
1003 /// The method declarations inside this class, if in C++ mode.
1004 methods: Vec<Method>,
1005
1006 /// The different constructors this struct or class contains.
1007 constructors: Vec<FunctionId>,
1008
1009 /// The destructor of this type. The bool represents whether this destructor
1010 /// is virtual.
1011 destructor: Option<(MethodKind, FunctionId)>,
1012
1013 /// Vector of classes this one inherits from.
1014 base_members: Vec<Base>,
1015
1016 /// The inner types that were declared inside this class, in something like:
1017 ///
1018 /// class Foo {
1019 /// typedef int FooTy;
1020 /// struct Bar {
1021 /// int baz;
1022 /// };
1023 /// }
1024 ///
1025 /// static Foo::Bar const = {3};
1026 inner_types: Vec<TypeId>,
1027
1028 /// Set of static constants declared inside this class.
1029 inner_vars: Vec<VarId>,
1030
1031 /// Whether this type should generate an vtable (TODO: Should be able to
1032 /// look at the virtual methods and ditch this field).
1033 has_own_virtual_method: bool,
1034
1035 /// Whether this type has destructor.
1036 has_destructor: bool,
1037
1038 /// Whether this type has a base type with more than one member.
1039 ///
1040 /// TODO: We should be able to compute this.
1041 has_nonempty_base: bool,
1042
1043 /// If this type has a template parameter which is not a type (e.g.: a
1044 /// size_t)
1045 has_non_type_template_params: bool,
1046
1047 /// Whether this type has a bit field member whose width couldn't be
1048 /// evaluated (e.g. if it depends on a template parameter). We generate an
1049 /// opaque type in this case.
1050 has_unevaluable_bit_field_width: bool,
1051
1052 /// Whether we saw `__attribute__((packed))` on or within this type.
1053 packed_attr: bool,
1054
1055 /// Used to know if we've found an opaque attribute that could cause us to
1056 /// generate a type with invalid layout. This is explicitly used to avoid us
1057 /// generating bad alignments when parsing types like max_align_t.
1058 ///
1059 /// It's not clear what the behavior should be here, if generating the item
1060 /// and pray, or behave as an opaque type.
1061 found_unknown_attr: bool,
1062
1063 /// Used to indicate when a struct has been forward declared. Usually used
1064 /// in headers so that APIs can't modify them directly.
1065 is_forward_declaration: bool,
1066}
1067
1068impl CompInfo {
1069 /// Construct a new compound type.
1070 pub fn new(kind: CompKind) -> Self {
1071 CompInfo {
1072 kind,
1073 fields: CompFields::default(),
1074 template_params: vec![],
1075 methods: vec![],
1076 constructors: vec![],
1077 destructor: None,
1078 base_members: vec![],
1079 inner_types: vec![],
1080 inner_vars: vec![],
1081 has_own_virtual_method: false,
1082 has_destructor: false,
1083 has_nonempty_base: false,
1084 has_non_type_template_params: false,
1085 has_unevaluable_bit_field_width: false,
1086 packed_attr: false,
1087 found_unknown_attr: false,
1088 is_forward_declaration: false,
1089 }
1090 }
1091
1092 /// Compute the layout of this type.
1093 ///
1094 /// This is called as a fallback under some circumstances where LLVM doesn't
1095 /// give us the correct layout.
1096 ///
1097 /// If we're a union without known layout, we try to compute it from our
1098 /// members. This is not ideal, but clang fails to report the size for these
1099 /// kind of unions, see test/headers/template_union.hpp
1100 pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
1101 // We can't do better than clang here, sorry.
1102 if self.kind == CompKind::Struct {
1103 return None;
1104 }
1105
1106 // By definition, we don't have the right layout information here if
1107 // we're a forward declaration.
1108 if self.is_forward_declaration() {
1109 return None;
1110 }
1111
1112 // empty union case
1113 if !self.has_fields() {
1114 return None;
1115 }
1116
1117 let mut max_size = 0;
1118 // Don't allow align(0)
1119 let mut max_align = 1;
1120 self.each_known_field_layout(ctx, |layout| {
1121 max_size = cmp::max(max_size, layout.size);
1122 max_align = cmp::max(max_align, layout.align);
1123 });
1124
1125 Some(Layout::new(max_size, max_align))
1126 }
1127
1128 /// Get this type's set of fields.
1129 pub fn fields(&self) -> &[Field] {
1130 match self.fields {
1131 CompFields::Error => &[],
1132 CompFields::After { ref fields, .. } => fields,
1133 CompFields::Before(..) => {
1134 panic!("Should always have computed bitfield units first");
1135 }
1136 }
1137 }
1138
1139 fn has_fields(&self) -> bool {
1140 match self.fields {
1141 CompFields::Error => false,
1142 CompFields::After { ref fields, .. } => !fields.is_empty(),
1143 CompFields::Before(ref raw_fields) => !raw_fields.is_empty(),
1144 }
1145 }
1146
1147 fn each_known_field_layout(
1148 &self,
1149 ctx: &BindgenContext,
1150 mut callback: impl FnMut(Layout),
1151 ) {
1152 match self.fields {
1153 CompFields::Error => {}
1154 CompFields::After { ref fields, .. } => {
1155 for field in fields.iter() {
1156 if let Some(layout) = field.layout(ctx) {
1157 callback(layout);
1158 }
1159 }
1160 }
1161 CompFields::Before(ref raw_fields) => {
1162 for field in raw_fields.iter() {
1163 let field_ty = ctx.resolve_type(field.0.ty);
1164 if let Some(layout) = field_ty.layout(ctx) {
1165 callback(layout);
1166 }
1167 }
1168 }
1169 }
1170 }
1171
1172 fn has_bitfields(&self) -> bool {
1173 match self.fields {
1174 CompFields::Error => false,
1175 CompFields::After {
1176 has_bitfield_units, ..
1177 } => has_bitfield_units,
1178 CompFields::Before(_) => {
1179 panic!("Should always have computed bitfield units first");
1180 }
1181 }
1182 }
1183
1184 /// Returns whether we have a too large bitfield unit, in which case we may
1185 /// not be able to derive some of the things we should be able to normally
1186 /// derive.
1187 pub fn has_too_large_bitfield_unit(&self) -> bool {
1188 if !self.has_bitfields() {
1189 return false;
1190 }
1191 self.fields().iter().any(|field| match *field {
1192 Field::DataMember(..) => false,
1193 Field::Bitfields(ref unit) => {
1194 unit.layout.size > RUST_DERIVE_IN_ARRAY_LIMIT
1195 }
1196 })
1197 }
1198
1199 /// Does this type have any template parameters that aren't types
1200 /// (e.g. int)?
1201 pub fn has_non_type_template_params(&self) -> bool {
1202 self.has_non_type_template_params
1203 }
1204
1205 /// Do we see a virtual function during parsing?
1206 /// Get the has_own_virtual_method boolean.
1207 pub fn has_own_virtual_method(&self) -> bool {
1208 self.has_own_virtual_method
1209 }
1210
1211 /// Did we see a destructor when parsing this type?
1212 pub fn has_own_destructor(&self) -> bool {
1213 self.has_destructor
1214 }
1215
1216 /// Get this type's set of methods.
1217 pub fn methods(&self) -> &[Method] {
1218 &self.methods
1219 }
1220
1221 /// Get this type's set of constructors.
1222 pub fn constructors(&self) -> &[FunctionId] {
1223 &self.constructors
1224 }
1225
1226 /// Get this type's destructor.
1227 pub fn destructor(&self) -> Option<(MethodKind, FunctionId)> {
1228 self.destructor
1229 }
1230
1231 /// What kind of compound type is this?
1232 pub fn kind(&self) -> CompKind {
1233 self.kind
1234 }
1235
1236 /// Is this a union?
1237 pub fn is_union(&self) -> bool {
1238 self.kind() == CompKind::Union
1239 }
1240
1241 /// The set of types that this one inherits from.
1242 pub fn base_members(&self) -> &[Base] {
1243 &self.base_members
1244 }
1245
1246 /// Construct a new compound type from a Clang type.
1247 pub fn from_ty(
1248 potential_id: ItemId,
1249 ty: &clang::Type,
1250 location: Option<clang::Cursor>,
1251 ctx: &mut BindgenContext,
1252 ) -> Result<Self, ParseError> {
1253 use clang_sys::*;
1254 assert!(
1255 ty.template_args().is_none(),
1256 "We handle template instantiations elsewhere"
1257 );
1258
1259 let mut cursor = ty.declaration();
1260 let mut kind = Self::kind_from_cursor(&cursor);
1261 if kind.is_err() {
1262 if let Some(location) = location {
1263 kind = Self::kind_from_cursor(&location);
1264 cursor = location;
1265 }
1266 }
1267
1268 let kind = kind?;
1269
1270 debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor);
1271
1272 let mut ci = CompInfo::new(kind);
1273 ci.is_forward_declaration =
1274 location.map_or(true, |cur| match cur.kind() {
1275 CXCursor_ParmDecl => true,
1276 CXCursor_StructDecl | CXCursor_UnionDecl |
1277 CXCursor_ClassDecl => !cur.is_definition(),
1278 _ => false,
1279 });
1280
1281 let mut maybe_anonymous_struct_field = None;
1282 cursor.visit(|cur| {
1283 if cur.kind() != CXCursor_FieldDecl {
1284 if let Some((ty, clang_ty, public, offset)) =
1285 maybe_anonymous_struct_field.take()
1286 {
1287 if cur.kind() == CXCursor_TypedefDecl &&
1288 cur.typedef_type().unwrap().canonical_type() ==
1289 clang_ty
1290 {
1291 // Typedefs of anonymous structs appear later in the ast
1292 // than the struct itself, that would otherwise be an
1293 // anonymous field. Detect that case here, and do
1294 // nothing.
1295 } else {
1296 let field = RawField::new(
1297 None, ty, None, None, None, public, offset,
1298 );
1299 ci.fields.append_raw_field(field);
1300 }
1301 }
1302 }
1303
1304 match cur.kind() {
1305 CXCursor_FieldDecl => {
1306 if let Some((ty, clang_ty, public, offset)) =
1307 maybe_anonymous_struct_field.take()
1308 {
1309 let mut used = false;
1310 cur.visit(|child| {
1311 if child.cur_type() == clang_ty {
1312 used = true;
1313 }
1314 CXChildVisit_Continue
1315 });
1316
1317 if !used {
1318 let field = RawField::new(
1319 None, ty, None, None, None, public, offset,
1320 );
1321 ci.fields.append_raw_field(field);
1322 }
1323 }
1324
1325 let bit_width = if cur.is_bit_field() {
1326 let width = cur.bit_width();
1327
1328 // Make opaque type if the bit width couldn't be
1329 // evaluated.
1330 if width.is_none() {
1331 ci.has_unevaluable_bit_field_width = true;
1332 return CXChildVisit_Break;
1333 }
1334
1335 width
1336 } else {
1337 None
1338 };
1339
1340 let field_type = Item::from_ty_or_ref(
1341 cur.cur_type(),
1342 cur,
1343 Some(potential_id),
1344 ctx,
1345 );
1346
1347 let comment = cur.raw_comment();
1348 let annotations = Annotations::new(&cur);
1349 let name = cur.spelling();
1350 let is_public = cur.public_accessible();
1351 let offset = cur.offset_of_field().ok();
1352
1353 // Name can be empty if there are bitfields, for example,
1354 // see tests/headers/struct_with_bitfields.h
1355 assert!(
1356 !name.is_empty() || bit_width.is_some(),
1357 "Empty field name?"
1358 );
1359
1360 let name = if name.is_empty() { None } else { Some(name) };
1361
1362 let field = RawField::new(
1363 name,
1364 field_type,
1365 comment,
1366 annotations,
1367 bit_width,
1368 is_public,
1369 offset,
1370 );
1371 ci.fields.append_raw_field(field);
1372
1373 // No we look for things like attributes and stuff.
1374 cur.visit(|cur| {
1375 if cur.kind() == CXCursor_UnexposedAttr {
1376 ci.found_unknown_attr = true;
1377 }
1378 CXChildVisit_Continue
1379 });
1380 }
1381 CXCursor_UnexposedAttr => {
1382 ci.found_unknown_attr = true;
1383 }
1384 CXCursor_EnumDecl |
1385 CXCursor_TypeAliasDecl |
1386 CXCursor_TypeAliasTemplateDecl |
1387 CXCursor_TypedefDecl |
1388 CXCursor_StructDecl |
1389 CXCursor_UnionDecl |
1390 CXCursor_ClassTemplate |
1391 CXCursor_ClassDecl => {
1392 // We can find non-semantic children here, clang uses a
1393 // StructDecl to note incomplete structs that haven't been
1394 // forward-declared before, see [1].
1395 //
1396 // Also, clang seems to scope struct definitions inside
1397 // unions, and other named struct definitions inside other
1398 // structs to the whole translation unit.
1399 //
1400 // Let's just assume that if the cursor we've found is a
1401 // definition, it's a valid inner type.
1402 //
1403 // [1]: https://github.com/rust-lang/rust-bindgen/issues/482
1404 let is_inner_struct =
1405 cur.semantic_parent() == cursor || cur.is_definition();
1406 if !is_inner_struct {
1407 return CXChildVisit_Continue;
1408 }
1409
1410 // Even if this is a definition, we may not be the semantic
1411 // parent, see #1281.
1412 let inner = Item::parse(cur, Some(potential_id), ctx)
1413 .expect("Inner ClassDecl");
1414
1415 // If we avoided recursion parsing this type (in
1416 // `Item::from_ty_with_id()`), then this might not be a
1417 // valid type ID, so check and gracefully handle this.
1418 if ctx.resolve_item_fallible(inner).is_some() {
1419 let inner = inner.expect_type_id(ctx);
1420
1421 ci.inner_types.push(inner);
1422
1423 // A declaration of an union or a struct without name
1424 // could also be an unnamed field, unfortunately.
1425 if cur.is_anonymous() && cur.kind() != CXCursor_EnumDecl
1426 {
1427 let ty = cur.cur_type();
1428 let public = cur.public_accessible();
1429 let offset = cur.offset_of_field().ok();
1430
1431 maybe_anonymous_struct_field =
1432 Some((inner, ty, public, offset));
1433 }
1434 }
1435 }
1436 CXCursor_PackedAttr => {
1437 ci.packed_attr = true;
1438 }
1439 CXCursor_TemplateTypeParameter => {
1440 let param = Item::type_param(None, cur, ctx).expect(
1441 "Item::type_param should't fail when pointing \
1442 at a TemplateTypeParameter",
1443 );
1444 ci.template_params.push(param);
1445 }
1446 CXCursor_CXXBaseSpecifier => {
1447 let is_virtual_base = cur.is_virtual_base();
1448 ci.has_own_virtual_method |= is_virtual_base;
1449
1450 let kind = if is_virtual_base {
1451 BaseKind::Virtual
1452 } else {
1453 BaseKind::Normal
1454 };
1455
1456 let field_name = match ci.base_members.len() {
1457 0 => "_base".into(),
1458 n => format!("_base_{}", n),
1459 };
1460 let type_id =
1461 Item::from_ty_or_ref(cur.cur_type(), cur, None, ctx);
1462 ci.base_members.push(Base {
1463 ty: type_id,
1464 kind,
1465 field_name,
1466 is_pub: cur.access_specifier() ==
1467 clang_sys::CX_CXXPublic,
1468 });
1469 }
1470 CXCursor_Constructor | CXCursor_Destructor |
1471 CXCursor_CXXMethod => {
1472 let is_virtual = cur.method_is_virtual();
1473 let is_static = cur.method_is_static();
1474 debug_assert!(!(is_static && is_virtual), "How?");
1475
1476 ci.has_destructor |= cur.kind() == CXCursor_Destructor;
1477 ci.has_own_virtual_method |= is_virtual;
1478
1479 // This used to not be here, but then I tried generating
1480 // stylo bindings with this (without path filters), and
1481 // cried a lot with a method in gfx/Point.h
1482 // (ToUnknownPoint), that somehow was causing the same type
1483 // to be inserted in the map two times.
1484 //
1485 // I couldn't make a reduced test case, but anyway...
1486 // Methods of template functions not only used to be inlined,
1487 // but also instantiated, and we wouldn't be able to call
1488 // them, so just bail out.
1489 if !ci.template_params.is_empty() {
1490 return CXChildVisit_Continue;
1491 }
1492
1493 // NB: This gets us an owned `Function`, not a
1494 // `FunctionSig`.
1495 let signature =
1496 match Item::parse(cur, Some(potential_id), ctx) {
1497 Ok(item)
1498 if ctx
1499 .resolve_item(item)
1500 .kind()
1501 .is_function() =>
1502 {
1503 item
1504 }
1505 _ => return CXChildVisit_Continue,
1506 };
1507
1508 let signature = signature.expect_function_id(ctx);
1509
1510 match cur.kind() {
1511 CXCursor_Constructor => {
1512 ci.constructors.push(signature);
1513 }
1514 CXCursor_Destructor => {
1515 let kind = if is_virtual {
1516 MethodKind::VirtualDestructor {
1517 pure_virtual: cur.method_is_pure_virtual(),
1518 }
1519 } else {
1520 MethodKind::Destructor
1521 };
1522 ci.destructor = Some((kind, signature));
1523 }
1524 CXCursor_CXXMethod => {
1525 let is_const = cur.method_is_const();
1526 let method_kind = if is_static {
1527 MethodKind::Static
1528 } else if is_virtual {
1529 MethodKind::Virtual {
1530 pure_virtual: cur.method_is_pure_virtual(),
1531 }
1532 } else {
1533 MethodKind::Normal
1534 };
1535
1536 let method =
1537 Method::new(method_kind, signature, is_const);
1538
1539 ci.methods.push(method);
1540 }
1541 _ => unreachable!("How can we see this here?"),
1542 }
1543 }
1544 CXCursor_NonTypeTemplateParameter => {
1545 ci.has_non_type_template_params = true;
1546 }
1547 CXCursor_VarDecl => {
1548 let linkage = cur.linkage();
1549 if linkage != CXLinkage_External &&
1550 linkage != CXLinkage_UniqueExternal
1551 {
1552 return CXChildVisit_Continue;
1553 }
1554
1555 let visibility = cur.visibility();
1556 if visibility != CXVisibility_Default {
1557 return CXChildVisit_Continue;
1558 }
1559
1560 if let Ok(item) = Item::parse(cur, Some(potential_id), ctx)
1561 {
1562 ci.inner_vars.push(item.as_var_id_unchecked());
1563 }
1564 }
1565 // Intentionally not handled
1566 CXCursor_CXXAccessSpecifier |
1567 CXCursor_CXXFinalAttr |
1568 CXCursor_FunctionTemplate |
1569 CXCursor_ConversionFunction => {}
1570 _ => {
1571 warn!(
1572 "unhandled comp member `{}` (kind {:?}) in `{}` ({})",
1573 cur.spelling(),
1574 clang::kind_to_str(cur.kind()),
1575 cursor.spelling(),
1576 cur.location()
1577 );
1578 }
1579 }
1580 CXChildVisit_Continue
1581 });
1582
1583 if let Some((ty, _, public, offset)) = maybe_anonymous_struct_field {
1584 let field =
1585 RawField::new(None, ty, None, None, None, public, offset);
1586 ci.fields.append_raw_field(field);
1587 }
1588
1589 Ok(ci)
1590 }
1591
1592 fn kind_from_cursor(
1593 cursor: &clang::Cursor,
1594 ) -> Result<CompKind, ParseError> {
1595 use clang_sys::*;
1596 Ok(match cursor.kind() {
1597 CXCursor_UnionDecl => CompKind::Union,
1598 CXCursor_ClassDecl | CXCursor_StructDecl => CompKind::Struct,
1599 CXCursor_CXXBaseSpecifier |
1600 CXCursor_ClassTemplatePartialSpecialization |
1601 CXCursor_ClassTemplate => match cursor.template_kind() {
1602 CXCursor_UnionDecl => CompKind::Union,
1603 _ => CompKind::Struct,
1604 },
1605 _ => {
1606 warn!("Unknown kind for comp type: {:?}", cursor);
1607 return Err(ParseError::Continue);
1608 }
1609 })
1610 }
1611
1612 /// Get the set of types that were declared within this compound type
1613 /// (e.g. nested class definitions).
1614 pub fn inner_types(&self) -> &[TypeId] {
1615 &self.inner_types
1616 }
1617
1618 /// Get the set of static variables declared within this compound type.
1619 pub fn inner_vars(&self) -> &[VarId] {
1620 &self.inner_vars
1621 }
1622
1623 /// Have we found a field with an opaque type that could potentially mess up
1624 /// the layout of this compound type?
1625 pub fn found_unknown_attr(&self) -> bool {
1626 self.found_unknown_attr
1627 }
1628
1629 /// Is this compound type packed?
1630 pub fn is_packed(
1631 &self,
1632 ctx: &BindgenContext,
1633 layout: Option<&Layout>,
1634 ) -> bool {
1635 if self.packed_attr {
1636 return true;
1637 }
1638
1639 // Even though `libclang` doesn't expose `#pragma packed(...)`, we can
1640 // detect it through its effects.
1641 if let Some(parent_layout) = layout {
1642 let mut packed = false;
1643 self.each_known_field_layout(ctx, |layout| {
1644 packed = packed || layout.align > parent_layout.align;
1645 });
1646 if packed {
1647 info!("Found a struct that was defined within `#pragma packed(...)`");
1648 return true;
1649 }
1650
1651 if self.has_own_virtual_method && parent_layout.align == 1 {
1652 return true;
1653 }
1654 }
1655
1656 false
1657 }
1658
1659 /// Returns true if compound type has been forward declared
1660 pub fn is_forward_declaration(&self) -> bool {
1661 self.is_forward_declaration
1662 }
1663
1664 /// Compute this compound structure's bitfield allocation units.
1665 pub fn compute_bitfield_units(
1666 &mut self,
1667 ctx: &BindgenContext,
1668 layout: Option<&Layout>,
1669 ) {
1670 let packed = self.is_packed(ctx, layout);
1671 self.fields.compute_bitfield_units(ctx, packed)
1672 }
1673
1674 /// Assign for each anonymous field a generated name.
1675 pub fn deanonymize_fields(&mut self, ctx: &BindgenContext) {
1676 self.fields.deanonymize_fields(ctx, &self.methods);
1677 }
1678
1679 /// Returns whether the current union can be represented as a Rust `union`
1680 ///
1681 /// Requirements:
1682 /// 1. Current RustTarget allows for `untagged_union`
1683 /// 2. Each field can derive `Copy` or we use ManuallyDrop.
1684 /// 3. It's not zero-sized.
1685 ///
1686 /// Second boolean returns whether all fields can be copied (and thus
1687 /// ManuallyDrop is not needed).
1688 pub fn is_rust_union(
1689 &self,
1690 ctx: &BindgenContext,
1691 layout: Option<&Layout>,
1692 name: &str,
1693 ) -> (bool, bool) {
1694 if !self.is_union() {
1695 return (false, false);
1696 }
1697
1698 if !ctx.options().rust_features().untagged_union {
1699 return (false, false);
1700 }
1701
1702 if self.is_forward_declaration() {
1703 return (false, false);
1704 }
1705
1706 let union_style = if ctx.options().bindgen_wrapper_union.matches(name) {
1707 NonCopyUnionStyle::BindgenWrapper
1708 } else if ctx.options().manually_drop_union.matches(name) {
1709 NonCopyUnionStyle::ManuallyDrop
1710 } else {
1711 ctx.options().default_non_copy_union_style
1712 };
1713
1714 let all_can_copy = self.fields().iter().all(|f| match *f {
1715 Field::DataMember(ref field_data) => {
1716 field_data.ty().can_derive_copy(ctx)
1717 }
1718 Field::Bitfields(_) => true,
1719 });
1720
1721 if !all_can_copy && union_style == NonCopyUnionStyle::BindgenWrapper {
1722 return (false, false);
1723 }
1724
1725 if layout.map_or(false, |l| l.size == 0) {
1726 return (false, false);
1727 }
1728
1729 (true, all_can_copy)
1730 }
1731}
1732
1733impl DotAttributes for CompInfo {
1734 fn dot_attributes<W>(
1735 &self,
1736 ctx: &BindgenContext,
1737 out: &mut W,
1738 ) -> io::Result<()>
1739 where
1740 W: io::Write,
1741 {
1742 writeln!(out, "<tr><td>CompKind</td><td>{:?}</td></tr>", self.kind)?;
1743
1744 if self.has_own_virtual_method {
1745 writeln!(out, "<tr><td>has_vtable</td><td>true</td></tr>")?;
1746 }
1747
1748 if self.has_destructor {
1749 writeln!(out, "<tr><td>has_destructor</td><td>true</td></tr>")?;
1750 }
1751
1752 if self.has_nonempty_base {
1753 writeln!(out, "<tr><td>has_nonempty_base</td><td>true</td></tr>")?;
1754 }
1755
1756 if self.has_non_type_template_params {
1757 writeln!(
1758 out,
1759 "<tr><td>has_non_type_template_params</td><td>true</td></tr>"
1760 )?;
1761 }
1762
1763 if self.packed_attr {
1764 writeln!(out, "<tr><td>packed_attr</td><td>true</td></tr>")?;
1765 }
1766
1767 if self.is_forward_declaration {
1768 writeln!(
1769 out,
1770 "<tr><td>is_forward_declaration</td><td>true</td></tr>"
1771 )?;
1772 }
1773
1774 if !self.fields().is_empty() {
1775 writeln!(out, r#"<tr><td>fields</td><td><table border="0">"#)?;
1776 for field in self.fields() {
1777 field.dot_attributes(ctx, out)?;
1778 }
1779 writeln!(out, "</table></td></tr>")?;
1780 }
1781
1782 Ok(())
1783 }
1784}
1785
1786impl IsOpaque for CompInfo {
1787 type Extra = Option<Layout>;
1788
1789 fn is_opaque(&self, ctx: &BindgenContext, layout: &Option<Layout>) -> bool {
1790 if self.has_non_type_template_params ||
1791 self.has_unevaluable_bit_field_width
1792 {
1793 return true;
1794 }
1795
1796 // When we do not have the layout for a bitfield's type (for example, it
1797 // is a type parameter), then we can't compute bitfield units. We are
1798 // left with no choice but to make the whole struct opaque, or else we
1799 // might generate structs with incorrect sizes and alignments.
1800 if let CompFields::Error = self.fields {
1801 return true;
1802 }
1803
1804 // Bitfields with a width that is larger than their unit's width have
1805 // some strange things going on, and the best we can do is make the
1806 // whole struct opaque.
1807 if self.fields().iter().any(|f| match *f {
1808 Field::DataMember(_) => false,
1809 Field::Bitfields(ref unit) => unit.bitfields().iter().any(|bf| {
1810 let bitfield_layout = ctx
1811 .resolve_type(bf.ty())
1812 .layout(ctx)
1813 .expect("Bitfield without layout? Gah!");
1814 bf.width() / 8 > bitfield_layout.size as u32
1815 }),
1816 }) {
1817 return true;
1818 }
1819
1820 if !ctx.options().rust_features().repr_packed_n {
1821 // If we don't have `#[repr(packed(N)]`, the best we can
1822 // do is make this struct opaque.
1823 //
1824 // See https://github.com/rust-lang/rust-bindgen/issues/537 and
1825 // https://github.com/rust-lang/rust/issues/33158
1826 if self.is_packed(ctx, layout.as_ref()) &&
1827 layout.map_or(false, |l| l.align > 1)
1828 {
1829 warn!("Found a type that is both packed and aligned to greater than \
1830 1; Rust before version 1.33 doesn't have `#[repr(packed(N))]`, so we \
1831 are treating it as opaque. You may wish to set bindgen's rust target \
1832 version to 1.33 or later to enable `#[repr(packed(N))]` support.");
1833 return true;
1834 }
1835 }
1836
1837 false
1838 }
1839}
1840
1841impl TemplateParameters for CompInfo {
1842 fn self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId> {
1843 self.template_params.clone()
1844 }
1845}
1846
1847impl Trace for CompInfo {
1848 type Extra = Item;
1849
1850 fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
1851 where
1852 T: Tracer,
1853 {
1854 for p in item.all_template_params(context) {
1855 tracer.visit_kind(p.into(), EdgeKind::TemplateParameterDefinition);
1856 }
1857
1858 for ty in self.inner_types() {
1859 tracer.visit_kind(ty.into(), EdgeKind::InnerType);
1860 }
1861
1862 for &var in self.inner_vars() {
1863 tracer.visit_kind(var.into(), EdgeKind::InnerVar);
1864 }
1865
1866 for method in self.methods() {
1867 tracer.visit_kind(method.signature.into(), EdgeKind::Method);
1868 }
1869
1870 if let Some((_kind, signature)) = self.destructor() {
1871 tracer.visit_kind(signature.into(), EdgeKind::Destructor);
1872 }
1873
1874 for ctor in self.constructors() {
1875 tracer.visit_kind(ctor.into(), EdgeKind::Constructor);
1876 }
1877
1878 // Base members and fields are not generated for opaque types (but all
1879 // of the above things are) so stop here.
1880 if item.is_opaque(context, &()) {
1881 return;
1882 }
1883
1884 for base in self.base_members() {
1885 tracer.visit_kind(base.ty.into(), EdgeKind::BaseMember);
1886 }
1887
1888 self.fields.trace(context, tracer, &());
1889 }
1890}
1891