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