diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index e014d191276..a8858a24e0f 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -343,7 +343,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
 }
 
 fn check_code(cx: &LateContext<'_, '_>, text: &str, span: Span) {
-    if text.contains("fn main() {") {
+    if text.contains("fn main() {") && !(text.contains("static") || text.contains("fn main() {}")) {
         span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
     }
 }
diff --git a/tests/ui/needless_doc_main.rs b/tests/ui/needless_doc_main.rs
new file mode 100644
index 00000000000..d2a3857b554
--- /dev/null
+++ b/tests/ui/needless_doc_main.rs
@@ -0,0 +1,33 @@
+/// This is a test for needless `fn main()` in doctests.
+///
+/// # Examples
+///
+/// This should lint
+/// ```
+/// fn main() {
+///     unimplemented!();
+/// }
+/// ```
+fn bad_doctest() {}
+
+/// # Examples
+///
+/// This shouldn't lint, because the `main` is empty:
+/// ```
+/// fn main(){}
+/// ```
+///
+/// This shouldn't lint either, because there's a `static`:
+/// ```
+/// static ANSWER: i32 = 42;
+///
+/// fn main() {
+///     assert_eq!(42, ANSWER);
+/// }
+/// ```
+fn no_false_positives() {}
+
+fn main() {
+    bad_doctest();
+    no_false_positives();
+}
diff --git a/tests/ui/needless_doc_main.stderr b/tests/ui/needless_doc_main.stderr
new file mode 100644
index 00000000000..22d145aad58
--- /dev/null
+++ b/tests/ui/needless_doc_main.stderr
@@ -0,0 +1,10 @@
+error: needless `fn main` in doctest
+  --> $DIR/needless_doc_main.rs:7:4
+   |
+LL | /// fn main() {
+   |    ^^^^^^^^^^^^
+   |
+   = note: `-D clippy::needless-doctest-main` implied by `-D warnings`
+
+error: aborting due to previous error
+