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