Skip to content

Commit

Permalink
Rollup merge of rust-lang#51401 - estebank:warn-repr, r=cramertj
Browse files Browse the repository at this point in the history
Warn on `repr` without hints

Fix rust-lang#51376.
  • Loading branch information
Mark-Simulacrum authored Jun 8, 2018
2 parents b1a6db2 + 0e3f19d commit 898bb78
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 202 deletions.
6 changes: 6 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ declare_lint! {
"potentially-conflicting impls were erroneously allowed"
}

declare_lint! {
pub BAD_REPR,
Warn,
"detects incorrect use of `repr` attribute"
}

declare_lint! {
pub DEPRECATED,
Warn,
Expand Down
73 changes: 73 additions & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,79 @@ impl EarlyLintPass for AnonymousParameters {
}
}

/// Checks for incorrect use use of `repr` attributes.
#[derive(Clone)]
pub struct BadRepr;

impl LintPass for BadRepr {
fn get_lints(&self) -> LintArray {
lint_array!()
}
}

impl EarlyLintPass for BadRepr {
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
if attr.name() == "repr" {
let list = attr.meta_item_list();

let repr_str = |lit: &str| { format!("#[repr({})]", lit) };

// Emit warnings with `repr` either has a literal assignment (`#[repr = "C"]`) or
// no hints (``#[repr]`)
let has_hints = list.as_ref().map(|ref list| !list.is_empty()).unwrap_or(false);
if !has_hints {
let mut suggested = false;
let mut warn = if let Some(ref lit) = attr.value_str() {
// avoid warning about empty `repr` on `#[repr = "foo"]`
let mut warn = cx.struct_span_lint(
BAD_REPR,
attr.span,
"`repr` attribute isn't configurable with a literal",
);
match format!("{}", lit).as_ref() {
| "C" | "packed" | "rust" | "transparent"
| "u8" | "u16" | "u32" | "u64" | "u128" | "usize"
| "i8" | "i16" | "i32" | "i64" | "i128" | "isize" => {
// if the literal could have been a valid `repr` arg,
// suggest the correct syntax
warn.span_suggestion(
attr.span,
"give `repr` a hint",
repr_str(&lit.as_str()),
);
suggested = true;
}
_ => { // the literal wasn't a valid `repr` arg
warn.span_label(attr.span, "needs a hint");
}
};
warn
} else {
let mut warn = cx.struct_span_lint(
BAD_REPR,
attr.span,
"`repr` attribute must have a hint",
);
warn.span_label(attr.span, "needs a hint");
warn
};
if !suggested {
warn.help(&format!(
"valid hints include `{}`, `{}`, `{}` and `{}`",
repr_str("C"),
repr_str("packed"),
repr_str("rust"),
repr_str("transparent"),
));
warn.note("for more information, visit \
<https://doc.rust-lang.org/reference/type-layout.html>");
}
warn.emit();
}
}
}
}

/// Checks for use of attributes which have been deprecated.
#[derive(Clone)]
pub struct DeprecatedAttr {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UnusedImportBraces,
AnonymousParameters,
UnusedDocComment,
BadRepr,
);

add_early_builtin_with_new!(sess,
Expand Down
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-43988.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn main() {
#[repr]
let _y = "123";
//~^^ ERROR attribute should not be applied to a statement
//~| WARN `repr` attribute must have a hint


fn foo() {}
Expand All @@ -44,5 +45,5 @@ fn main() {

let _z = #[repr] 1;
//~^ ERROR attribute should not be applied to an expression

//~| WARN `repr` attribute must have a hint
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@
#![start = "x4300"] //~ WARN unused attribute
// see issue-43106-gating-of-test.rs for crate-level; but non crate-level is below at "4200"
// see issue-43106-gating-of-bench.rs for crate-level; but non crate-level is below at "4100"
#![repr = "3900"] //~ WARN unused attribute
#![repr = "3900"]
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
#![path = "3800"] //~ WARN unused attribute
#![abi = "3700"] //~ WARN unused attribute
#![automatically_derived = "3600"] //~ WARN unused attribute
Expand Down Expand Up @@ -309,20 +311,25 @@ mod bench {

#[repr = "3900"]
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
mod repr {
mod inner { #![repr="3900"] }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal

#[repr = "3900"] fn f() { }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal

struct S;

#[repr = "3900"] type T = S;
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal

#[repr = "3900"] impl S { }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
}

#[path = "3800"]
Expand Down
Loading

0 comments on commit 898bb78

Please sign in to comment.