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