From 3d7a6fee79a7a42ac69b185806733dbbd1fc664e Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Nov 2017 12:26:54 -0500 Subject: [PATCH] Prevent repr(C, u8) from triggering a warning on non-clike enums --- src/librustc/hir/check_attr.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 05c371113b4..003255f8796 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -75,7 +75,9 @@ impl<'a> CheckAttrVisitor<'a> { } }; - let mut conflicting_reprs = 0; + let mut int_reprs = 0; + let mut is_c = false; + let mut is_simd = false; for word in words { @@ -86,7 +88,7 @@ impl<'a> CheckAttrVisitor<'a> { let (message, label) = match &*name.as_str() { "C" => { - conflicting_reprs += 1; + is_c = true; if target != Target::Struct && target != Target::Union && target != Target::Enum { @@ -108,7 +110,7 @@ impl<'a> CheckAttrVisitor<'a> { } } "simd" => { - conflicting_reprs += 1; + is_simd = true; if target != Target::Struct { ("attribute should be applied to struct", "a struct") @@ -128,7 +130,7 @@ impl<'a> CheckAttrVisitor<'a> { "i8" | "u8" | "i16" | "u16" | "i32" | "u32" | "i64" | "u64" | "isize" | "usize" => { - conflicting_reprs += 1; + int_reprs += 1; if target != Target::Enum { ("attribute should be applied to enum", "an enum") @@ -142,7 +144,11 @@ impl<'a> CheckAttrVisitor<'a> { .span_label(item.span, format!("not {}", label)) .emit(); } - if conflicting_reprs > 1 { + + // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8) + if (int_reprs > 1) + || (is_simd && is_c) + || (int_reprs == 1 && is_c && is_c_like_enum(item)) { span_warn!(self.sess, attr.span, E0566, "conflicting representation hints"); } @@ -162,3 +168,17 @@ impl<'a> Visitor<'a> for CheckAttrVisitor<'a> { pub fn check_crate(sess: &Session, krate: &ast::Crate) { visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate); } + +fn is_c_like_enum(item: &ast::Item) -> bool { + if let ast::ItemKind::Enum(ref def, _) = item.node { + for variant in &def.variants { + match variant.node.data { + ast::VariantData::Unit(_) => { /* continue */ } + _ => { return false; } + } + } + true + } else { + false + } +}