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