Fix `-Z print-type-sizes`'s handling of zero-sized fields.
Currently, the type `struct S { x: u32, y: u32, tag: () }` is incorrectly described like this: ``` print-type-size type: `S`: 8 bytes, alignment: 4 bytes print-type-size field `.x`: 4 bytes print-type-size field `.tag`: 0 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size padding: 4 bytes print-type-size field `.y`: 4 bytes, alignment: 4 bytes ``` Specifically: - The `padding` line is wrong. (There is no padding.) - The `offset` and `alignment` on the `.tag` line shouldn't be printed. The problem is that multiple fields can end up with the same offset, and the printing code doesn't handle this correctly. This commit fixes it by adjusting the field sorting so that zero-sized fields are dealt with before non-zero-sized fields. With that in place, the printing code works correctly. The commit also corrects the "something is very wrong" comment. The new output looks like this: ``` print-type-size type: `S`: 8 bytes, alignment: 4 bytes print-type-size field `.tag`: 0 bytes print-type-size field `.x`: 4 bytes print-type-size field `.y`: 4 bytes ```
This commit is contained in:
parent
7dbfb0a8ca
commit
c681841ca0
|
@ -132,9 +132,12 @@ impl CodeStats {
|
|||
|
||||
let mut min_offset = discr_size;
|
||||
|
||||
// We want to print fields by increasing offset.
|
||||
// We want to print fields by increasing offset. We also want
|
||||
// zero-sized fields before non-zero-sized fields, otherwise
|
||||
// the loop below goes wrong; hence the `f.size` in the sort
|
||||
// key.
|
||||
let mut fields = fields.clone();
|
||||
fields.sort_by_key(|f| f.offset);
|
||||
fields.sort_by_key(|f| (f.offset, f.size));
|
||||
|
||||
for field in fields.iter() {
|
||||
let FieldInfo { ref name, offset, size, align } = *field;
|
||||
|
@ -146,7 +149,7 @@ impl CodeStats {
|
|||
}
|
||||
|
||||
if offset < min_offset {
|
||||
// if this happens something is very wrong
|
||||
// If this happens it's probably a union.
|
||||
println!("print-type-size {}field `.{}`: {} bytes, \
|
||||
offset: {} bytes, \
|
||||
alignment: {} bytes",
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// compile-flags: -Z print-type-sizes
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
// At one point, zero-sized fields such as those in this file were causing
|
||||
// incorrect output from `-Z print-type-sizes`.
|
||||
|
||||
#![feature(start)]
|
||||
|
||||
struct S1 {
|
||||
x: u32,
|
||||
y: u32,
|
||||
tag: (),
|
||||
}
|
||||
|
||||
struct Void();
|
||||
struct Empty {}
|
||||
|
||||
struct S5<TagW, TagZ> {
|
||||
tagw: TagW,
|
||||
w: u32,
|
||||
unit: (),
|
||||
x: u32,
|
||||
void: Void,
|
||||
y: u32,
|
||||
empty: Empty,
|
||||
z: u32,
|
||||
tagz: TagZ,
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn start(_: isize, _: *const *const u8) -> isize {
|
||||
let _s1: S1 = S1 { x: 0, y: 0, tag: () };
|
||||
|
||||
let _s5: S5<(), Empty> = S5 {
|
||||
tagw: (),
|
||||
w: 1,
|
||||
unit: (),
|
||||
x: 2,
|
||||
void: Void(),
|
||||
y: 3,
|
||||
empty: Empty {},
|
||||
z: 4,
|
||||
tagz: Empty {},
|
||||
};
|
||||
0
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
print-type-size type: `S5<(), Empty>`: 16 bytes, alignment: 4 bytes
|
||||
print-type-size field `.tagw`: 0 bytes
|
||||
print-type-size field `.unit`: 0 bytes
|
||||
print-type-size field `.void`: 0 bytes
|
||||
print-type-size field `.empty`: 0 bytes
|
||||
print-type-size field `.tagz`: 0 bytes
|
||||
print-type-size field `.w`: 4 bytes
|
||||
print-type-size field `.x`: 4 bytes
|
||||
print-type-size field `.y`: 4 bytes
|
||||
print-type-size field `.z`: 4 bytes
|
||||
print-type-size type: `S1`: 8 bytes, alignment: 4 bytes
|
||||
print-type-size field `.tag`: 0 bytes
|
||||
print-type-size field `.x`: 4 bytes
|
||||
print-type-size field `.y`: 4 bytes
|
||||
print-type-size type: `Empty`: 0 bytes, alignment: 1 bytes
|
||||
print-type-size type: `Void`: 0 bytes, alignment: 1 bytes
|
Loading…
Reference in New Issue