From 42b75a5c18463b4fef98267663fab13d265eac3e Mon Sep 17 00:00:00 2001 From: Chris Wong Date: Sun, 3 Jul 2016 15:24:27 +1200 Subject: [PATCH] Warn about multiple conflicting #[repr] hints Closes #34622 --- src/librustc/diagnostics.rs | 1 + src/librustc/hir/check_attr.rs | 19 +++++++++++- src/libsyntax/attr.rs | 5 ++-- .../compile-fail/conflicting-repr-hints.rs | 30 +++++++++++++++++++ src/test/run-pass/mir_adt_construction.rs | 2 +- 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/conflicting-repr-hints.rs diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 38c60a0b7c7c1..de68cc707ad7a 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1804,4 +1804,5 @@ register_diagnostics! { E0490, // a value of type `..` is borrowed for too long E0491, // in type `..`, reference has a longer lifetime than the data it... E0495, // cannot infer an appropriate lifetime due to conflicting requirements + E0566 // conflicting representation hints } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 21143f93a7da8..53624702c848b 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -52,6 +52,7 @@ impl<'a> CheckAttrVisitor<'a> { } }; + let mut conflicting_reprs = 0; for word in words { let name = match word.name() { Some(word) => word, @@ -60,13 +61,24 @@ impl<'a> CheckAttrVisitor<'a> { let message = match &*name { "C" => { + conflicting_reprs += 1; if target != Target::Struct && target != Target::Enum { "attribute should be applied to struct or enum" } else { continue } } - "packed" | "simd" => { + "packed" => { + // Do not increment conflicting_reprs here, because "packed" + // can be used to modify another repr hint + if target != Target::Struct { + "attribute should be applied to struct" + } else { + continue + } + } + "simd" => { + conflicting_reprs += 1; if target != Target::Struct { "attribute should be applied to struct" } else { @@ -76,6 +88,7 @@ impl<'a> CheckAttrVisitor<'a> { "i8" | "u8" | "i16" | "u16" | "i32" | "u32" | "i64" | "u64" | "isize" | "usize" => { + conflicting_reprs += 1; if target != Target::Enum { "attribute should be applied to enum" } else { @@ -87,6 +100,10 @@ impl<'a> CheckAttrVisitor<'a> { span_err!(self.sess, attr.span, E0517, "{}", message); } + if conflicting_reprs > 1 { + span_warn!(self.sess, attr.span, E0566, + "conflicting representation hints"); + } } fn check_attribute(&self, attr: &ast::Attribute, target: Target) { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 6060ff529f215..703f3f7adf910 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -904,9 +904,8 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec } }; - match hint { - Some(h) => acc.push(h), - None => { } + if let Some(h) = hint { + acc.push(h); } } else { span_err!(diagnostic, item.span, E0553, diff --git a/src/test/compile-fail/conflicting-repr-hints.rs b/src/test/compile-fail/conflicting-repr-hints.rs new file mode 100644 index 0000000000000..9e0c0d845ca24 --- /dev/null +++ b/src/test/compile-fail/conflicting-repr-hints.rs @@ -0,0 +1,30 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +#[repr(C)] +enum A { A } + +#[repr(u64)] +enum B { B } + +#[repr(C, u64)] //~ WARNING conflicting representation hints +enum C { C } + +#[repr(u32, u64)] //~ WARNING conflicting representation hints +enum D { D } + +#[repr(C, packed)] +struct E(i32); + +#[rustc_error] +fn main() {} //~ ERROR compilation successful diff --git a/src/test/run-pass/mir_adt_construction.rs b/src/test/run-pass/mir_adt_construction.rs index dae843bba9fa6..6b47721ab4b32 100644 --- a/src/test/run-pass/mir_adt_construction.rs +++ b/src/test/run-pass/mir_adt_construction.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[repr(C, u32)] +#[repr(C)] enum CEnum { Hello = 30, World = 60