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