about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-07-27 19:48:13 +0000
committerbors <bors@rust-lang.org>2017-07-27 19:48:13 +0000
commit52a3309695e82ed399c1a22b4e4fdde5d3aa0f3b (patch)
tree6b2401ce78e7cb509920cd53e9d40075928b232b
parent5cc1baa2900ab344e8e8386aa8314b59051868ca (diff)
parent5cccd6a9eeea380af4f8150b7afcdc9f15332abc (diff)
downloadrust-52a3309695e82ed399c1a22b4e4fdde5d3aa0f3b.tar.gz
rust-52a3309695e82ed399c1a22b4e4fdde5d3aa0f3b.zip
Auto merge of #43443 - bitshifter:issue-43317, r=nikomatsakis
Improve checking of conflicting packed and align representation hints on structs and unions.

Fixes #43317 and improves #33626.
-rw-r--r--src/librustc/diagnostics.rs1
-rw-r--r--src/librustc/hir/check_attr.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs22
-rw-r--r--src/librustc_typeck/diagnostics.rs1
-rw-r--r--src/test/compile-fail/conflicting-repr-hints.rs29
-rw-r--r--src/test/compile-fail/repr-packed-contains-align.rs44
6 files changed, 81 insertions, 24 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index b52224eb5d7..3ce39b23b0f 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -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
 }
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index e4b1cdabb04..946cbb7960b 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -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 {
 
@@ -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
                     }
                 }
@@ -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",
@@ -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();
-        }
     }
 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 3c570d85147..7f69885047b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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>,
@@ -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) {
@@ -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();
+        }
     }
 }
 
@@ -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;
             }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 1e26a734e76..60f32408abb 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -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)
diff --git a/src/test/compile-fail/conflicting-repr-hints.rs b/src/test/compile-fail/conflicting-repr-hints.rs
index 01fa3ffbaa6..12ac8fb57b1 100644
--- a/src/test/compile-fail/conflicting-repr-hints.rs
+++ b/src/test/compile-fail/conflicting-repr-hints.rs
@@ -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() {}
diff --git a/src/test/compile-fail/repr-packed-contains-align.rs b/src/test/compile-fail/repr-packed-contains-align.rs
index c584dcf3e59..78d43064ea3 100644
--- a/src/test/compile-fail/repr-packed-contains-align.rs
+++ b/src/test/compile-fail/repr-packed-contains-align.rs
@@ -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() {}