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