Skip to content

Commit 3c46b41

Browse files
committed
ImproperCTypes: don't consider packed reprs
1 parent 18ddb65 commit 3c46b41

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
@@ -811,7 +811,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
811811
if let FfiUnsafe(explanations) = ffires_accumulator {
812812
// we assume the repr() of this ADT is either non-packed C or transparent.
813813
debug_assert!(
814-
def.repr().c()
814+
(def.repr().c() && !def.repr().packed())
815815
|| def.repr().transparent()
816816
|| def.repr().int.is_some()
817817
);
@@ -884,7 +884,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
884884
) -> FfiResult<'tcx> {
885885
debug_assert!(matches!(def.adt_kind(), AdtKind::Struct | AdtKind::Union));
886886

887-
if !def.repr().c() && !def.repr().transparent() {
887+
if !((def.repr().c() && !def.repr().packed()) || def.repr().transparent()) {
888+
// FIXME(ctypes) packed reprs prevent C compatibility, right?
888889
return FfiResult::new_with_reason(
889890
ty,
890891
if def.is_struct() {
@@ -960,7 +961,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
960961
}
961962
// Check for a repr() attribute to specify the size of the
962963
// discriminant.
963-
if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none() {
964+
if !(def.repr().c() && !def.repr().packed())
965+
&& !def.repr().transparent()
966+
&& def.repr().int.is_none()
967+
{
964968
// Special-case types like `Option<extern fn()>` and `Result<extern fn(), ()>`
965969
if let Some(inner_ty) = repr_nullable_ptr(self.cx.tcx, self.cx.typing_env(), ty) {
966970
return self.visit_type(state, Some(ty), inner_ty);
@@ -1351,22 +1355,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13511355
item: &'tcx hir::Item<'tcx>,
13521356
adt_def: AdtDef<'tcx>,
13531357
) {
1354-
let tcx = cx.tcx;
13551358
// repr(C) structs also with packed or aligned representation
13561359
// should be ignored.
1357-
if adt_def.repr().c()
1358-
&& !adt_def.repr().packed()
1359-
&& adt_def.repr().align.is_none()
1360-
&& tcx.sess.target.os == "aix"
1361-
&& !adt_def.all_fields().next().is_none()
1362-
{
1360+
debug_assert!(
1361+
adt_def.repr().c() && !adt_def.repr().packed() && adt_def.repr().align.is_none()
1362+
);
1363+
if cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() {
13631364
let struct_variant_data = item.expect_struct().2;
13641365
for field_def in struct_variant_data.fields().iter().skip(1) {
13651366
// Struct fields (after the first field) are checked for the
13661367
// power alignment rule, as fields after the first are likely
13671368
// to be the fields that are misaligned.
13681369
let def_id = field_def.def_id;
1369-
let ty = tcx.type_of(def_id).instantiate_identity();
1370+
let ty = cx.tcx.type_of(def_id).instantiate_identity();
13701371
if Self::check_arg_for_power_alignment(cx, ty) {
13711372
cx.emit_span_lint(USES_POWER_ALIGNMENT, field_def.span, UsesPowerAlignment);
13721373
}

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)