Skip to content

Commit 8f86951

Browse files
committed
ImproperCTypes: don't consider packed reprs
`[repr(C,packed)]` structs shouldn't be considered FFI-safe
1 parent 24adf70 commit 8f86951

File tree

2 files changed

+20
-27
lines changed

2 files changed

+20
-27
lines changed

compiler/rustc_lint/src/types/improper_ctypes.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
10161016
// takes priority over transparent_with_all_zst_fields
10171017
if let FfiUnsafe(explanations) = ffires_accumulator {
10181018
// we assume the repr() of this ADT is either non-packed C or transparent.
1019-
debug_assert!(def.repr().c() || def.repr().transparent() || def.repr().int.is_some());
1019+
debug_assert!(
1020+
(def.repr().c() && !def.repr().packed())
1021+
|| def.repr().transparent()
1022+
|| def.repr().int.is_some()
1023+
);
10201024

10211025
if def.repr().transparent() || matches!(def.adt_kind(), AdtKind::Enum) {
10221026
let field_ffires = FfiUnsafe(explanations).wrap_all(
@@ -1086,7 +1090,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
10861090
) -> FfiResult<'tcx> {
10871091
debug_assert!(matches!(def.adt_kind(), AdtKind::Struct | AdtKind::Union));
10881092

1089-
if !def.repr().c() && !def.repr().transparent() {
1093+
if !((def.repr().c() && !def.repr().packed()) || def.repr().transparent()) {
1094+
// FIXME(ctypes) packed reprs prevent C compatibility, right?
10901095
return FfiResult::new_with_reason(
10911096
ty,
10921097
if def.is_struct() {
@@ -1162,7 +1167,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
11621167
}
11631168
// Check for a repr() attribute to specify the size of the
11641169
// discriminant.
1165-
if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none() {
1170+
if !(def.repr().c() && !def.repr().packed())
1171+
&& !def.repr().transparent()
1172+
&& def.repr().int.is_none()
1173+
{
11661174
// Special-case types like `Option<extern fn()>` and `Result<extern fn(), ()>`
11671175
if let Some(inner_ty) = repr_nullable_ptr(self.cx.tcx, self.cx.typing_env(), ty) {
11681176
return self.visit_type(state, Some(ty), inner_ty);
@@ -1558,22 +1566,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
15581566
item: &'tcx hir::Item<'tcx>,
15591567
adt_def: AdtDef<'tcx>,
15601568
) {
1561-
let tcx = cx.tcx;
15621569
// repr(C) structs also with packed or aligned representation
15631570
// should be ignored.
1564-
if adt_def.repr().c()
1565-
&& !adt_def.repr().packed()
1566-
&& adt_def.repr().align.is_none()
1567-
&& tcx.sess.target.os == "aix"
1568-
&& !adt_def.all_fields().next().is_none()
1569-
{
1571+
debug_assert!(
1572+
adt_def.repr().c() && !adt_def.repr().packed() && adt_def.repr().align.is_none()
1573+
);
1574+
if cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() {
15701575
let struct_variant_data = item.expect_struct().2;
15711576
for field_def in struct_variant_data.fields().iter().skip(1) {
15721577
// Struct fields (after the first field) are checked for the
15731578
// power alignment rule, as fields after the first are likely
15741579
// to be the fields that are misaligned.
15751580
let def_id = field_def.def_id;
1576-
let ty = tcx.type_of(def_id).instantiate_identity();
1581+
let ty = cx.tcx.type_of(def_id).instantiate_identity();
15771582
if Self::check_arg_for_power_alignment(cx, ty) {
15781583
cx.emit_span_lint(USES_POWER_ALIGNMENT, field_def.span, UsesPowerAlignment);
15791584
}

tests/ui/lint/improper_ctypes/repr-rust-is-undefined.stderr

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,13 @@ error: `extern` block uses type `B`, which is not FFI-safe
2323
LL | fn bar(x: B);
2424
| ^ not FFI-safe
2525
|
26-
= note: this struct/enum/union (`B`) is FFI-unsafe due to a `A` field
26+
= help: consider adding a `#[repr(C)]` (not `#[repr(C,packed)]`) or `#[repr(transparent)]` attribute to `B`
27+
= note: `B` has unspecified layout
2728
note: the type is defined here
2829
--> $DIR/repr-rust-is-undefined.rs:13:1
2930
|
3031
LL | struct B {
3132
| ^^^^^^^^
32-
= help: consider adding a `#[repr(C)]` (not `#[repr(C,packed)]`) or `#[repr(transparent)]` attribute to `A`
33-
= note: `A` has unspecified layout
34-
note: the type is defined here
35-
--> $DIR/repr-rust-is-undefined.rs:8:1
36-
|
37-
LL | struct A {
38-
| ^^^^^^^^
3933

4034
error: `extern` block uses type `A`, which is not FFI-safe
4135
--> $DIR/repr-rust-is-undefined.rs:37:15
@@ -57,19 +51,13 @@ error: `extern` block uses type `B`, which is not FFI-safe
5751
LL | fn quux(x: B2);
5852
| ^^ not FFI-safe
5953
|
60-
= note: this struct/enum/union (`B`) is FFI-unsafe due to a `A` field
54+
= help: consider adding a `#[repr(C)]` (not `#[repr(C,packed)]`) or `#[repr(transparent)]` attribute to `B`
55+
= note: `B` has unspecified layout
6156
note: the type is defined here
6257
--> $DIR/repr-rust-is-undefined.rs:13:1
6358
|
6459
LL | struct B {
6560
| ^^^^^^^^
66-
= help: consider adding a `#[repr(C)]` (not `#[repr(C,packed)]`) or `#[repr(transparent)]` attribute to `A`
67-
= note: `A` has unspecified layout
68-
note: the type is defined here
69-
--> $DIR/repr-rust-is-undefined.rs:8:1
70-
|
71-
LL | struct A {
72-
| ^^^^^^^^
7361

7462
error: `extern` block uses type `D`, which is not FFI-safe
7563
--> $DIR/repr-rust-is-undefined.rs:40:16

0 commit comments

Comments
 (0)