From ecb10bf95dab635a8896f5aed215000166ee0de2 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Thu, 3 Jun 2021 22:17:35 +0200 Subject: [PATCH 1/2] Fix `repr(...)` validation ICE Includes minor refactor and more helpful errors in case of incorrect repr attributes --- compiler/rustc_attr/src/builtin.rs | 234 ++++++++++++++++++---------- src/test/ui/repr/basic.rs | 69 +++++++++ src/test/ui/repr/basic.stderr | 238 +++++++++++++++++++++++++++++ 3 files changed, 463 insertions(+), 78 deletions(-) create mode 100644 src/test/ui/repr/basic.rs create mode 100644 src/test/ui/repr/basic.stderr diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 20971ebb95748..0b2273fa1aef7 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -2,7 +2,7 @@ use rustc_ast::{self as ast, Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem}; use rustc_ast_pretty::pprust; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_err, Applicability, Handler}; use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg}; use rustc_macros::HashStable_Generic; use rustc_session::parse::{feature_err, ParseSess}; @@ -827,6 +827,150 @@ pub enum ReprAttr { ReprNoNiche, } +impl ReprAttr { + fn try_from_meta_item( + diagnostic: &Handler, + item: &MetaItem, + ) -> Result, /* invalid attr */ ()> { + use ReprAttr::*; + let name = item.name_or_empty(); + let expect_no_args = || { + if !item.is_word() { + struct_span_err!( + diagnostic, + item.span, + E0589, + "invalid `repr({})` attribute: no arguments expected", + name, + ) + .span_suggestion( + item.path.span.shrink_to_hi().to(item.span.shrink_to_hi()), + "remove additional values", + format!("{}", name), + Applicability::MachineApplicable, + ) + .emit(); + } + }; + let expect_one_int_arg = || { + if let MetaItemKind::NameValue(ref value) = item.kind { + let mut err = struct_span_err!( + diagnostic, + item.span, + E0693, + "incorrect `repr({})` attribute format", + name + ); + match value.kind { + ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { + err.span_suggestion( + item.span, + "use parentheses instead", + format!("{}({})", name, int), + Applicability::MachineApplicable, + ); + } + ast::LitKind::Str(s, _) => { + err.span_suggestion( + item.span, + "use parentheses instead", + format!("{}({})", name, s), + Applicability::MachineApplicable, + ); + } + _ => {} + } + err.emit(); + } else if item.is_word() || matches!(item.meta_item_list(), Some([])) { + struct_span_err!( + diagnostic, + item.span, + E0693, + "invalid `repr({})` attribute: expected a value", + name + ) + .span_suggestion( + item.span, + "add a value", + format!("{}(/* value */)", name), + Applicability::HasPlaceholders, + ) + .emit(); + } else if let Some([NestedMetaItem::Literal(value)]) = item.meta_item_list() { + match parse_alignment(&value.kind) { + Ok(literal) => return Some(literal), + Err(message) => { + struct_span_err!( + diagnostic, + item.span, + E0589, + "invalid `repr({})` attribute: {}", + name, + message + ) + .emit(); + } + }; + } else if let Some([first_meta, .., last_meta]) = item.meta_item_list() { + struct_span_err!( + diagnostic, + item.span, + E0693, + "invalid `repr({})` attribute: expected only one value", + item.name_or_empty(), + ) + .span_label(first_meta.span().to(last_meta.span()), "only one argument expected") + .emit(); + } + return None; + }; + // Every possible repr variant must be covered here or else an ICE will occur + Ok(Some(match name { + sym::C => { + expect_no_args(); + ReprC + } + sym::simd => { + expect_no_args(); + ReprSimd + } + sym::transparent => { + expect_no_args(); + ReprTransparent + } + sym::no_niche => { + expect_no_args(); + ReprNoNiche + } + sym::align => { + if let Some(arg) = expect_one_int_arg() { + ReprAlign(arg) + } else { + return Ok(None); + } + } + sym::packed => { + if item.is_word() { + ReprPacked(1) + } else if let Some(arg) = expect_one_int_arg() { + ReprPacked(arg) + } else { + return Ok(None); + } + } + name => { + if let Some(ty) = int_type_of_word(name) { + expect_no_args(); + ReprInt(ty) + } else { + // Unrecognized repr attr + return Err(()); + } + } + })) + } +} + #[derive(Eq, PartialEq, Debug, Copy, Clone)] #[derive(Encodable, Decodable, HashStable_Generic)] pub enum IntType { @@ -846,7 +990,7 @@ impl IntType { } } -/// Parse #[repr(...)] forms. +/// Parse `#[repr(...)]` forms. /// /// Valid repr contents: any of the primitive integral type names (see /// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use @@ -854,90 +998,24 @@ impl IntType { /// structure layout, `packed` to remove padding, and `transparent` to elegate representation /// concerns to the only non-ZST field. pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { - use ReprAttr::*; - let mut acc = Vec::new(); let diagnostic = &sess.parse_sess.span_diagnostic; if attr.has_name(sym::repr) { if let Some(items) = attr.meta_item_list() { sess.mark_attr_used(attr); for item in items { - let mut recognised = false; - if item.is_word() { - let hint = match item.name_or_empty() { - sym::C => Some(ReprC), - sym::packed => Some(ReprPacked(1)), - sym::simd => Some(ReprSimd), - sym::transparent => Some(ReprTransparent), - sym::no_niche => Some(ReprNoNiche), - name => int_type_of_word(name).map(ReprInt), - }; - - if let Some(h) = hint { - recognised = true; - acc.push(h); + match item + .meta_item() + .ok_or(()) + .and_then(|item| ReprAttr::try_from_meta_item(diagnostic, &item)) + { + Ok(None) => { + // Recognized attribute, but failed to parse (e.g. align() or packed(1, 2, 3)) } - } else if let Some((name, value)) = item.name_value_literal() { - let mut literal_error = None; - if name == sym::align { - recognised = true; - match parse_alignment(&value.kind) { - Ok(literal) => acc.push(ReprAlign(literal)), - Err(message) => literal_error = Some(message), - }; - } else if name == sym::packed { - recognised = true; - match parse_alignment(&value.kind) { - Ok(literal) => acc.push(ReprPacked(literal)), - Err(message) => literal_error = Some(message), - }; + Ok(Some(attr)) => acc.push(attr), + Err(()) => { + diagnostic.delay_span_bug(item.span(), "unrecognized representation hint") } - if let Some(literal_error) = literal_error { - struct_span_err!( - diagnostic, - item.span(), - E0589, - "invalid `repr(align)` attribute: {}", - literal_error - ) - .emit(); - } - } else if let Some(meta_item) = item.meta_item() { - if meta_item.has_name(sym::align) { - if let MetaItemKind::NameValue(ref value) = meta_item.kind { - recognised = true; - let mut err = struct_span_err!( - diagnostic, - item.span(), - E0693, - "incorrect `repr(align)` attribute format" - ); - match value.kind { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("align({})", int), - Applicability::MachineApplicable, - ); - } - ast::LitKind::Str(s, _) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("align({})", s), - Applicability::MachineApplicable, - ); - } - _ => {} - } - err.emit(); - } - } - } - if !recognised { - // Not a word we recognize - diagnostic.delay_span_bug(item.span(), "unrecognized representation hint"); } } } diff --git a/src/test/ui/repr/basic.rs b/src/test/ui/repr/basic.rs new file mode 100644 index 0000000000000..df7357bb88e1a --- /dev/null +++ b/src/test/ui/repr/basic.rs @@ -0,0 +1,69 @@ +#![feature(repr_simd)] +#![feature(no_niche)] + +#[repr(transparent())] //~ ERROR invalid `repr(transparent)` attribute: no arguments expected + //~| ERROR invalid `repr(transparent)` attribute: no arguments expected +struct S0(u32); + +#[repr(transparent(1, 2, 3))] //~ ERROR invalid `repr(transparent)` attribute: no arguments expected + //~| ERROR invalid `repr(transparent)` attribute: no arguments expected +struct S1(u32); + +#[repr(C())] //~ ERROR invalid `repr(C)` attribute: no arguments expected + //~| ERROR invalid `repr(C)` attribute: no arguments expected +struct S2(u32); + +#[repr(C(1, 2, 3))] //~ ERROR invalid `repr(C)` attribute: no arguments expected + //~| ERROR invalid `repr(C)` attribute: no arguments expected +struct S3(u32); + +#[repr(simd())] //~ ERROR invalid `repr(simd)` attribute: no arguments expected + //~| ERROR invalid `repr(simd)` attribute: no arguments expected +struct S4(u32); + +#[repr(simd(1, 2, 3))] //~ ERROR invalid `repr(simd)` attribute: no arguments expected + //~| ERROR invalid `repr(simd)` attribute: no arguments expected +struct S5(u32); + +#[repr(no_niche())] //~ ERROR invalid `repr(no_niche)` attribute: no arguments expected + //~| ERROR invalid `repr(no_niche)` attribute: no arguments expected +struct S6(u32); + +#[repr(no_niche(1, 2, 3))] //~ ERROR invalid `repr(no_niche)` attribute: no arguments expected + //~| ERROR invalid `repr(no_niche)` attribute: no arguments expected +struct S7(u32); + +#[repr(align())] //~ ERROR invalid `repr(align)` attribute: expected a value + //~| ERROR invalid `repr(align)` attribute: expected a value +struct S8(u32); + +#[repr(align(1, 2, 3))] //~ ERROR invalid `repr(align)` attribute: expected only one value + //~| ERROR invalid `repr(align)` attribute: expected only one value +struct S9(u32); + +#[repr(packed())] //~ ERROR invalid `repr(packed)` attribute: expected a value + //~| ERROR invalid `repr(packed)` attribute: expected a value +struct S10(u32); + +#[repr(packed(1, 2, 3))] //~ ERROR invalid `repr(packed)` attribute: expected only one value + //~| ERROR invalid `repr(packed)` attribute: expected only one value +struct S11(u32); + +#[repr(i8())] //~ ERROR invalid `repr(i8)` attribute: no arguments expected + //~| ERROR invalid `repr(i8)` attribute: no arguments expected +enum S12 { A, B } + +#[repr(i8(1, 2, 3))] //~ ERROR invalid `repr(i8)` attribute: no arguments expected + //~| ERROR invalid `repr(i8)` attribute: no arguments expected +enum S13 { A, B } + +#[repr] //~ ERROR malformed `repr` attribute input +struct S14(u32); + +#[repr(123)] //~ ERROR meta item in `repr` must be an identifier +struct S15(u32); + +#[repr("foo")] //~ ERROR meta item in `repr` must be an identifier +struct S16(u32); + +fn main() {} diff --git a/src/test/ui/repr/basic.stderr b/src/test/ui/repr/basic.stderr new file mode 100644 index 0000000000000..57eba736d7206 --- /dev/null +++ b/src/test/ui/repr/basic.stderr @@ -0,0 +1,238 @@ +error: malformed `repr` attribute input + --> $DIR/basic.rs:60:1 + | +LL | #[repr] + | ^^^^^^^ help: must be of the form: `#[repr(C)]` + +error[E0589]: invalid `repr(transparent)` attribute: no arguments expected + --> $DIR/basic.rs:4:8 + | +LL | #[repr(transparent())] + | ^^^^^^^^^^^-- + | | + | help: remove additional values: `transparent` + +error[E0589]: invalid `repr(transparent)` attribute: no arguments expected + --> $DIR/basic.rs:8:8 + | +LL | #[repr(transparent(1, 2, 3))] + | ^^^^^^^^^^^--------- + | | + | help: remove additional values: `transparent` + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/basic.rs:12:8 + | +LL | #[repr(C())] + | ^-- + | | + | help: remove additional values: `C` + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/basic.rs:16:8 + | +LL | #[repr(C(1, 2, 3))] + | ^--------- + | | + | help: remove additional values: `C` + +error[E0589]: invalid `repr(simd)` attribute: no arguments expected + --> $DIR/basic.rs:20:8 + | +LL | #[repr(simd())] + | ^^^^-- + | | + | help: remove additional values: `simd` + +error[E0589]: invalid `repr(simd)` attribute: no arguments expected + --> $DIR/basic.rs:24:8 + | +LL | #[repr(simd(1, 2, 3))] + | ^^^^--------- + | | + | help: remove additional values: `simd` + +error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected + --> $DIR/basic.rs:28:8 + | +LL | #[repr(no_niche())] + | ^^^^^^^^-- + | | + | help: remove additional values: `no_niche` + +error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected + --> $DIR/basic.rs:32:8 + | +LL | #[repr(no_niche(1, 2, 3))] + | ^^^^^^^^--------- + | | + | help: remove additional values: `no_niche` + +error[E0693]: invalid `repr(align)` attribute: expected a value + --> $DIR/basic.rs:36:8 + | +LL | #[repr(align())] + | ^^^^^^^ help: add a value: `align(/* value */)` + +error[E0693]: invalid `repr(align)` attribute: expected only one value + --> $DIR/basic.rs:40:8 + | +LL | #[repr(align(1, 2, 3))] + | ^^^^^^-------^ + | | + | only one argument expected + +error[E0693]: invalid `repr(packed)` attribute: expected a value + --> $DIR/basic.rs:44:8 + | +LL | #[repr(packed())] + | ^^^^^^^^ help: add a value: `packed(/* value */)` + +error[E0693]: invalid `repr(packed)` attribute: expected only one value + --> $DIR/basic.rs:48:8 + | +LL | #[repr(packed(1, 2, 3))] + | ^^^^^^^-------^ + | | + | only one argument expected + +error[E0589]: invalid `repr(i8)` attribute: no arguments expected + --> $DIR/basic.rs:52:8 + | +LL | #[repr(i8())] + | ^^-- + | | + | help: remove additional values: `i8` + +error[E0589]: invalid `repr(i8)` attribute: no arguments expected + --> $DIR/basic.rs:56:8 + | +LL | #[repr(i8(1, 2, 3))] + | ^^--------- + | | + | help: remove additional values: `i8` + +error[E0565]: meta item in `repr` must be an identifier + --> $DIR/basic.rs:63:8 + | +LL | #[repr(123)] + | ^^^ + +error[E0565]: meta item in `repr` must be an identifier + --> $DIR/basic.rs:66:8 + | +LL | #[repr("foo")] + | ^^^^^ + +error[E0589]: invalid `repr(transparent)` attribute: no arguments expected + --> $DIR/basic.rs:4:8 + | +LL | #[repr(transparent())] + | ^^^^^^^^^^^-- + | | + | help: remove additional values: `transparent` + +error[E0589]: invalid `repr(transparent)` attribute: no arguments expected + --> $DIR/basic.rs:8:8 + | +LL | #[repr(transparent(1, 2, 3))] + | ^^^^^^^^^^^--------- + | | + | help: remove additional values: `transparent` + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/basic.rs:12:8 + | +LL | #[repr(C())] + | ^-- + | | + | help: remove additional values: `C` + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/basic.rs:16:8 + | +LL | #[repr(C(1, 2, 3))] + | ^--------- + | | + | help: remove additional values: `C` + +error[E0589]: invalid `repr(simd)` attribute: no arguments expected + --> $DIR/basic.rs:20:8 + | +LL | #[repr(simd())] + | ^^^^-- + | | + | help: remove additional values: `simd` + +error[E0589]: invalid `repr(simd)` attribute: no arguments expected + --> $DIR/basic.rs:24:8 + | +LL | #[repr(simd(1, 2, 3))] + | ^^^^--------- + | | + | help: remove additional values: `simd` + +error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected + --> $DIR/basic.rs:28:8 + | +LL | #[repr(no_niche())] + | ^^^^^^^^-- + | | + | help: remove additional values: `no_niche` + +error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected + --> $DIR/basic.rs:32:8 + | +LL | #[repr(no_niche(1, 2, 3))] + | ^^^^^^^^--------- + | | + | help: remove additional values: `no_niche` + +error[E0693]: invalid `repr(align)` attribute: expected a value + --> $DIR/basic.rs:36:8 + | +LL | #[repr(align())] + | ^^^^^^^ help: add a value: `align(/* value */)` + +error[E0693]: invalid `repr(align)` attribute: expected only one value + --> $DIR/basic.rs:40:8 + | +LL | #[repr(align(1, 2, 3))] + | ^^^^^^-------^ + | | + | only one argument expected + +error[E0693]: invalid `repr(packed)` attribute: expected a value + --> $DIR/basic.rs:44:8 + | +LL | #[repr(packed())] + | ^^^^^^^^ help: add a value: `packed(/* value */)` + +error[E0693]: invalid `repr(packed)` attribute: expected only one value + --> $DIR/basic.rs:48:8 + | +LL | #[repr(packed(1, 2, 3))] + | ^^^^^^^-------^ + | | + | only one argument expected + +error[E0589]: invalid `repr(i8)` attribute: no arguments expected + --> $DIR/basic.rs:52:8 + | +LL | #[repr(i8())] + | ^^-- + | | + | help: remove additional values: `i8` + +error[E0589]: invalid `repr(i8)` attribute: no arguments expected + --> $DIR/basic.rs:56:8 + | +LL | #[repr(i8(1, 2, 3))] + | ^^--------- + | | + | help: remove additional values: `i8` + +error: aborting due to 31 previous errors + +Some errors have detailed explanations: E0565, E0589, E0693. +For more information about an error, try `rustc --explain E0565`. From a6393f93ce4689a1a54e6a61416d7476468dda11 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Sun, 6 Jun 2021 16:21:44 +0200 Subject: [PATCH 2/2] Expand `repr(...)` diagnostics --- compiler/rustc_ast/src/ast.rs | 18 ++ compiler/rustc_attr/src/builtin.rs | 182 +++++++++--- compiler/rustc_typeck/src/collect.rs | 35 +-- src/test/ui/repr/basic.rs | 45 ++- src/test/ui/repr/basic.stderr | 342 ++++++++++++++++------ src/test/ui/repr/repr-align-assign.fixed | 4 +- src/test/ui/repr/repr-align-assign.stderr | 28 +- src/test/ui/repr/repr-align.rs | 24 +- src/test/ui/repr/repr-align.stderr | 72 ++--- src/test/ui/repr/rustfix.fixed | 30 ++ src/test/ui/repr/rustfix.rs | 30 ++ src/test/ui/repr/rustfix.stderr | 162 ++++++++++ 12 files changed, 765 insertions(+), 207 deletions(-) create mode 100644 src/test/ui/repr/rustfix.fixed create mode 100644 src/test/ui/repr/rustfix.rs create mode 100644 src/test/ui/repr/rustfix.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b3bac1d7ecdef..073ce18ce90c3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1552,6 +1552,24 @@ pub enum StrStyle { Raw(u16), } +impl StrStyle { + /// Actual string data offset from the start of [Lit] span + pub fn prefix_len(self) -> u32 { + match self { + Self::Cooked => 1, + Self::Raw(n) => u32::from(n) + 2, // r#" is 1 + `#` count long + 1 + } + } + + /// Actual string data offset from the end of [Lit] span + pub fn suffix_len(self) -> u32 { + match self { + Self::Cooked => 1, + Self::Raw(n) => u32::from(n) + 1, // no starting `r` is present, only add 1 + } + } +} + /// An AST literal. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct Lit { diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 0b2273fa1aef7..a8008a4f646f9 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -8,7 +8,7 @@ use rustc_macros::HashStable_Generic; use rustc_session::parse::{feature_err, ParseSess}; use rustc_session::Session; use rustc_span::hygiene::Transparency; -use rustc_span::{symbol::sym, symbol::Symbol, Span}; +use rustc_span::{symbol::sym, symbol::Symbol, BytePos, Span}; use std::num::NonZeroU32; pub fn is_builtin_attr(attr: &Attribute) -> bool { @@ -843,10 +843,10 @@ impl ReprAttr { "invalid `repr({})` attribute: no arguments expected", name, ) - .span_suggestion( + .span_suggestion_verbose( item.path.span.shrink_to_hi().to(item.span.shrink_to_hi()), "remove additional values", - format!("{}", name), + String::new(), Applicability::MachineApplicable, ) .emit(); @@ -862,23 +862,74 @@ impl ReprAttr { name ); match value.kind { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - err.span_suggestion( - item.span, + ast::LitKind::Int(_int, ast::LitIntType::Unsuffixed) => { + let open_paren_span = + item.path.span.shrink_to_hi().to(value.span.shrink_to_lo()); + let close_paren_span = + item.span.shrink_to_hi().to(value.span.shrink_to_hi()); + + err.multipart_suggestion( "use parentheses instead", - format!("{}({})", name, int), + vec![ + (open_paren_span, "(".to_string()), + (close_paren_span, ")".to_string()), + ], Applicability::MachineApplicable, ); } - ast::LitKind::Str(s, _) => { - err.span_suggestion( - item.span, - "use parentheses instead", - format!("{}({})", name, s), - Applicability::MachineApplicable, - ); + ast::LitKind::Str(str, style) => { + // repr(foo = "123" ) + // ^^^ ^ + let open_paren_span = + item.path.span.shrink_to_hi().to(value.span.shrink_to_lo()); + let close_paren_span = + item.span.shrink_to_hi().to(value.span.shrink_to_hi()); + // repr(foo = "123" ) + // ^^^^ ^^ + // BytePos math is safe because strings can only be surrounded by single + // byte characters (`r`, `#`, and `"` are all one byte) + let open_paren_span = open_paren_span + .with_hi(open_paren_span.hi() + BytePos(style.prefix_len())); + let close_paren_span = close_paren_span + .with_hi(close_paren_span.lo() - BytePos(style.suffix_len())); + + if str.is_empty() { + // When encountering repr(foo = "") suggest additional help + err.span_suggestion_verbose( + open_paren_span.to(close_paren_span), + "use parentheses instead and add a value", + "(/* value */)".to_string(), + Applicability::HasPlaceholders, + ); + } else { + err.multipart_suggestion( + "use parentheses instead", + vec![ + (open_paren_span, "(".to_string()), + (close_paren_span, ")".to_string()), + ], + Applicability::MachineApplicable, + ); + + match str.as_str().parse::() { + Ok(num) => match is_alignment_valid(num) { + Ok(align) => { + err.emit(); + return Some(align); + } + Err(msg) => { + err.span_label(value.span, msg); + } + }, + Err(_) => { + err.span_label(value.span, "must be a non-negative number"); + } + } + } + } + _ => { + err.span_label(value.span, "must be a non-negative number"); } - _ => {} } err.emit(); } else if item.is_word() || matches!(item.meta_item_list(), Some([])) { @@ -886,31 +937,32 @@ impl ReprAttr { diagnostic, item.span, E0693, - "invalid `repr({})` attribute: expected a value", + "invalid `repr({})` attribute: expected a non-negative number", name ) - .span_suggestion( - item.span, + .span_suggestion_verbose( + item.path.span.shrink_to_hi().to(item.span.shrink_to_hi()), "add a value", - format!("{}(/* value */)", name), + "(/* value */)".to_string(), Applicability::HasPlaceholders, ) .emit(); - } else if let Some([NestedMetaItem::Literal(value)]) = item.meta_item_list() { - match parse_alignment(&value.kind) { - Ok(literal) => return Some(literal), - Err(message) => { - struct_span_err!( - diagnostic, - item.span, - E0589, - "invalid `repr({})` attribute: {}", - name, - message - ) - .emit(); + } else if let Some([meta]) = item.meta_item_list() { + match parse_alignment( + struct_span_err!( + diagnostic, + meta.span(), + E0589, + "invalid `repr({})` attribute", + name, + ), + meta, + ) { + Ok(lit) => return Some(lit), + Err(()) => { + // parse_alignment already emitted an error } - }; + } } else if let Some([first_meta, .., last_meta]) = item.meta_item_list() { struct_span_err!( diagnostic, @@ -1124,15 +1176,65 @@ fn allow_unstable<'a>( }) } -pub fn parse_alignment(node: &ast::LitKind) -> Result { - if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node { - if literal.is_power_of_two() { - // rustc_middle::ty::layout::Align restricts align to <= 2^29 - if *literal <= 1 << 29 { Ok(*literal as u32) } else { Err("larger than 2^29") } +pub fn parse_alignment( + mut err: rustc_errors::DiagnosticBuilder<'_>, + node: &ast::NestedMetaItem, +) -> Result { + if let ast::NestedMetaItem::Literal(lit) = node { + if let ast::LitKind::Int(val, ast::LitIntType::Unsuffixed) = lit.kind { + match is_alignment_valid(val) { + Ok(align) => { + err.cancel(); + return Ok(align); + } + Err(msg) => { + err.span_label(lit.span, msg); + } + } + } else if let ast::LitKind::Str(sym, style) = lit.kind { + match sym.as_str().parse::() { + Ok(num) => match is_alignment_valid(num) { + Ok(align) => { + err.multipart_suggestion( + "remove the quotes", + vec![ + ( + lit.span.with_hi(lit.span.lo() + BytePos(style.prefix_len())), + "".to_string(), + ), + ( + lit.span.with_lo(lit.span.hi() - BytePos(style.suffix_len())), + "".to_string(), + ), + ], + Applicability::MachineApplicable, + ); + err.emit(); + return Ok(align); + } + Err(msg) => { + err.span_label(lit.span, msg); + } + }, + Err(_) => { + err.span_label(lit.span, "must be a non-negative number"); + } + } } else { - Err("not a power of two") + err.span_label(lit.span, "not an unsuffixed integer"); } } else { - Err("not an unsuffixed integer") + err.span_label(node.span(), "not a non-negative number"); + } + err.emit(); + Err(()) +} + +fn is_alignment_valid(n: u128) -> Result { + if n.is_power_of_two() { + // rustc_target::abi::Align restricts align to <= 2^29 + if n <= 1 << 29 { Ok(n as u32) } else { Err("larger than 2^29") } + } else { + Err("not a power of two") } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 0528f8812f920..c611479d50283 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2906,29 +2906,30 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if tcx.sess.check_name(attr, sym::repr) { codegen_fn_attrs.alignment = match attr.meta_item_list() { Some(items) => match items.as_slice() { - [item] => match item.name_value_literal() { - Some((sym::align, literal)) => { - let alignment = rustc_attr::parse_alignment(&literal.kind); - - match alignment { - Ok(align) => Some(align), - Err(msg) => { + [item] if item.has_name(sym::align) => { + match item.meta_item_list() { + Some([meta]) => { + let alignment = rustc_attr::parse_alignment( struct_span_err!( tcx.sess.diagnostic(), - attr.span, + meta.span(), E0589, - "invalid `repr(align)` attribute: {}", - msg - ) - .emit(); - - None + "invalid `repr(align)` attribute", + ), + &meta, + ); + + match alignment { + Ok(align) => Some(align), + Err(()) => { + // Error already emitted by parse_alignment + None + } } } + _ => None, } - _ => None, - }, - [] => None, + } _ => None, }, None => None, diff --git a/src/test/ui/repr/basic.rs b/src/test/ui/repr/basic.rs index df7357bb88e1a..f55d6628fbf9e 100644 --- a/src/test/ui/repr/basic.rs +++ b/src/test/ui/repr/basic.rs @@ -33,37 +33,58 @@ struct S6(u32); //~| ERROR invalid `repr(no_niche)` attribute: no arguments expected struct S7(u32); -#[repr(align())] //~ ERROR invalid `repr(align)` attribute: expected a value - //~| ERROR invalid `repr(align)` attribute: expected a value + +#[repr(align)] //~ ERROR invalid `repr(align)` attribute: expected a non-negative number + //~| ERROR invalid `repr(align)` attribute: expected a non-negative number struct S8(u32); -#[repr(align(1, 2, 3))] //~ ERROR invalid `repr(align)` attribute: expected only one value - //~| ERROR invalid `repr(align)` attribute: expected only one value +#[repr(align())] //~ ERROR invalid `repr(align)` attribute: expected a non-negative number + //~| ERROR invalid `repr(align)` attribute: expected a non-negative number struct S9(u32); -#[repr(packed())] //~ ERROR invalid `repr(packed)` attribute: expected a value - //~| ERROR invalid `repr(packed)` attribute: expected a value +#[repr(align(foo()))] //~ ERROR invalid `repr(align)` attribute + //~| ERROR invalid `repr(align)` attribute struct S10(u32); +#[repr(align = "1")] //~ ERROR incorrect `repr(align)` attribute + //~| ERROR incorrect `repr(align)` attribute +struct S11(u32); + +#[repr(align = "")] //~ ERROR incorrect `repr(align)` attribute + //~| ERROR incorrect `repr(align)` attribute +struct S12(u32); + +#[repr(align = true)] //~ ERROR incorrect `repr(align)` attribute + //~| ERROR incorrect `repr(align)` attribute +struct S13(u32); + +#[repr(align(1, 2, 3))] //~ ERROR invalid `repr(align)` attribute: expected only one value + //~| ERROR invalid `repr(align)` attribute: expected only one value +struct S14(u32); + +#[repr(packed())] //~ ERROR invalid `repr(packed)` attribute: expected a non-negative number + //~| ERROR invalid `repr(packed)` attribute: expected a non-negative number +struct S15(u32); + #[repr(packed(1, 2, 3))] //~ ERROR invalid `repr(packed)` attribute: expected only one value //~| ERROR invalid `repr(packed)` attribute: expected only one value -struct S11(u32); +struct S16(u32); #[repr(i8())] //~ ERROR invalid `repr(i8)` attribute: no arguments expected //~| ERROR invalid `repr(i8)` attribute: no arguments expected -enum S12 { A, B } +enum S17 { A, B } #[repr(i8(1, 2, 3))] //~ ERROR invalid `repr(i8)` attribute: no arguments expected //~| ERROR invalid `repr(i8)` attribute: no arguments expected -enum S13 { A, B } +enum S18 { A, B } #[repr] //~ ERROR malformed `repr` attribute input -struct S14(u32); +struct S19(u32); #[repr(123)] //~ ERROR meta item in `repr` must be an identifier -struct S15(u32); +struct S20(u32); #[repr("foo")] //~ ERROR meta item in `repr` must be an identifier -struct S16(u32); +struct S21(u32); fn main() {} diff --git a/src/test/ui/repr/basic.stderr b/src/test/ui/repr/basic.stderr index 57eba736d7206..0d4f7ea578d22 100644 --- a/src/test/ui/repr/basic.stderr +++ b/src/test/ui/repr/basic.stderr @@ -1,5 +1,5 @@ error: malformed `repr` attribute input - --> $DIR/basic.rs:60:1 + --> $DIR/basic.rs:81:1 | LL | #[repr] | ^^^^^^^ help: must be of the form: `#[repr(C)]` @@ -8,88 +8,169 @@ error[E0589]: invalid `repr(transparent)` attribute: no arguments expected --> $DIR/basic.rs:4:8 | LL | #[repr(transparent())] - | ^^^^^^^^^^^-- - | | - | help: remove additional values: `transparent` + | ^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(transparent)] + | -- error[E0589]: invalid `repr(transparent)` attribute: no arguments expected --> $DIR/basic.rs:8:8 | LL | #[repr(transparent(1, 2, 3))] - | ^^^^^^^^^^^--------- - | | - | help: remove additional values: `transparent` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(transparent)] + | -- error[E0589]: invalid `repr(C)` attribute: no arguments expected --> $DIR/basic.rs:12:8 | LL | #[repr(C())] - | ^-- - | | - | help: remove additional values: `C` + | ^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- error[E0589]: invalid `repr(C)` attribute: no arguments expected --> $DIR/basic.rs:16:8 | LL | #[repr(C(1, 2, 3))] - | ^--------- - | | - | help: remove additional values: `C` + | ^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- error[E0589]: invalid `repr(simd)` attribute: no arguments expected --> $DIR/basic.rs:20:8 | LL | #[repr(simd())] - | ^^^^-- - | | - | help: remove additional values: `simd` + | ^^^^^^ + | +help: remove additional values + | +LL | #[repr(simd)] + | -- error[E0589]: invalid `repr(simd)` attribute: no arguments expected --> $DIR/basic.rs:24:8 | LL | #[repr(simd(1, 2, 3))] - | ^^^^--------- - | | - | help: remove additional values: `simd` + | ^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(simd)] + | -- error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected --> $DIR/basic.rs:28:8 | LL | #[repr(no_niche())] - | ^^^^^^^^-- - | | - | help: remove additional values: `no_niche` + | ^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(no_niche)] + | -- error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected --> $DIR/basic.rs:32:8 | LL | #[repr(no_niche(1, 2, 3))] - | ^^^^^^^^--------- - | | - | help: remove additional values: `no_niche` + | ^^^^^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(no_niche)] + | -- -error[E0693]: invalid `repr(align)` attribute: expected a value - --> $DIR/basic.rs:36:8 +error[E0693]: invalid `repr(align)` attribute: expected a non-negative number + --> $DIR/basic.rs:37:8 + | +LL | #[repr(align)] + | ^^^^^ + | +help: add a value + | +LL | #[repr(align(/* value */))] + | ^^^^^^^^^^^^^ + +error[E0693]: invalid `repr(align)` attribute: expected a non-negative number + --> $DIR/basic.rs:41:8 | LL | #[repr(align())] - | ^^^^^^^ help: add a value: `align(/* value */)` + | ^^^^^^^ + | +help: add a value + | +LL | #[repr(align(/* value */))] + | ^^^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute + --> $DIR/basic.rs:45:14 + | +LL | #[repr(align(foo()))] + | ^^^^^ not a non-negative number + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/basic.rs:49:8 + | +LL | #[repr(align = "1")] + | ^^^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(1))] + | ^ ^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/basic.rs:53:8 + | +LL | #[repr(align = "")] + | ^^^^^^^^^^ + | +help: use parentheses instead and add a value + | +LL | #[repr(align(/* value */))] + | ^^^^^^^^^^^^^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/basic.rs:57:8 + | +LL | #[repr(align = true)] + | ^^^^^^^^---- + | | + | must be a non-negative number error[E0693]: invalid `repr(align)` attribute: expected only one value - --> $DIR/basic.rs:40:8 + --> $DIR/basic.rs:61:8 | LL | #[repr(align(1, 2, 3))] | ^^^^^^-------^ | | | only one argument expected -error[E0693]: invalid `repr(packed)` attribute: expected a value - --> $DIR/basic.rs:44:8 +error[E0693]: invalid `repr(packed)` attribute: expected a non-negative number + --> $DIR/basic.rs:65:8 | LL | #[repr(packed())] - | ^^^^^^^^ help: add a value: `packed(/* value */)` + | ^^^^^^^^ + | +help: add a value + | +LL | #[repr(packed(/* value */))] + | ^^^^^^^^^^^^^ error[E0693]: invalid `repr(packed)` attribute: expected only one value - --> $DIR/basic.rs:48:8 + --> $DIR/basic.rs:69:8 | LL | #[repr(packed(1, 2, 3))] | ^^^^^^^-------^ @@ -97,29 +178,35 @@ LL | #[repr(packed(1, 2, 3))] | only one argument expected error[E0589]: invalid `repr(i8)` attribute: no arguments expected - --> $DIR/basic.rs:52:8 + --> $DIR/basic.rs:73:8 | LL | #[repr(i8())] - | ^^-- - | | - | help: remove additional values: `i8` + | ^^^^ + | +help: remove additional values + | +LL | #[repr(i8)] + | -- error[E0589]: invalid `repr(i8)` attribute: no arguments expected - --> $DIR/basic.rs:56:8 + --> $DIR/basic.rs:77:8 | LL | #[repr(i8(1, 2, 3))] - | ^^--------- - | | - | help: remove additional values: `i8` + | ^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(i8)] + | -- error[E0565]: meta item in `repr` must be an identifier - --> $DIR/basic.rs:63:8 + --> $DIR/basic.rs:84:8 | LL | #[repr(123)] | ^^^ error[E0565]: meta item in `repr` must be an identifier - --> $DIR/basic.rs:66:8 + --> $DIR/basic.rs:87:8 | LL | #[repr("foo")] | ^^^^^ @@ -128,88 +215,169 @@ error[E0589]: invalid `repr(transparent)` attribute: no arguments expected --> $DIR/basic.rs:4:8 | LL | #[repr(transparent())] - | ^^^^^^^^^^^-- - | | - | help: remove additional values: `transparent` + | ^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(transparent)] + | -- error[E0589]: invalid `repr(transparent)` attribute: no arguments expected --> $DIR/basic.rs:8:8 | LL | #[repr(transparent(1, 2, 3))] - | ^^^^^^^^^^^--------- - | | - | help: remove additional values: `transparent` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(transparent)] + | -- error[E0589]: invalid `repr(C)` attribute: no arguments expected --> $DIR/basic.rs:12:8 | LL | #[repr(C())] - | ^-- - | | - | help: remove additional values: `C` + | ^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- error[E0589]: invalid `repr(C)` attribute: no arguments expected --> $DIR/basic.rs:16:8 | LL | #[repr(C(1, 2, 3))] - | ^--------- - | | - | help: remove additional values: `C` + | ^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- error[E0589]: invalid `repr(simd)` attribute: no arguments expected --> $DIR/basic.rs:20:8 | LL | #[repr(simd())] - | ^^^^-- - | | - | help: remove additional values: `simd` + | ^^^^^^ + | +help: remove additional values + | +LL | #[repr(simd)] + | -- error[E0589]: invalid `repr(simd)` attribute: no arguments expected --> $DIR/basic.rs:24:8 | LL | #[repr(simd(1, 2, 3))] - | ^^^^--------- - | | - | help: remove additional values: `simd` + | ^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(simd)] + | -- error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected --> $DIR/basic.rs:28:8 | LL | #[repr(no_niche())] - | ^^^^^^^^-- - | | - | help: remove additional values: `no_niche` + | ^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(no_niche)] + | -- error[E0589]: invalid `repr(no_niche)` attribute: no arguments expected --> $DIR/basic.rs:32:8 | LL | #[repr(no_niche(1, 2, 3))] - | ^^^^^^^^--------- - | | - | help: remove additional values: `no_niche` + | ^^^^^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(no_niche)] + | -- -error[E0693]: invalid `repr(align)` attribute: expected a value - --> $DIR/basic.rs:36:8 +error[E0693]: invalid `repr(align)` attribute: expected a non-negative number + --> $DIR/basic.rs:37:8 + | +LL | #[repr(align)] + | ^^^^^ + | +help: add a value + | +LL | #[repr(align(/* value */))] + | ^^^^^^^^^^^^^ + +error[E0693]: invalid `repr(align)` attribute: expected a non-negative number + --> $DIR/basic.rs:41:8 | LL | #[repr(align())] - | ^^^^^^^ help: add a value: `align(/* value */)` + | ^^^^^^^ + | +help: add a value + | +LL | #[repr(align(/* value */))] + | ^^^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute + --> $DIR/basic.rs:45:14 + | +LL | #[repr(align(foo()))] + | ^^^^^ not a non-negative number + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/basic.rs:49:8 + | +LL | #[repr(align = "1")] + | ^^^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(1))] + | ^ ^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/basic.rs:53:8 + | +LL | #[repr(align = "")] + | ^^^^^^^^^^ + | +help: use parentheses instead and add a value + | +LL | #[repr(align(/* value */))] + | ^^^^^^^^^^^^^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/basic.rs:57:8 + | +LL | #[repr(align = true)] + | ^^^^^^^^---- + | | + | must be a non-negative number error[E0693]: invalid `repr(align)` attribute: expected only one value - --> $DIR/basic.rs:40:8 + --> $DIR/basic.rs:61:8 | LL | #[repr(align(1, 2, 3))] | ^^^^^^-------^ | | | only one argument expected -error[E0693]: invalid `repr(packed)` attribute: expected a value - --> $DIR/basic.rs:44:8 +error[E0693]: invalid `repr(packed)` attribute: expected a non-negative number + --> $DIR/basic.rs:65:8 | LL | #[repr(packed())] - | ^^^^^^^^ help: add a value: `packed(/* value */)` + | ^^^^^^^^ + | +help: add a value + | +LL | #[repr(packed(/* value */))] + | ^^^^^^^^^^^^^ error[E0693]: invalid `repr(packed)` attribute: expected only one value - --> $DIR/basic.rs:48:8 + --> $DIR/basic.rs:69:8 | LL | #[repr(packed(1, 2, 3))] | ^^^^^^^-------^ @@ -217,22 +385,28 @@ LL | #[repr(packed(1, 2, 3))] | only one argument expected error[E0589]: invalid `repr(i8)` attribute: no arguments expected - --> $DIR/basic.rs:52:8 + --> $DIR/basic.rs:73:8 | LL | #[repr(i8())] - | ^^-- - | | - | help: remove additional values: `i8` + | ^^^^ + | +help: remove additional values + | +LL | #[repr(i8)] + | -- error[E0589]: invalid `repr(i8)` attribute: no arguments expected - --> $DIR/basic.rs:56:8 + --> $DIR/basic.rs:77:8 | LL | #[repr(i8(1, 2, 3))] - | ^^--------- - | | - | help: remove additional values: `i8` + | ^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(i8)] + | -- -error: aborting due to 31 previous errors +error: aborting due to 41 previous errors Some errors have detailed explanations: E0565, E0589, E0693. For more information about an error, try `rustc --explain E0565`. diff --git a/src/test/ui/repr/repr-align-assign.fixed b/src/test/ui/repr/repr-align-assign.fixed index 59ca22e9728c6..6b7799297e89e 100644 --- a/src/test/ui/repr/repr-align-assign.fixed +++ b/src/test/ui/repr/repr-align-assign.fixed @@ -2,11 +2,11 @@ #![allow(dead_code)] -#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format +#[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format //~| ERROR incorrect `repr(align)` attribute format struct A(u64); -#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format +#[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format //~| ERROR incorrect `repr(align)` attribute format struct B(u64); diff --git a/src/test/ui/repr/repr-align-assign.stderr b/src/test/ui/repr/repr-align-assign.stderr index b878ae0d17337..8c719a4c9d2e1 100644 --- a/src/test/ui/repr/repr-align-assign.stderr +++ b/src/test/ui/repr/repr-align-assign.stderr @@ -2,25 +2,45 @@ error[E0693]: incorrect `repr(align)` attribute format --> $DIR/repr-align-assign.rs:5:8 | LL | #[repr(align=8)] - | ^^^^^^^ help: use parentheses instead: `align(8)` + | ^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(8))] + | ^ ^ error[E0693]: incorrect `repr(align)` attribute format --> $DIR/repr-align-assign.rs:9:8 | LL | #[repr(align="8")] - | ^^^^^^^^^ help: use parentheses instead: `align(8)` + | ^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(8))] + | ^ ^ error[E0693]: incorrect `repr(align)` attribute format --> $DIR/repr-align-assign.rs:5:8 | LL | #[repr(align=8)] - | ^^^^^^^ help: use parentheses instead: `align(8)` + | ^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(8))] + | ^ ^ error[E0693]: incorrect `repr(align)` attribute format --> $DIR/repr-align-assign.rs:9:8 | LL | #[repr(align="8")] - | ^^^^^^^^^ help: use parentheses instead: `align(8)` + | ^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(8))] + | ^ ^ error: aborting due to 4 previous errors diff --git a/src/test/ui/repr/repr-align.rs b/src/test/ui/repr/repr-align.rs index 58ecf9a518327..a14d0e52c5678 100644 --- a/src/test/ui/repr/repr-align.rs +++ b/src/test/ui/repr/repr-align.rs @@ -1,30 +1,30 @@ #![allow(dead_code)] -#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer - //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer +#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute + //~| ERROR: invalid `repr(align)` attribute struct S0(i32); -#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two - //~| ERROR: invalid `repr(align)` attribute: not a power of two +#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute + //~| ERROR: invalid `repr(align)` attribute struct S1(i32); -#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29 - //~| ERROR: invalid `repr(align)` attribute: larger than 2^29 +#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute + //~| ERROR: invalid `repr(align)` attribute struct S2(i32); #[repr(align(536870912))] // ok: this is the largest accepted alignment struct S3(i32); -#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer - //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer +#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute + //~| ERROR: invalid `repr(align)` attribute enum E0 { A, B } -#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two - //~| ERROR: invalid `repr(align)` attribute: not a power of two +#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute + //~| ERROR: invalid `repr(align)` attribute enum E1 { A, B } -#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29 - //~| ERROR: invalid `repr(align)` attribute: larger than 2^29 +#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute + //~| ERROR: invalid `repr(align)` attribute enum E2 { A, B } #[repr(align(536870912))] // ok: this is the largest accepted alignment diff --git a/src/test/ui/repr/repr-align.stderr b/src/test/ui/repr/repr-align.stderr index 900a811bb8ad7..9a191d6252ef1 100644 --- a/src/test/ui/repr/repr-align.stderr +++ b/src/test/ui/repr/repr-align.stderr @@ -1,74 +1,74 @@ -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer - --> $DIR/repr-align.rs:3:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:3:14 | LL | #[repr(align(16.0))] - | ^^^^^^^^^^^ + | ^^^^ not an unsuffixed integer -error[E0589]: invalid `repr(align)` attribute: not a power of two - --> $DIR/repr-align.rs:7:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:7:14 | LL | #[repr(align(15))] - | ^^^^^^^^^ + | ^^ not a power of two -error[E0589]: invalid `repr(align)` attribute: larger than 2^29 - --> $DIR/repr-align.rs:11:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:11:14 | LL | #[repr(align(4294967296))] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ larger than 2^29 -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer - --> $DIR/repr-align.rs:18:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:18:14 | LL | #[repr(align(16.0))] - | ^^^^^^^^^^^ + | ^^^^ not an unsuffixed integer -error[E0589]: invalid `repr(align)` attribute: not a power of two - --> $DIR/repr-align.rs:22:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:22:14 | LL | #[repr(align(15))] - | ^^^^^^^^^ + | ^^ not a power of two -error[E0589]: invalid `repr(align)` attribute: larger than 2^29 - --> $DIR/repr-align.rs:26:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:26:14 | LL | #[repr(align(4294967296))] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ larger than 2^29 -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer - --> $DIR/repr-align.rs:3:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:3:14 | LL | #[repr(align(16.0))] - | ^^^^^^^^^^^ + | ^^^^ not an unsuffixed integer -error[E0589]: invalid `repr(align)` attribute: not a power of two - --> $DIR/repr-align.rs:7:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:7:14 | LL | #[repr(align(15))] - | ^^^^^^^^^ + | ^^ not a power of two -error[E0589]: invalid `repr(align)` attribute: larger than 2^29 - --> $DIR/repr-align.rs:11:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:11:14 | LL | #[repr(align(4294967296))] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ larger than 2^29 -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer - --> $DIR/repr-align.rs:18:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:18:14 | LL | #[repr(align(16.0))] - | ^^^^^^^^^^^ + | ^^^^ not an unsuffixed integer -error[E0589]: invalid `repr(align)` attribute: not a power of two - --> $DIR/repr-align.rs:22:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:22:14 | LL | #[repr(align(15))] - | ^^^^^^^^^ + | ^^ not a power of two -error[E0589]: invalid `repr(align)` attribute: larger than 2^29 - --> $DIR/repr-align.rs:26:8 +error[E0589]: invalid `repr(align)` attribute + --> $DIR/repr-align.rs:26:14 | LL | #[repr(align(4294967296))] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ larger than 2^29 error: aborting due to 12 previous errors diff --git a/src/test/ui/repr/rustfix.fixed b/src/test/ui/repr/rustfix.fixed new file mode 100644 index 0000000000000..1f32fbe23a512 --- /dev/null +++ b/src/test/ui/repr/rustfix.fixed @@ -0,0 +1,30 @@ +// run-rustfix +#[repr(align = r#"1"#)] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct A; + +#[repr(align = r###"foo"###)] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct B; + +#[repr(align = 1)] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct C; + +#[repr(C)] //~ ERROR invalid `repr(C)` attribute: no arguments expected + //~| ERROR invalid `repr(C)` attribute: no arguments expected +struct D; + +#[repr(C)] //~ ERROR invalid `repr(C)` attribute: no arguments expected + //~| ERROR invalid `repr(C)` attribute: no arguments expected +struct E; + +#[repr(align("1"))] //~ ERROR invalid `repr(align)` attribute + //~| ERROR invalid `repr(align)` attribute +struct F; + +#[repr(align(r############"1"############))] //~ ERROR invalid `repr(align)` attribute + //~| ERROR invalid `repr(align)` attribute +struct G; + +fn main() {} diff --git a/src/test/ui/repr/rustfix.rs b/src/test/ui/repr/rustfix.rs new file mode 100644 index 0000000000000..5e44ead225b5b --- /dev/null +++ b/src/test/ui/repr/rustfix.rs @@ -0,0 +1,30 @@ +// run-rustfix +#[repr(align = r#"1"#)] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct A; + +#[repr(align = r###"foo"###)] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct B; + +#[repr(align = 1)] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct C; + +#[repr(C(1, "", true))] //~ ERROR invalid `repr(C)` attribute: no arguments expected + //~| ERROR invalid `repr(C)` attribute: no arguments expected +struct D; + +#[repr(C())] //~ ERROR invalid `repr(C)` attribute: no arguments expected + //~| ERROR invalid `repr(C)` attribute: no arguments expected +struct E; + +#[repr(align("1"))] //~ ERROR invalid `repr(align)` attribute + //~| ERROR invalid `repr(align)` attribute +struct F; + +#[repr(align(r############"1"############))] //~ ERROR invalid `repr(align)` attribute + //~| ERROR invalid `repr(align)` attribute +struct G; + +fn main() {} diff --git a/src/test/ui/repr/rustfix.stderr b/src/test/ui/repr/rustfix.stderr new file mode 100644 index 0000000000000..2f4dd14a3ddc5 --- /dev/null +++ b/src/test/ui/repr/rustfix.stderr @@ -0,0 +1,162 @@ +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/rustfix.rs:2:8 + | +LL | #[repr(align = r#"1"#)] + | ^^^^^^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(1))] + | ^ ^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/rustfix.rs:6:8 + | +LL | #[repr(align = r###"foo"###)] + | ^^^^^^^^------------ + | | + | must be a non-negative number + | +help: use parentheses instead + | +LL | #[repr(align(foo))] + | ^ ^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/rustfix.rs:10:8 + | +LL | #[repr(align = 1)] + | ^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(1))] + | ^ ^ + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/rustfix.rs:14:8 + | +LL | #[repr(C(1, "", true))] + | ^^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/rustfix.rs:18:8 + | +LL | #[repr(C())] + | ^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- + +error[E0589]: invalid `repr(align)` attribute + --> $DIR/rustfix.rs:22:14 + | +LL | #[repr(align("1"))] + | ^^^ + | +help: remove the quotes + | +LL | #[repr(align(1))] + | --- + +error[E0589]: invalid `repr(align)` attribute + --> $DIR/rustfix.rs:26:14 + | +LL | #[repr(align(r############"1"############))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the quotes + | +LL | #[repr(align(1))] + | --- + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/rustfix.rs:2:8 + | +LL | #[repr(align = r#"1"#)] + | ^^^^^^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(1))] + | ^ ^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/rustfix.rs:6:8 + | +LL | #[repr(align = r###"foo"###)] + | ^^^^^^^^------------ + | | + | must be a non-negative number + | +help: use parentheses instead + | +LL | #[repr(align(foo))] + | ^ ^ + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/rustfix.rs:10:8 + | +LL | #[repr(align = 1)] + | ^^^^^^^^^ + | +help: use parentheses instead + | +LL | #[repr(align(1))] + | ^ ^ + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/rustfix.rs:14:8 + | +LL | #[repr(C(1, "", true))] + | ^^^^^^^^^^^^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- + +error[E0589]: invalid `repr(C)` attribute: no arguments expected + --> $DIR/rustfix.rs:18:8 + | +LL | #[repr(C())] + | ^^^ + | +help: remove additional values + | +LL | #[repr(C)] + | -- + +error[E0589]: invalid `repr(align)` attribute + --> $DIR/rustfix.rs:22:14 + | +LL | #[repr(align("1"))] + | ^^^ + | +help: remove the quotes + | +LL | #[repr(align(1))] + | --- + +error[E0589]: invalid `repr(align)` attribute + --> $DIR/rustfix.rs:26:14 + | +LL | #[repr(align(r############"1"############))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the quotes + | +LL | #[repr(align(1))] + | --- + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0589, E0693. +For more information about an error, try `rustc --explain E0589`.