Enhance well-formedness checks for #[repr(...)]
attributes
This commit is contained in:
parent
e916b7cb77
commit
a7bfd35966
8 changed files with 234 additions and 10 deletions
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue