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