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 field 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 /// Return the flex array member for the struct/class, if any.
830 fn flex_array_member(&self, ctx: &BindgenContext) -> Option<TypeId> {
831 let fields = match self {
832 CompFields::Before(_) => panic!("raw fields"),
833 CompFields::After { fields, .. } => fields,
834 CompFields::Error => return None, // panic?
835 };
836
837 match fields.last()? {
838 Field::Bitfields(..) => None,
839 Field::DataMember(FieldData { ty, .. }) => ctx
840 .resolve_type(*ty)
841 .is_incomplete_array(ctx)
842 .map(|item| item.expect_type_id(ctx)),
843 }
844 }
845}
846
847impl Trace for CompFields {
848 type Extra = ();
849
850 fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, _: &())
851 where
852 T: Tracer,
853 {
854 match *self {
855 CompFields::Error => {}
856 CompFields::Before(ref fields: &Vec) => {
857 for f: &RawField in fields {
858 tracer.visit_kind(item:f.ty().into(), kind:EdgeKind::Field);
859 }
860 }
861 CompFields::After { ref fields: &Vec, .. } => {
862 for f: &Field in fields {
863 f.trace(context, tracer, &());
864 }
865 }
866 }
867 }
868}
869
870/// Common data shared across different field types.
871#[derive(Clone, Debug)]
872pub(crate) struct FieldData {
873 /// The name of the field, empty if it's an unnamed bitfield width.
874 name: Option<String>,
875
876 /// The inner type.
877 ty: TypeId,
878
879 /// The doc comment on the field if any.
880 comment: Option<String>,
881
882 /// Annotations for this field, or the default.
883 annotations: Annotations,
884
885 /// If this field is a bitfield, and how many bits does it contain if it is.
886 bitfield_width: Option<u32>,
887
888 /// If the C++ field is declared `public`
889 public: bool,
890
891 /// The offset of the field (in bits)
892 offset: Option<usize>,
893}
894
895impl FieldMethods for FieldData {
896 fn name(&self) -> Option<&str> {
897 self.name.as_deref()
898 }
899
900 fn ty(&self) -> TypeId {
901 self.ty
902 }
903
904 fn comment(&self) -> Option<&str> {
905 self.comment.as_deref()
906 }
907
908 fn bitfield_width(&self) -> Option<u32> {
909 self.bitfield_width
910 }
911
912 fn is_public(&self) -> bool {
913 self.public
914 }
915
916 fn annotations(&self) -> &Annotations {
917 &self.annotations
918 }
919
920 fn offset(&self) -> Option<usize> {
921 self.offset
922 }
923}
924
925/// The kind of inheritance a base class is using.
926#[derive(Clone, Debug, PartialEq, Eq)]
927pub(crate) enum BaseKind {
928 /// Normal inheritance, like:
929 ///
930 /// ```cpp
931 /// class A : public B {};
932 /// ```
933 Normal,
934 /// Virtual inheritance, like:
935 ///
936 /// ```cpp
937 /// class A: public virtual B {};
938 /// ```
939 Virtual,
940}
941
942/// A base class.
943#[derive(Clone, Debug)]
944pub(crate) struct Base {
945 /// The type of this base class.
946 pub(crate) ty: TypeId,
947 /// The kind of inheritance we're doing.
948 pub(crate) kind: BaseKind,
949 /// Name of the field in which this base should be stored.
950 pub(crate) field_name: String,
951 /// Whether this base is inherited from publicly.
952 pub(crate) is_pub: bool,
953}
954
955impl Base {
956 /// Whether this base class is inheriting virtually.
957 pub(crate) fn is_virtual(&self) -> bool {
958 self.kind == BaseKind::Virtual
959 }
960
961 /// Whether this base class should have it's own field for storage.
962 pub(crate) fn requires_storage(&self, ctx: &BindgenContext) -> bool {
963 // Virtual bases are already taken into account by the vtable
964 // pointer.
965 //
966 // FIXME(emilio): Is this always right?
967 if self.is_virtual() {
968 return false;
969 }
970
971 // NB: We won't include zero-sized types in our base chain because they
972 // would contribute to our size given the dummy field we insert for
973 // zero-sized types.
974 if self.ty.is_zero_sized(ctx) {
975 return false;
976 }
977
978 true
979 }
980
981 /// Whether this base is inherited from publicly.
982 pub(crate) fn is_public(&self) -> bool {
983 self.is_pub
984 }
985}
986
987/// A compound type.
988///
989/// Either a struct or union, a compound type is built up from the combination
990/// of fields which also are associated with their own (potentially compound)
991/// type.
992#[derive(Debug)]
993pub(crate) struct CompInfo {
994 /// Whether this is a struct or a union.
995 kind: CompKind,
996
997 /// The members of this struct or union.
998 fields: CompFields,
999
1000 /// The abstract template parameters of this class. Note that these are NOT
1001 /// concrete template arguments, and should always be a
1002 /// `Type(TypeKind::TypeParam(name))`. For concrete template arguments, see
1003 /// `TypeKind::TemplateInstantiation`.
1004 template_params: Vec<TypeId>,
1005
1006 /// The method declarations inside this class, if in C++ mode.
1007 methods: Vec<Method>,
1008
1009 /// The different constructors this struct or class contains.
1010 constructors: Vec<FunctionId>,
1011
1012 /// The destructor of this type. The bool represents whether this destructor
1013 /// is virtual.
1014 destructor: Option<(MethodKind, FunctionId)>,
1015
1016 /// Vector of classes this one inherits from.
1017 base_members: Vec<Base>,
1018
1019 /// The inner types that were declared inside this class, in something like:
1020 ///
1021 /// class Foo {
1022 /// typedef int FooTy;
1023 /// struct Bar {
1024 /// int baz;
1025 /// };
1026 /// }
1027 ///
1028 /// static Foo::Bar const = {3};
1029 inner_types: Vec<TypeId>,
1030
1031 /// Set of static constants declared inside this class.
1032 inner_vars: Vec<VarId>,
1033
1034 /// Whether this type should generate an vtable (TODO: Should be able to
1035 /// look at the virtual methods and ditch this field).
1036 has_own_virtual_method: bool,
1037
1038 /// Whether this type has destructor.
1039 has_destructor: bool,
1040
1041 /// Whether this type has a base type with more than one member.
1042 ///
1043 /// TODO: We should be able to compute this.
1044 has_nonempty_base: bool,
1045
1046 /// If this type has a template parameter which is not a type (e.g.: a
1047 /// size_t)
1048 has_non_type_template_params: bool,
1049
1050 /// Whether this type has a bit field member whose width couldn't be
1051 /// evaluated (e.g. if it depends on a template parameter). We generate an
1052 /// opaque type in this case.
1053 has_unevaluable_bit_field_width: bool,
1054
1055 /// Whether we saw `__attribute__((packed))` on or within this type.
1056 packed_attr: bool,
1057
1058 /// Used to know if we've found an opaque attribute that could cause us to
1059 /// generate a type with invalid layout. This is explicitly used to avoid us
1060 /// generating bad alignments when parsing types like max_align_t.
1061 ///
1062 /// It's not clear what the behavior should be here, if generating the item
1063 /// and pray, or behave as an opaque type.
1064 found_unknown_attr: bool,
1065
1066 /// Used to indicate when a struct has been forward declared. Usually used
1067 /// in headers so that APIs can't modify them directly.
1068 is_forward_declaration: bool,
1069}
1070
1071impl CompInfo {
1072 /// Construct a new compound type.
1073 pub(crate) fn new(kind: CompKind) -> Self {
1074 CompInfo {
1075 kind,
1076 fields: CompFields::default(),
1077 template_params: vec![],
1078 methods: vec![],
1079 constructors: vec![],
1080 destructor: None,
1081 base_members: vec![],
1082 inner_types: vec![],
1083 inner_vars: vec![],
1084 has_own_virtual_method: false,
1085 has_destructor: false,
1086 has_nonempty_base: false,
1087 has_non_type_template_params: false,
1088 has_unevaluable_bit_field_width: false,
1089 packed_attr: false,
1090 found_unknown_attr: false,
1091 is_forward_declaration: false,
1092 }
1093 }
1094
1095 /// Compute the layout of this type.
1096 ///
1097 /// This is called as a fallback under some circumstances where LLVM doesn't
1098 /// give us the correct layout.
1099 ///
1100 /// If we're a union without known layout, we try to compute it from our
1101 /// members. This is not ideal, but clang fails to report the size for these
1102 /// kind of unions, see test/headers/template_union.hpp
1103 pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
1104 // We can't do better than clang here, sorry.
1105 if self.kind == CompKind::Struct {
1106 return None;
1107 }
1108
1109 // By definition, we don't have the right layout information here if
1110 // we're a forward declaration.
1111 if self.is_forward_declaration() {
1112 return None;
1113 }
1114
1115 // empty union case
1116 if !self.has_fields() {
1117 return None;
1118 }
1119
1120 let mut max_size = 0;
1121 // Don't allow align(0)
1122 let mut max_align = 1;
1123 self.each_known_field_layout(ctx, |layout| {
1124 max_size = cmp::max(max_size, layout.size);
1125 max_align = cmp::max(max_align, layout.align);
1126 });
1127
1128 Some(Layout::new(max_size, max_align))
1129 }
1130
1131 /// Get this type's set of fields.
1132 pub(crate) fn fields(&self) -> &[Field] {
1133 match self.fields {
1134 CompFields::Error => &[],
1135 CompFields::After { ref fields, .. } => fields,
1136 CompFields::Before(..) => {
1137 panic!("Should always have computed bitfield units first");
1138 }
1139 }
1140 }
1141
1142 /// Return the flex array member and its element type if any
1143 pub(crate) fn flex_array_member(
1144 &self,
1145 ctx: &BindgenContext,
1146 ) -> Option<TypeId> {
1147 self.fields.flex_array_member(ctx)
1148 }
1149
1150 fn has_fields(&self) -> bool {
1151 match self.fields {
1152 CompFields::Error => false,
1153 CompFields::After { ref fields, .. } => !fields.is_empty(),
1154 CompFields::Before(ref raw_fields) => !raw_fields.is_empty(),
1155 }
1156 }
1157
1158 fn each_known_field_layout(
1159 &self,
1160 ctx: &BindgenContext,
1161 mut callback: impl FnMut(Layout),
1162 ) {
1163 match self.fields {
1164 CompFields::Error => {}
1165 CompFields::After { ref fields, .. } => {
1166 for field in fields.iter() {
1167 if let Some(layout) = field.layout(ctx) {
1168 callback(layout);
1169 }
1170 }
1171 }
1172 CompFields::Before(ref raw_fields) => {
1173 for field in raw_fields.iter() {
1174 let field_ty = ctx.resolve_type(field.0.ty);
1175 if let Some(layout) = field_ty.layout(ctx) {
1176 callback(layout);
1177 }
1178 }
1179 }
1180 }
1181 }
1182
1183 fn has_bitfields(&self) -> bool {
1184 match self.fields {
1185 CompFields::Error => false,
1186 CompFields::After {
1187 has_bitfield_units, ..
1188 } => has_bitfield_units,
1189 CompFields::Before(_) => {
1190 panic!("Should always have computed bitfield units first");
1191 }
1192 }
1193 }
1194
1195 /// Returns whether we have a too large bitfield unit, in which case we may
1196 /// not be able to derive some of the things we should be able to normally
1197 /// derive.
1198 pub(crate) fn has_too_large_bitfield_unit(&self) -> bool {
1199 if !self.has_bitfields() {
1200 return false;
1201 }
1202 self.fields().iter().any(|field| match *field {
1203 Field::DataMember(..) => false,
1204 Field::Bitfields(ref unit) => {
1205 unit.layout.size > RUST_DERIVE_IN_ARRAY_LIMIT
1206 }
1207 })
1208 }
1209
1210 /// Does this type have any template parameters that aren't types
1211 /// (e.g. int)?
1212 pub(crate) fn has_non_type_template_params(&self) -> bool {
1213 self.has_non_type_template_params
1214 }
1215
1216 /// Do we see a virtual function during parsing?
1217 /// Get the has_own_virtual_method boolean.
1218 pub(crate) fn has_own_virtual_method(&self) -> bool {
1219 self.has_own_virtual_method
1220 }
1221
1222 /// Did we see a destructor when parsing this type?
1223 pub(crate) fn has_own_destructor(&self) -> bool {
1224 self.has_destructor
1225 }
1226
1227 /// Get this type's set of methods.
1228 pub(crate) fn methods(&self) -> &[Method] {
1229 &self.methods
1230 }
1231
1232 /// Get this type's set of constructors.
1233 pub(crate) fn constructors(&self) -> &[FunctionId] {
1234 &self.constructors
1235 }
1236
1237 /// Get this type's destructor.
1238 pub(crate) fn destructor(&self) -> Option<(MethodKind, FunctionId)> {
1239 self.destructor
1240 }
1241
1242 /// What kind of compound type is this?
1243 pub(crate) fn kind(&self) -> CompKind {
1244 self.kind
1245 }
1246
1247 /// Is this a union?
1248 pub(crate) fn is_union(&self) -> bool {
1249 self.kind() == CompKind::Union
1250 }
1251
1252 /// The set of types that this one inherits from.
1253 pub(crate) fn base_members(&self) -> &[Base] {
1254 &self.base_members
1255 }
1256
1257 /// Construct a new compound type from a Clang type.
1258 pub(crate) fn from_ty(
1259 potential_id: ItemId,
1260 ty: &clang::Type,
1261 location: Option<clang::Cursor>,
1262 ctx: &mut BindgenContext,
1263 ) -> Result<Self, ParseError> {
1264 use clang_sys::*;
1265 assert!(
1266 ty.template_args().is_none(),
1267 "We handle template instantiations elsewhere"
1268 );
1269
1270 let mut cursor = ty.declaration();
1271 let mut kind = Self::kind_from_cursor(&cursor);
1272 if kind.is_err() {
1273 if let Some(location) = location {
1274 kind = Self::kind_from_cursor(&location);
1275 cursor = location;
1276 }
1277 }
1278
1279 let kind = kind?;
1280
1281 debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor);
1282
1283 let mut ci = CompInfo::new(kind);
1284 ci.is_forward_declaration =
1285 location.map_or(true, |cur| match cur.kind() {
1286 CXCursor_ParmDecl => true,
1287 CXCursor_StructDecl | CXCursor_UnionDecl |
1288 CXCursor_ClassDecl => !cur.is_definition(),
1289 _ => false,
1290 });
1291
1292 let mut maybe_anonymous_struct_field = None;
1293 cursor.visit(|cur| {
1294 if cur.kind() != CXCursor_FieldDecl {
1295 if let Some((ty, clang_ty, public, offset)) =
1296 maybe_anonymous_struct_field.take()
1297 {
1298 if cur.kind() == CXCursor_TypedefDecl &&
1299 cur.typedef_type().unwrap().canonical_type() ==
1300 clang_ty
1301 {
1302 // Typedefs of anonymous structs appear later in the ast
1303 // than the struct itself, that would otherwise be an
1304 // anonymous field. Detect that case here, and do
1305 // nothing.
1306 } else {
1307 let field = RawField::new(
1308 None, ty, None, None, None, public, offset,
1309 );
1310 ci.fields.append_raw_field(field);
1311 }
1312 }
1313 }
1314
1315 match cur.kind() {
1316 CXCursor_FieldDecl => {
1317 if let Some((ty, clang_ty, public, offset)) =
1318 maybe_anonymous_struct_field.take()
1319 {
1320 let mut used = false;
1321 cur.visit(|child| {
1322 if child.cur_type() == clang_ty {
1323 used = true;
1324 }
1325 CXChildVisit_Continue
1326 });
1327
1328 if !used {
1329 let field = RawField::new(
1330 None, ty, None, None, None, public, offset,
1331 );
1332 ci.fields.append_raw_field(field);
1333 }
1334 }
1335
1336 let bit_width = if cur.is_bit_field() {
1337 let width = cur.bit_width();
1338
1339 // Make opaque type if the bit width couldn't be
1340 // evaluated.
1341 if width.is_none() {
1342 ci.has_unevaluable_bit_field_width = true;
1343 return CXChildVisit_Break;
1344 }
1345
1346 width
1347 } else {
1348 None
1349 };
1350
1351 let field_type = Item::from_ty_or_ref(
1352 cur.cur_type(),
1353 cur,
1354 Some(potential_id),
1355 ctx,
1356 );
1357
1358 let comment = cur.raw_comment();
1359 let annotations = Annotations::new(&cur);
1360 let name = cur.spelling();
1361 let is_public = cur.public_accessible();
1362 let offset = cur.offset_of_field().ok();
1363
1364 // Name can be empty if there are bitfields, for example,
1365 // see tests/headers/struct_with_bitfields.h
1366 assert!(
1367 !name.is_empty() || bit_width.is_some(),
1368 "Empty field name?"
1369 );
1370
1371 let name = if name.is_empty() { None } else { Some(name) };
1372
1373 let field = RawField::new(
1374 name,
1375 field_type,
1376 comment,
1377 annotations,
1378 bit_width,
1379 is_public,
1380 offset,
1381 );
1382 ci.fields.append_raw_field(field);
1383
1384 // No we look for things like attributes and stuff.
1385 cur.visit(|cur| {
1386 if cur.kind() == CXCursor_UnexposedAttr {
1387 ci.found_unknown_attr = true;
1388 }
1389 CXChildVisit_Continue
1390 });
1391 }
1392 CXCursor_UnexposedAttr => {
1393 ci.found_unknown_attr = true;
1394 }
1395 CXCursor_EnumDecl |
1396 CXCursor_TypeAliasDecl |
1397 CXCursor_TypeAliasTemplateDecl |
1398 CXCursor_TypedefDecl |
1399 CXCursor_StructDecl |
1400 CXCursor_UnionDecl |
1401 CXCursor_ClassTemplate |
1402 CXCursor_ClassDecl => {
1403 // We can find non-semantic children here, clang uses a
1404 // StructDecl to note incomplete structs that haven't been
1405 // forward-declared before, see [1].
1406 //
1407 // Also, clang seems to scope struct definitions inside
1408 // unions, and other named struct definitions inside other
1409 // structs to the whole translation unit.
1410 //
1411 // Let's just assume that if the cursor we've found is a
1412 // definition, it's a valid inner type.
1413 //
1414 // [1]: https://github.com/rust-lang/rust-bindgen/issues/482
1415 let is_inner_struct =
1416 cur.semantic_parent() == cursor || cur.is_definition();
1417 if !is_inner_struct {
1418 return CXChildVisit_Continue;
1419 }
1420
1421 // Even if this is a definition, we may not be the semantic
1422 // parent, see #1281.
1423 let inner = Item::parse(cur, Some(potential_id), ctx)
1424 .expect("Inner ClassDecl");
1425
1426 // If we avoided recursion parsing this type (in
1427 // `Item::from_ty_with_id()`), then this might not be a
1428 // valid type ID, so check and gracefully handle this.
1429 if ctx.resolve_item_fallible(inner).is_some() {
1430 let inner = inner.expect_type_id(ctx);
1431
1432 ci.inner_types.push(inner);
1433
1434 // A declaration of an union or a struct without name
1435 // could also be an unnamed field, unfortunately.
1436 if cur.is_anonymous() && cur.kind() != CXCursor_EnumDecl
1437 {
1438 let ty = cur.cur_type();
1439 let public = cur.public_accessible();
1440 let offset = cur.offset_of_field().ok();
1441
1442 maybe_anonymous_struct_field =
1443 Some((inner, ty, public, offset));
1444 }
1445 }
1446 }
1447 CXCursor_PackedAttr => {
1448 ci.packed_attr = true;
1449 }
1450 CXCursor_TemplateTypeParameter => {
1451 let param = Item::type_param(None, cur, ctx).expect(
1452 "Item::type_param shouldn't fail when pointing \
1453 at a TemplateTypeParameter",
1454 );
1455 ci.template_params.push(param);
1456 }
1457 CXCursor_CXXBaseSpecifier => {
1458 let is_virtual_base = cur.is_virtual_base();
1459 ci.has_own_virtual_method |= is_virtual_base;
1460
1461 let kind = if is_virtual_base {
1462 BaseKind::Virtual
1463 } else {
1464 BaseKind::Normal
1465 };
1466
1467 let field_name = match ci.base_members.len() {
1468 0 => "_base".into(),
1469 n => format!("_base_{}", n),
1470 };
1471 let type_id =
1472 Item::from_ty_or_ref(cur.cur_type(), cur, None, ctx);
1473 ci.base_members.push(Base {
1474 ty: type_id,
1475 kind,
1476 field_name,
1477 is_pub: cur.access_specifier() ==
1478 clang_sys::CX_CXXPublic,
1479 });
1480 }
1481 CXCursor_Constructor | CXCursor_Destructor |
1482 CXCursor_CXXMethod => {
1483 let is_virtual = cur.method_is_virtual();
1484 let is_static = cur.method_is_static();
1485 debug_assert!(!(is_static && is_virtual), "How?");
1486
1487 ci.has_destructor |= cur.kind() == CXCursor_Destructor;
1488 ci.has_own_virtual_method |= is_virtual;
1489
1490 // This used to not be here, but then I tried generating
1491 // stylo bindings with this (without path filters), and
1492 // cried a lot with a method in gfx/Point.h
1493 // (ToUnknownPoint), that somehow was causing the same type
1494 // to be inserted in the map two times.
1495 //
1496 // I couldn't make a reduced test case, but anyway...
1497 // Methods of template functions not only used to be inlined,
1498 // but also instantiated, and we wouldn't be able to call
1499 // them, so just bail out.
1500 if !ci.template_params.is_empty() {
1501 return CXChildVisit_Continue;
1502 }
1503
1504 // NB: This gets us an owned `Function`, not a
1505 // `FunctionSig`.
1506 let signature =
1507 match Item::parse(cur, Some(potential_id), ctx) {
1508 Ok(item)
1509 if ctx
1510 .resolve_item(item)
1511 .kind()
1512 .is_function() =>
1513 {
1514 item
1515 }
1516 _ => return CXChildVisit_Continue,
1517 };
1518
1519 let signature = signature.expect_function_id(ctx);
1520
1521 match cur.kind() {
1522 CXCursor_Constructor => {
1523 ci.constructors.push(signature);
1524 }
1525 CXCursor_Destructor => {
1526 let kind = if is_virtual {
1527 MethodKind::VirtualDestructor {
1528 pure_virtual: cur.method_is_pure_virtual(),
1529 }
1530 } else {
1531 MethodKind::Destructor
1532 };
1533 ci.destructor = Some((kind, signature));
1534 }
1535 CXCursor_CXXMethod => {
1536 let is_const = cur.method_is_const();
1537 let method_kind = if is_static {
1538 MethodKind::Static
1539 } else if is_virtual {
1540 MethodKind::Virtual {
1541 pure_virtual: cur.method_is_pure_virtual(),
1542 }
1543 } else {
1544 MethodKind::Normal
1545 };
1546
1547 let method =
1548 Method::new(method_kind, signature, is_const);
1549
1550 ci.methods.push(method);
1551 }
1552 _ => unreachable!("How can we see this here?"),
1553 }
1554 }
1555 CXCursor_NonTypeTemplateParameter => {
1556 ci.has_non_type_template_params = true;
1557 }
1558 CXCursor_VarDecl => {
1559 let linkage = cur.linkage();
1560 if linkage != CXLinkage_External &&
1561 linkage != CXLinkage_UniqueExternal
1562 {
1563 return CXChildVisit_Continue;
1564 }
1565
1566 let visibility = cur.visibility();
1567 if visibility != CXVisibility_Default {
1568 return CXChildVisit_Continue;
1569 }
1570
1571 if let Ok(item) = Item::parse(cur, Some(potential_id), ctx)
1572 {
1573 ci.inner_vars.push(item.as_var_id_unchecked());
1574 }
1575 }
1576 // Intentionally not handled
1577 CXCursor_CXXAccessSpecifier |
1578 CXCursor_CXXFinalAttr |
1579 CXCursor_FunctionTemplate |
1580 CXCursor_ConversionFunction => {}
1581 _ => {
1582 warn!(
1583 "unhandled comp member `{}` (kind {:?}) in `{}` ({})",
1584 cur.spelling(),
1585 clang::kind_to_str(cur.kind()),
1586 cursor.spelling(),
1587 cur.location()
1588 );
1589 }
1590 }
1591 CXChildVisit_Continue
1592 });
1593
1594 if let Some((ty, _, public, offset)) = maybe_anonymous_struct_field {
1595 let field =
1596 RawField::new(None, ty, None, None, None, public, offset);
1597 ci.fields.append_raw_field(field);
1598 }
1599
1600 Ok(ci)
1601 }
1602
1603 fn kind_from_cursor(
1604 cursor: &clang::Cursor,
1605 ) -> Result<CompKind, ParseError> {
1606 use clang_sys::*;
1607 Ok(match cursor.kind() {
1608 CXCursor_UnionDecl => CompKind::Union,
1609 CXCursor_ClassDecl | CXCursor_StructDecl => CompKind::Struct,
1610 CXCursor_CXXBaseSpecifier |
1611 CXCursor_ClassTemplatePartialSpecialization |
1612 CXCursor_ClassTemplate => match cursor.template_kind() {
1613 CXCursor_UnionDecl => CompKind::Union,
1614 _ => CompKind::Struct,
1615 },
1616 _ => {
1617 warn!("Unknown kind for comp type: {:?}", cursor);
1618 return Err(ParseError::Continue);
1619 }
1620 })
1621 }
1622
1623 /// Get the set of types that were declared within this compound type
1624 /// (e.g. nested class definitions).
1625 pub(crate) fn inner_types(&self) -> &[TypeId] {
1626 &self.inner_types
1627 }
1628
1629 /// Get the set of static variables declared within this compound type.
1630 pub(crate) fn inner_vars(&self) -> &[VarId] {
1631 &self.inner_vars
1632 }
1633
1634 /// Have we found a field with an opaque type that could potentially mess up
1635 /// the layout of this compound type?
1636 pub(crate) fn found_unknown_attr(&self) -> bool {
1637 self.found_unknown_attr
1638 }
1639
1640 /// Is this compound type packed?
1641 pub(crate) fn is_packed(
1642 &self,
1643 ctx: &BindgenContext,
1644 layout: Option<&Layout>,
1645 ) -> bool {
1646 if self.packed_attr {
1647 return true;
1648 }
1649
1650 // Even though `libclang` doesn't expose `#pragma packed(...)`, we can
1651 // detect it through its effects.
1652 if let Some(parent_layout) = layout {
1653 let mut packed = false;
1654 self.each_known_field_layout(ctx, |layout| {
1655 packed = packed || layout.align > parent_layout.align;
1656 });
1657 if packed {
1658 info!("Found a struct that was defined within `#pragma packed(...)`");
1659 return true;
1660 }
1661
1662 if self.has_own_virtual_method && parent_layout.align == 1 {
1663 return true;
1664 }
1665 }
1666
1667 false
1668 }
1669
1670 /// Return true if a compound type is "naturally packed". This means we can exclude the
1671 /// "packed" attribute without changing the layout.
1672 /// This is useful for types that need an "align(N)" attribute since rustc won't compile
1673 /// structs that have both of those attributes.
1674 pub(crate) fn already_packed(&self, ctx: &BindgenContext) -> Option<bool> {
1675 let mut total_size: usize = 0;
1676
1677 for field in self.fields().iter() {
1678 let layout = field.layout(ctx)?;
1679
1680 if layout.align != 0 && total_size % layout.align != 0 {
1681 return Some(false);
1682 }
1683
1684 total_size += layout.size;
1685 }
1686
1687 Some(true)
1688 }
1689
1690 /// Returns true if compound type has been forward declared
1691 pub(crate) fn is_forward_declaration(&self) -> bool {
1692 self.is_forward_declaration
1693 }
1694
1695 /// Compute this compound structure's bitfield allocation units.
1696 pub(crate) fn compute_bitfield_units(
1697 &mut self,
1698 ctx: &BindgenContext,
1699 layout: Option<&Layout>,
1700 ) {
1701 let packed = self.is_packed(ctx, layout);
1702 self.fields.compute_bitfield_units(ctx, packed)
1703 }
1704
1705 /// Assign for each anonymous field a generated name.
1706 pub(crate) fn deanonymize_fields(&mut self, ctx: &BindgenContext) {
1707 self.fields.deanonymize_fields(ctx, &self.methods);
1708 }
1709
1710 /// Returns whether the current union can be represented as a Rust `union`
1711 ///
1712 /// Requirements:
1713 /// 1. Current RustTarget allows for `untagged_union`
1714 /// 2. Each field can derive `Copy` or we use ManuallyDrop.
1715 /// 3. It's not zero-sized.
1716 ///
1717 /// Second boolean returns whether all fields can be copied (and thus
1718 /// ManuallyDrop is not needed).
1719 pub(crate) fn is_rust_union(
1720 &self,
1721 ctx: &BindgenContext,
1722 layout: Option<&Layout>,
1723 name: &str,
1724 ) -> (bool, bool) {
1725 if !self.is_union() {
1726 return (false, false);
1727 }
1728
1729 if !ctx.options().untagged_union {
1730 return (false, false);
1731 }
1732
1733 if self.is_forward_declaration() {
1734 return (false, false);
1735 }
1736
1737 let union_style = if ctx.options().bindgen_wrapper_union.matches(name) {
1738 NonCopyUnionStyle::BindgenWrapper
1739 } else if ctx.options().manually_drop_union.matches(name) {
1740 NonCopyUnionStyle::ManuallyDrop
1741 } else {
1742 ctx.options().default_non_copy_union_style
1743 };
1744
1745 let all_can_copy = self.fields().iter().all(|f| match *f {
1746 Field::DataMember(ref field_data) => {
1747 field_data.ty().can_derive_copy(ctx)
1748 }
1749 Field::Bitfields(_) => true,
1750 });
1751
1752 if !all_can_copy && union_style == NonCopyUnionStyle::BindgenWrapper {
1753 return (false, false);
1754 }
1755
1756 if layout.map_or(false, |l| l.size == 0) {
1757 return (false, false);
1758 }
1759
1760 (true, all_can_copy)
1761 }
1762}
1763
1764impl DotAttributes for CompInfo {
1765 fn dot_attributes<W>(
1766 &self,
1767 ctx: &BindgenContext,
1768 out: &mut W,
1769 ) -> io::Result<()>
1770 where
1771 W: io::Write,
1772 {
1773 writeln!(out, "<tr><td>CompKind</td><td>{:?}</td></tr>", self.kind)?;
1774
1775 if self.has_own_virtual_method {
1776 writeln!(out, "<tr><td>has_vtable</td><td>true</td></tr>")?;
1777 }
1778
1779 if self.has_destructor {
1780 writeln!(out, "<tr><td>has_destructor</td><td>true</td></tr>")?;
1781 }
1782
1783 if self.has_nonempty_base {
1784 writeln!(out, "<tr><td>has_nonempty_base</td><td>true</td></tr>")?;
1785 }
1786
1787 if self.has_non_type_template_params {
1788 writeln!(
1789 out,
1790 "<tr><td>has_non_type_template_params</td><td>true</td></tr>"
1791 )?;
1792 }
1793
1794 if self.packed_attr {
1795 writeln!(out, "<tr><td>packed_attr</td><td>true</td></tr>")?;
1796 }
1797
1798 if self.is_forward_declaration {
1799 writeln!(
1800 out,
1801 "<tr><td>is_forward_declaration</td><td>true</td></tr>"
1802 )?;
1803 }
1804
1805 if !self.fields().is_empty() {
1806 writeln!(out, r#"<tr><td>fields</td><td><table border="0">"#)?;
1807 for field in self.fields() {
1808 field.dot_attributes(ctx, out)?;
1809 }
1810 writeln!(out, "</table></td></tr>")?;
1811 }
1812
1813 Ok(())
1814 }
1815}
1816
1817impl IsOpaque for CompInfo {
1818 type Extra = Option<Layout>;
1819
1820 fn is_opaque(&self, ctx: &BindgenContext, layout: &Option<Layout>) -> bool {
1821 if self.has_non_type_template_params ||
1822 self.has_unevaluable_bit_field_width
1823 {
1824 return true;
1825 }
1826
1827 // When we do not have the layout for a bitfield's type (for example, it
1828 // is a type parameter), then we can't compute bitfield units. We are
1829 // left with no choice but to make the whole struct opaque, or else we
1830 // might generate structs with incorrect sizes and alignments.
1831 if let CompFields::Error = self.fields {
1832 return true;
1833 }
1834
1835 // Bitfields with a width that is larger than their unit's width have
1836 // some strange things going on, and the best we can do is make the
1837 // whole struct opaque.
1838 if self.fields().iter().any(|f| match *f {
1839 Field::DataMember(_) => false,
1840 Field::Bitfields(ref unit) => unit.bitfields().iter().any(|bf| {
1841 let bitfield_layout = ctx
1842 .resolve_type(bf.ty())
1843 .layout(ctx)
1844 .expect("Bitfield without layout? Gah!");
1845 bf.width() / 8 > bitfield_layout.size as u32
1846 }),
1847 }) {
1848 return true;
1849 }
1850
1851 if !ctx.options().rust_features().repr_packed_n {
1852 // If we don't have `#[repr(packed(N)]`, the best we can
1853 // do is make this struct opaque.
1854 //
1855 // See https://github.com/rust-lang/rust-bindgen/issues/537 and
1856 // https://github.com/rust-lang/rust/issues/33158
1857 if self.is_packed(ctx, layout.as_ref()) &&
1858 layout.map_or(false, |l| l.align > 1)
1859 {
1860 warn!("Found a type that is both packed and aligned to greater than \
1861 1; Rust before version 1.33 doesn't have `#[repr(packed(N))]`, so we \
1862 are treating it as opaque. You may wish to set bindgen's rust target \
1863 version to 1.33 or later to enable `#[repr(packed(N))]` support.");
1864 return true;
1865 }
1866 }
1867
1868 false
1869 }
1870}
1871
1872impl TemplateParameters for CompInfo {
1873 fn self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId> {
1874 self.template_params.clone()
1875 }
1876}
1877
1878impl Trace for CompInfo {
1879 type Extra = Item;
1880
1881 fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
1882 where
1883 T: Tracer,
1884 {
1885 for p in item.all_template_params(context) {
1886 tracer.visit_kind(p.into(), EdgeKind::TemplateParameterDefinition);
1887 }
1888
1889 for ty in self.inner_types() {
1890 tracer.visit_kind(ty.into(), EdgeKind::InnerType);
1891 }
1892
1893 for &var in self.inner_vars() {
1894 tracer.visit_kind(var.into(), EdgeKind::InnerVar);
1895 }
1896
1897 for method in self.methods() {
1898 tracer.visit_kind(method.signature.into(), EdgeKind::Method);
1899 }
1900
1901 if let Some((_kind, signature)) = self.destructor() {
1902 tracer.visit_kind(signature.into(), EdgeKind::Destructor);
1903 }
1904
1905 for ctor in self.constructors() {
1906 tracer.visit_kind(ctor.into(), EdgeKind::Constructor);
1907 }
1908
1909 // Base members and fields are not generated for opaque types (but all
1910 // of the above things are) so stop here.
1911 if item.is_opaque(context, &()) {
1912 return;
1913 }
1914
1915 for base in self.base_members() {
1916 tracer.visit_kind(base.ty.into(), EdgeKind::BaseMember);
1917 }
1918
1919 self.fields.trace(context, tracer, &());
1920 }
1921}
1922