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