Skip to content

Commit f48dc94

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

File tree

2 files changed

+16
-27
lines changed

2 files changed

+16
-27
lines changed

compiler/rustc_lint/src/types/improper_ctypes.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
825825
if let FfiUnsafe(explanations) = ffires_accumulator {
826826
// we assume the repr() of this ADT is either non-packed C or transparent.
827827
debug_assert!(
828-
def.repr().c()
828+
(def.repr().c() && !def.repr().packed())
829829
|| def.repr().transparent()
830830
|| def.repr().int.is_some()
831831
);
@@ -898,7 +898,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
898898
) -> FfiResult<'tcx> {
899899
debug_assert!(matches!(def.adt_kind(), AdtKind::Struct | AdtKind::Union));
900900

901-
if !def.repr().c() && !def.repr().transparent() {
901+
if !((def.repr().c() && !def.repr().packed()) || def.repr().transparent()) {
902+
// FIXME(ctypes) packed reprs prevent C compatibility, right?
902903
return FfiResult::new_with_reason(
903904
ty,
904905
if def.is_struct() {
@@ -974,7 +975,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
974975
}
975976
// Check for a repr() attribute to specify the size of the
976977
// discriminant.
977-
if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none() {
978+
if !(def.repr().c() && !def.repr().packed())
979+
&& !def.repr().transparent()
980+
&& def.repr().int.is_none()
981+
{
978982
// Special-case types like `Option<extern fn()>` and `Result<extern fn(), ()>`
979983
if let Some(inner_ty) = repr_nullable_ptr(self.cx.tcx, self.cx.typing_env(), ty) {
980984
return self.visit_type(state, Some(ty), inner_ty);
@@ -1365,22 +1369,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13651369
item: &'tcx hir::Item<'tcx>,
13661370
adt_def: AdtDef<'tcx>,
13671371
) {
1368-
let tcx = cx.tcx;
13691372
// repr(C) structs also with packed or aligned representation
13701373
// should be ignored.
1371-
if adt_def.repr().c()
1372-
&& !adt_def.repr().packed()
1373-
&& adt_def.repr().align.is_none()
1374-
&& tcx.sess.target.os == "aix"
1375-
&& !adt_def.all_fields().next().is_none()
1376-
{
1374+
debug_assert!(
1375+
adt_def.repr().c() && !adt_def.repr().packed() && adt_def.repr().align.is_none()
1376+
);
1377+
if cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() {
13771378
let struct_variant_data = item.expect_struct().2;
13781379
for field_def in struct_variant_data.fields().iter().skip(1) {
13791380
// Struct fields (after the first field) are checked for the
13801381
// power alignment rule, as fields after the first are likely
13811382
// to be the fields that are misaligned.
13821383
let def_id = field_def.def_id;
1383-
let ty = tcx.type_of(def_id).instantiate_identity();
1384+
let ty = cx.tcx.type_of(def_id).instantiate_identity();
13841385
if Self::check_arg_for_power_alignment(cx, ty) {
13851386
cx.emit_span_lint(USES_POWER_ALIGNMENT, field_def.span, UsesPowerAlignment);
13861387
}

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)