diff options
| author | Fabian Wolff <fabian.wolff@alumni.ethz.ch> | 2021-07-09 22:03:48 +0200 |
|---|---|---|
| committer | Fabian Wolff <fabian.wolff@alumni.ethz.ch> | 2021-07-09 22:03:48 +0200 |
| commit | a7bfd35966b112fc5033e9fb549e081b8541a15b (patch) | |
| tree | dca130c23a586b57764debc0d34d2625edb68be5 /compiler/rustc_attr/src | |
| parent | e916b7cb7708e470be8d0134bdf39479051a5c44 (diff) | |
Enhance well-formedness checks for `#[repr(...)]` attributes
Diffstat (limited to 'compiler/rustc_attr/src')
| -rw-r--r-- | compiler/rustc_attr/src/builtin.rs | 104 |
1 files changed, 96 insertions, 8 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 20971ebb957..b7b053cd5dd 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -870,6 +870,23 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> { sym::simd => Some(ReprSimd), sym::transparent => Some(ReprTransparent), sym::no_niche => Some(ReprNoNiche), + sym::align => { + let mut err = struct_span_err!( + diagnostic, + item.span(), + E0589, + "invalid `repr(align)` attribute: `align` needs an argument" + ); + err.span_suggestion( + item.span(), + "supply an argument here", + "align(...)".to_string(), + Applicability::HasPlaceholders, + ); + err.emit(); + recognised = true; + None + } name => int_type_of_word(name).map(ReprInt), }; @@ -891,33 +908,47 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> { Ok(literal) => acc.push(ReprPacked(literal)), Err(message) => literal_error = Some(message), }; + } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche) + || int_type_of_word(name).is_some() + { + recognised = true; + struct_span_err!( + diagnostic, + item.span(), + E0552, + "invalid representation hint: `{}` does not take a parenthesized argument list", + name.to_ident_string(), + ).emit(); } if let Some(literal_error) = literal_error { struct_span_err!( diagnostic, item.span(), E0589, - "invalid `repr(align)` attribute: {}", + "invalid `repr({})` attribute: {}", + name.to_ident_string(), 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 { + if let MetaItemKind::NameValue(ref value) = meta_item.kind { + if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) { + let name = meta_item.name_or_empty().to_ident_string(); recognised = true; let mut err = struct_span_err!( diagnostic, item.span(), E0693, - "incorrect `repr(align)` attribute format" + "incorrect `repr({})` attribute format", + name, ); match value.kind { ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { err.span_suggestion( item.span(), "use parentheses instead", - format!("align({})", int), + format!("{}({})", name, int), Applicability::MachineApplicable, ); } @@ -925,19 +956,76 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> { err.span_suggestion( item.span(), "use parentheses instead", - format!("align({})", s), + format!("{}({})", name, s), Applicability::MachineApplicable, ); } _ => {} } err.emit(); + } else { + if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent | sym::no_niche + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0552, + "invalid representation hint: `{}` does not take a value", + meta_item.name_or_empty().to_ident_string(), + ) + .emit(); + } + } + } else if let MetaItemKind::List(_) = meta_item.kind { + if meta_item.has_name(sym::align) { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0693, + "incorrect `repr(align)` attribute format: \ + `align` takes exactly one argument in parentheses" + ) + .emit(); + } else if meta_item.has_name(sym::packed) { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0552, + "incorrect `repr(packed)` attribute format: \ + `packed` takes exactly one parenthesized argument, \ + or no parentheses at all" + ) + .emit(); + } else if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent | sym::no_niche + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0552, + "invalid representation hint: `{}` does not take a parenthesized argument list", + meta_item.name_or_empty().to_ident_string(), + ).emit(); } } } if !recognised { - // Not a word we recognize - diagnostic.delay_span_bug(item.span(), "unrecognized representation hint"); + // Not a word we recognize. This will be caught and reported by + // the `check_mod_attrs` pass, but this pass doesn't always run + // (e.g. if we only pretty-print the source), so we have to gate + // the `delay_span_bug` call as follows: + if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) { + diagnostic.delay_span_bug(item.span(), "unrecognized representation hint"); + } } } } |
