Fix suggestion-cases-error of `empty_line_after_outer_attr`
diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs
index 0c5f8bb..3bd7485 100644
--- a/clippy_lints/src/empty_line_after.rs
+++ b/clippy_lints/src/empty_line_after.rs
@@ -10,7 +10,7 @@
 use rustc_lexer::TokenKind;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_session::impl_lint_pass;
-use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw};
+use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -129,10 +129,55 @@
     kind: StopKind,
     first: usize,
     last: usize,
+    name: Option<Symbol>,
 }
 
 impl Stop {
-    fn convert_to_inner(&self) -> (Span, String) {
+    fn is_outer_attr_only(&self) -> bool {
+        let Some(name) = self.name else {
+            return false;
+        };
+        // Check if the attribute only has effect when as an outer attribute
+        // The below attributes are collected from the builtin attributes of The Rust Reference
+        // https://doc.rust-lang.org/reference/attributes.html#r-attributes.builtin
+        // And the comments below are from compiler errors and warnings
+        matches!(
+            name,
+            // Cannot be used at crate level
+            sym::repr | sym::test | sym::derive | sym::automatically_derived | sym::path | sym::global_allocator |
+            // Only has an effect on macro definitions
+            sym::macro_export |
+            // Only be applied to trait definitions
+            sym::on_unimplemented |
+            // Only be placed on trait implementations
+            sym::do_not_recommend |
+            // Only has an effect on items
+            sym::ignore | sym::should_panic | sym::proc_macro | sym::proc_macro_derive | sym::proc_macro_attribute |
+            // Has no effect when applied to a module
+            sym::must_use |
+            // Should be applied to a foreign function or static
+            sym::link_name | sym::link_ordinal | sym::link_section |
+            // Should be applied to an `extern crate` item
+            sym::no_link |
+            // Should be applied to a free function, impl method or static
+            sym::export_name | sym::no_mangle |
+            // Should be applied to a `static` variable
+            sym::used |
+            // Should be applied to function or closure
+            sym::inline |
+            // Should be applied to a function definition
+            sym::cold | sym::target_feature | sym::track_caller | sym::instruction_set |
+            // Should be applied to a struct or enum
+            sym::non_exhaustive |
+            // Note: No any warning when it as an inner attribute, but it has no effect
+            sym::panic_handler
+        )
+    }
+
+    fn convert_to_inner(&self) -> Option<(Span, String)> {
+        if self.is_outer_attr_only() {
+            return None;
+        }
         let inner = match self.kind {
             // #![...]
             StopKind::Attr => InnerSpan::new(1, 1),
@@ -140,7 +185,7 @@
             //   ^      ^
             StopKind::Doc(_) => InnerSpan::new(2, 3),
         };
-        (self.span.from_inner(inner), "!".into())
+        Some((self.span.from_inner(inner), "!".into()))
     }
 
     fn comment_out(&self, cx: &EarlyContext<'_>, suggestions: &mut Vec<(Span, String)>) {
@@ -177,6 +222,7 @@
             },
             first: file.lookup_line(file.relative_position(lo))?,
             last: file.lookup_line(file.relative_position(hi))?,
+            name: attr.name(),
         })
     }
 }
@@ -356,6 +402,12 @@
         if let Some(parent) = self.items.iter().rev().nth(1)
             && (parent.kind == "module" || parent.kind == "crate")
             && parent.mod_items == Some(id)
+            && let suggestions = gaps
+                .iter()
+                .flat_map(|gap| gap.prev_chunk)
+                .filter_map(Stop::convert_to_inner)
+                .collect::<Vec<_>>()
+            && !suggestions.is_empty()
         {
             let desc = if parent.kind == "module" {
                 "parent module"
@@ -367,10 +419,7 @@
                     StopKind::Attr => format!("if the attribute should apply to the {desc} use an inner attribute"),
                     StopKind::Doc(_) => format!("if the comment should document the {desc} use an inner doc comment"),
                 },
-                gaps.iter()
-                    .flat_map(|gap| gap.prev_chunk)
-                    .map(Stop::convert_to_inner)
-                    .collect(),
+                suggestions,
                 Applicability::MaybeIncorrect,
             );
         }
@@ -425,6 +474,7 @@
                 first: line.line,
                 // last doesn't need to be accurate here, we don't compare it with anything
                 last: line.line,
+                name: None,
             });
         }
 
diff --git a/tests/ui/empty_line_after/outer_attribute.1.fixed b/tests/ui/empty_line_after/outer_attribute.1.fixed
index 36d80a2..e36e3c2 100644
--- a/tests/ui/empty_line_after/outer_attribute.1.fixed
+++ b/tests/ui/empty_line_after/outer_attribute.1.fixed
@@ -105,4 +105,13 @@
 ")]
 pub struct Args;
 
+mod issue_14980 {
+    //~v empty_line_after_outer_attr
+    #[repr(align(536870912))]
+    enum Aligned {
+        Zero = 0,
+        One = 1,
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.2.fixed b/tests/ui/empty_line_after/outer_attribute.2.fixed
index 0e8e412..b0908fc 100644
--- a/tests/ui/empty_line_after/outer_attribute.2.fixed
+++ b/tests/ui/empty_line_after/outer_attribute.2.fixed
@@ -108,4 +108,13 @@
 ")]
 pub struct Args;
 
+mod issue_14980 {
+    //~v empty_line_after_outer_attr
+    #[repr(align(536870912))]
+    enum Aligned {
+        Zero = 0,
+        One = 1,
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.rs b/tests/ui/empty_line_after/outer_attribute.rs
index 1295088..4ae113c 100644
--- a/tests/ui/empty_line_after/outer_attribute.rs
+++ b/tests/ui/empty_line_after/outer_attribute.rs
@@ -116,4 +116,14 @@
 ")]
 pub struct Args;
 
+mod issue_14980 {
+    //~v empty_line_after_outer_attr
+    #[repr(align(536870912))]
+
+    enum Aligned {
+        Zero = 0,
+        One = 1,
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.stderr b/tests/ui/empty_line_after/outer_attribute.stderr
index 519ba6e..331bc7c 100644
--- a/tests/ui/empty_line_after/outer_attribute.stderr
+++ b/tests/ui/empty_line_after/outer_attribute.stderr
@@ -111,5 +111,16 @@
    |
    = help: if the empty lines are unintentional, remove them
 
-error: aborting due to 9 previous errors
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:121:5
+   |
+LL | /     #[repr(align(536870912))]
+LL | |
+   | |_^
+LL |       enum Aligned {
+   |       ------------ the attribute applies to this enum
+   |
+   = help: if the empty line is unintentional, remove it
+
+error: aborting due to 10 previous errors