Skip to content

Improve checking of conflicting packed and align representation hints on structs and unions. #43443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2025,5 +2025,4 @@ register_diagnostics! {
E0490, // a value of type `..` is borrowed for too long
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
E0566, // conflicting representation hints
E0587, // conflicting packed and align representation hints
}
8 changes: 0 additions & 8 deletions src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ impl<'a> CheckAttrVisitor<'a> {
};

let mut conflicting_reprs = 0;
let mut found_packed = false;
let mut found_align = false;

for word in words {

Expand Down Expand Up @@ -106,7 +104,6 @@ impl<'a> CheckAttrVisitor<'a> {
("attribute should be applied to struct or union",
"a struct or union")
} else {
found_packed = true;
continue
}
}
Expand All @@ -120,7 +117,6 @@ impl<'a> CheckAttrVisitor<'a> {
}
}
"align" => {
found_align = true;
if target != Target::Struct &&
target != Target::Union {
("attribute should be applied to struct or union",
Expand Down Expand Up @@ -150,10 +146,6 @@ impl<'a> CheckAttrVisitor<'a> {
span_warn!(self.sess, attr.span, E0566,
"conflicting representation hints");
}
if found_align && found_packed {
struct_span_err!(self.sess, attr.span, E0587,
"conflicting packed and align representation hints").emit();
}
}
}

Expand Down
22 changes: 13 additions & 9 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1063,11 +1063,7 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
check_simd(tcx, span, def_id);
}

// if struct is packed and not aligned, check fields for alignment.
// Checks for combining packed and align attrs on single struct are done elsewhere.
if tcx.adt_def(def_id).repr.packed() && tcx.adt_def(def_id).repr.align == 0 {
check_packed(tcx, span, def_id);
}
check_packed(tcx, span, def_id);
}

fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Expand All @@ -1077,6 +1073,8 @@ fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);

check_packed(tcx, span, def_id);
}

pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) {
Expand Down Expand Up @@ -1478,9 +1476,15 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
}

fn check_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
if check_packed_inner(tcx, def_id, &mut Vec::new()) {
struct_span_err!(tcx.sess, sp, E0588,
"packed struct cannot transitively contain a `[repr(align)]` struct").emit();
if tcx.adt_def(def_id).repr.packed() {
if tcx.adt_def(def_id).repr.align > 0 {
struct_span_err!(tcx.sess, sp, E0587,
"type has conflicting packed and align representation hints").emit();
}
else if check_packed_inner(tcx, def_id, &mut Vec::new()) {
struct_span_err!(tcx.sess, sp, E0588,
"packed type cannot transitively contain a `[repr(align)]` type").emit();
}
}
}

Expand All @@ -1493,7 +1497,7 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
return false;
}
match t.sty {
ty::TyAdt(def, substs) if def.is_struct() => {
ty::TyAdt(def, substs) if def.is_struct() || def.is_union() => {
if tcx.adt_def(def.did).repr.align > 0 {
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4663,6 +4663,7 @@ register_diagnostics! {
// but `{}` was found in the type `{}`
E0567, // auto traits can not have type parameters
E0568, // auto-traits can not have predicates,
E0587, // struct has conflicting packed and align representation hints
E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
E0592, // duplicate definitions with name `{}`
// E0613, // Removed (merged with E0609)
Expand Down
29 changes: 27 additions & 2 deletions src/test/compile-fail/conflicting-repr-hints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,32 @@ enum D { D }
#[repr(C, packed)]
struct E(i32);

#[repr(packed, align(8))] //~ ERROR conflicting packed and align representation hints
struct F(i32);
#[repr(packed, align(8))]
struct F(i32); //~ ERROR type has conflicting packed and align representation hints

#[repr(packed)]
#[repr(align(8))]
struct G(i32); //~ ERROR type has conflicting packed and align representation hints

#[repr(align(8))]
#[repr(packed)]
struct H(i32); //~ ERROR type has conflicting packed and align representation hints

#[repr(packed, align(8))]
union X { //~ ERROR type has conflicting packed and align representation hints
i: i32
}

#[repr(packed)]
#[repr(align(8))]
union Y { //~ ERROR type has conflicting packed and align representation hints
i: i32
}

#[repr(align(8))]
#[repr(packed)]
union Z { //~ ERROR type has conflicting packed and align representation hints
i: i32
}

fn main() {}
44 changes: 40 additions & 4 deletions src/test/compile-fail/repr-packed-contains-align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,53 @@
// except according to those terms.
#![feature(attr_literals)]
#![feature(repr_align)]
#![feature(untagged_unions)]
#![allow(dead_code)]

#[repr(align(16))]
struct A(i32);
struct SA(i32);

struct B(A);
struct SB(SA);

#[repr(align(16))]
union UA {
i: i32
}

union UB {
a: UA
}

#[repr(packed)]
struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type

#[repr(packed)]
struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type

#[repr(packed)]
struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type

#[repr(packed)]
struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type

#[repr(packed)]
union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
a: UA
}

#[repr(packed)]
union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
n: UB
}

#[repr(packed)]
struct C(A); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct
union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
a: SA
}

#[repr(packed)]
struct D(B); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct
union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
n: SB
}

fn main() {}