diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index c054a00894e..52b3fc7f344 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -8,7 +8,8 @@ use crate::utils::{ use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{ - CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass, + in_external_macro, CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, + LintContext, LintPass, }; use rustc::ty::{self, TyCtxt}; use rustc::{declare_tool_lint, lint_array}; @@ -241,6 +242,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { let skip_unused_imports = item.attrs.iter().any(|attr| attr.check_name("macro_use")); for attr in &item.attrs { + if in_external_macro(cx.sess(), attr.span) { + return; + } if let Some(lint_list) = &attr.meta_item_list() { if let Some(ident) = attr.ident() { match &*ident.as_str() { diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs new file mode 100644 index 00000000000..d527aac6fa1 --- /dev/null +++ b/tests/ui/auxiliary/proc_macro_derive.rs @@ -0,0 +1,17 @@ +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(repr128, proc_macro_hygiene, proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, TokenStream}; + +#[proc_macro_derive(DeriveSomething)] +pub fn derive(_: TokenStream) -> TokenStream { + let output = quote! { + #[allow(dead_code)] + extern crate clippy_lints; + }; + output +} diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 7da251101f5..2ef1ec7dad4 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -1,3 +1,5 @@ +// aux-build:proc_macro_derive.rs + #![warn(clippy::useless_attribute)] #[allow(dead_code)] @@ -10,6 +12,9 @@ #[macro_use] extern crate clippy_lints; +#[macro_use] +extern crate proc_macro_derive; + // don't lint on unused_import for `use` items #[allow(unused_imports)] use std::collections; @@ -22,4 +27,9 @@ mod foo { #[allow(deprecated)] pub use foo::Bar; +// This should not trigger the lint. There's lint level definitions inside the external derive +// that would trigger the useless_attribute lint. +#[derive(DeriveSomething)] +struct Baz; + fn main() {} diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 2f7a010fc3e..50ba3d1b016 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -1,5 +1,5 @@ error: useless lint attribute - --> $DIR/useless_attribute.rs:3:1 + --> $DIR/useless_attribute.rs:5:1 | LL | #[allow(dead_code)] | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]` @@ -7,7 +7,7 @@ LL | #[allow(dead_code)] = note: `-D clippy::useless-attribute` implied by `-D warnings` error: useless lint attribute - --> $DIR/useless_attribute.rs:4:1 + --> $DIR/useless_attribute.rs:6:1 | LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)`