diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs
index 5fc988e4319..638c3c1267b 100644
--- a/src/parse/macros/cfg_if.rs
+++ b/src/parse/macros/cfg_if.rs
@@ -2,7 +2,7 @@ use std::panic::{catch_unwind, AssertUnwindSafe};
 
 use rustc_ast::ast;
 use rustc_ast::token::{Delimiter, TokenKind};
-use rustc_parse::parser::ForceCollect;
+use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_span::symbol::kw;
 
 use crate::parse::macros::build_stream_parser;
@@ -31,32 +31,7 @@ fn parse_cfg_if_inner<'a>(
 
     while parser.token.kind != TokenKind::Eof {
         if process_if_cfg {
-            if !parser.eat_keyword(kw::If) {
-                return Err("Expected `if`");
-            }
-
-            if !matches!(parser.token.kind, TokenKind::Pound) {
-                return Err("Failed to parse attributes");
-            }
-
-            // Inner attributes are not actually syntactically permitted here, but we don't
-            // care about inner vs outer attributes in this position. Our purpose with this
-            // special case parsing of cfg_if macros is to ensure we can correctly resolve
-            // imported modules that may have a custom `path` defined.
-            //
-            // As such, we just need to advance the parser past the attribute and up to
-            // to the opening brace.
-            // See also https://github.com/rust-lang/rust/pull/79433
-            parser
-                .parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
-                .map_err(|e| {
-                    e.cancel();
-                    "Failed to parse attributes"
-                })?;
-        }
-
-        if !parser.eat(&TokenKind::OpenDelim(Delimiter::Brace)) {
-            return Err("Expected an opening brace");
+            eat_if(&mut parser)?;
         }
 
         while parser.token != TokenKind::CloseDelim(Delimiter::Brace)
@@ -64,7 +39,17 @@ fn parse_cfg_if_inner<'a>(
         {
             let item = match parser.parse_item(ForceCollect::No) {
                 Ok(Some(item_ptr)) => item_ptr.into_inner(),
-                Ok(None) => continue,
+                Ok(None) => {
+                    if matches!(parser.token.kind, TokenKind::Ident(symbol, ..) if symbol == kw::If)
+                    {
+                        // eat a nested if
+                        eat_if(&mut parser)?;
+                    } else {
+                        // Not sure what token we're on. To prevent infinite loops bump the parser
+                        parser.bump();
+                    }
+                    continue;
+                }
                 Err(err) => {
                     err.cancel();
                     parser.psess.dcx.reset_err_count();
@@ -82,12 +67,15 @@ fn parse_cfg_if_inner<'a>(
             return Err("Expected a closing brace");
         }
 
-        if parser.eat(&TokenKind::Eof) {
-            break;
+        if matches!(parser.token.kind, TokenKind::Ident(symbol, ..) if symbol == kw::Else) {
+            // there might be an `else` after the `if`
+            parser.eat_keyword(kw::Else);
+            // there might be an opening brace after the `else`, but it might also be an `else if`
+            parser.eat(&TokenKind::OpenDelim(Delimiter::Brace));
         }
 
-        if !parser.eat_keyword(kw::Else) {
-            return Err("Expected `else`");
+        if parser.eat(&TokenKind::Eof) {
+            break;
         }
 
         process_if_cfg = parser.token.is_keyword(kw::If);
@@ -95,3 +83,33 @@ fn parse_cfg_if_inner<'a>(
 
     Ok(items)
 }
+
+fn eat_if(parser: &mut Parser<'_>) -> Result<(), &'static str> {
+    if !parser.eat_keyword(kw::If) {
+        return Err("Expected `if`");
+    }
+
+    if !matches!(parser.token.kind, TokenKind::Pound) {
+        return Err("Failed to parse attributes");
+    }
+
+    // Inner attributes are not actually syntactically permitted here, but we don't
+    // care about inner vs outer attributes in this position. Our purpose with this
+    // special case parsing of cfg_if macros is to ensure we can correctly resolve
+    // imported modules that may have a custom `path` defined.
+    //
+    // As such, we just need to advance the parser past the attribute and up to
+    // to the opening brace.
+    // See also https://github.com/rust-lang/rust/pull/79433
+    parser
+        .parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
+        .map_err(|e| {
+            e.cancel();
+            "Failed to parse attributes"
+        })?;
+
+    if !parser.eat(&TokenKind::OpenDelim(Delimiter::Brace)) {
+        return Err("Expected an opening brace");
+    }
+    Ok(())
+}
diff --git a/tests/source/issue-4442/a.rs b/tests/source/issue-4442/a.rs
new file mode 100644
index 00000000000..4278f0f85b8
--- /dev/null
+++ b/tests/source/issue-4442/a.rs
@@ -0,0 +1,2 @@
+fn a       ()
+{println!("mod a")}
diff --git a/tests/source/issue-4442/b.rs b/tests/source/issue-4442/b.rs
new file mode 100644
index 00000000000..da69971945b
--- /dev/null
+++ b/tests/source/issue-4442/b.rs
@@ -0,0 +1,2 @@
+fn b       ()
+{println!("mod b")}
diff --git a/tests/source/issue-4442/c.rs b/tests/source/issue-4442/c.rs
new file mode 100644
index 00000000000..43fadb4146d
--- /dev/null
+++ b/tests/source/issue-4442/c.rs
@@ -0,0 +1,2 @@
+fn c       ()
+{println!("mod c")}
diff --git a/tests/source/issue-4442/d.rs b/tests/source/issue-4442/d.rs
new file mode 100644
index 00000000000..99a9598f325
--- /dev/null
+++ b/tests/source/issue-4442/d.rs
@@ -0,0 +1,2 @@
+fn d       ()
+{println!("mod d")}
diff --git a/tests/source/issue-4442/e.rs b/tests/source/issue-4442/e.rs
new file mode 100644
index 00000000000..dc28c824946
--- /dev/null
+++ b/tests/source/issue-4442/e.rs
@@ -0,0 +1,2 @@
+fn e       ()
+{println!("mod e")}
diff --git a/tests/source/issue-4442/lib.rs b/tests/source/issue-4442/lib.rs
new file mode 100644
index 00000000000..4eddbfa28fa
--- /dev/null
+++ b/tests/source/issue-4442/lib.rs
@@ -0,0 +1,26 @@
+// main.rs
+cfg_if::cfg_if! {
+    if #[cfg(not(feature = "client"))] {
+        mod a;
+        if #[cfg(feature = "server")] {
+            if #[cfg(not(feature = "client"))] {
+                if #[cfg(feature = "server")] {
+                    if #[cfg(not(feature = "client"))] {
+                        mod b;
+                    } else {
+                        mod c;
+                    }
+                    if #[cfg(feature = "server")] {
+                        if #[cfg(not(feature = "client"))] {
+                            if #[cfg(feature = "server")] {
+                                mod d;
+                            } else {
+                                mod e;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/tests/source/issue_5413.rs b/tests/source/issue_5413.rs
new file mode 100644
index 00000000000..c4952f69cba
--- /dev/null
+++ b/tests/source/issue_5413.rs
@@ -0,0 +1,16 @@
+cfg_if! {
+    if
+}
+
+cfg_if! {
+    if #[a] { } else if
+}
+
+cfg_if! {
+    if #[a] { if }
+}
+
+fn main(
+    ) {
+println!("hello world!");
+     }
diff --git a/tests/target/issue-4442/a.rs b/tests/target/issue-4442/a.rs
new file mode 100644
index 00000000000..6ee01582a2c
--- /dev/null
+++ b/tests/target/issue-4442/a.rs
@@ -0,0 +1,3 @@
+fn a() {
+    println!("mod a")
+}
diff --git a/tests/target/issue-4442/b.rs b/tests/target/issue-4442/b.rs
new file mode 100644
index 00000000000..c1a0a54d143
--- /dev/null
+++ b/tests/target/issue-4442/b.rs
@@ -0,0 +1,3 @@
+fn b() {
+    println!("mod b")
+}
diff --git a/tests/target/issue-4442/c.rs b/tests/target/issue-4442/c.rs
new file mode 100644
index 00000000000..1e4661c5033
--- /dev/null
+++ b/tests/target/issue-4442/c.rs
@@ -0,0 +1,3 @@
+fn c() {
+    println!("mod c")
+}
diff --git a/tests/target/issue-4442/d.rs b/tests/target/issue-4442/d.rs
new file mode 100644
index 00000000000..3679b181da8
--- /dev/null
+++ b/tests/target/issue-4442/d.rs
@@ -0,0 +1,3 @@
+fn d() {
+    println!("mod d")
+}
diff --git a/tests/target/issue-4442/e.rs b/tests/target/issue-4442/e.rs
new file mode 100644
index 00000000000..5a21024b9ac
--- /dev/null
+++ b/tests/target/issue-4442/e.rs
@@ -0,0 +1,3 @@
+fn e() {
+    println!("mod e")
+}
diff --git a/tests/target/issue-4442/lib.rs b/tests/target/issue-4442/lib.rs
new file mode 100644
index 00000000000..4eddbfa28fa
--- /dev/null
+++ b/tests/target/issue-4442/lib.rs
@@ -0,0 +1,26 @@
+// main.rs
+cfg_if::cfg_if! {
+    if #[cfg(not(feature = "client"))] {
+        mod a;
+        if #[cfg(feature = "server")] {
+            if #[cfg(not(feature = "client"))] {
+                if #[cfg(feature = "server")] {
+                    if #[cfg(not(feature = "client"))] {
+                        mod b;
+                    } else {
+                        mod c;
+                    }
+                    if #[cfg(feature = "server")] {
+                        if #[cfg(not(feature = "client"))] {
+                            if #[cfg(feature = "server")] {
+                                mod d;
+                            } else {
+                                mod e;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/tests/target/issue_5413.rs b/tests/target/issue_5413.rs
new file mode 100644
index 00000000000..67f7e06d6a4
--- /dev/null
+++ b/tests/target/issue_5413.rs
@@ -0,0 +1,15 @@
+cfg_if! {
+    if
+}
+
+cfg_if! {
+    if #[a] { } else if
+}
+
+cfg_if! {
+    if #[a] { if }
+}
+
+fn main() {
+    println!("hello world!");
+}
diff --git a/tests/target/issue_5428.rs b/tests/target/issue_5428.rs
new file mode 100644
index 00000000000..727d8e4c20f
--- /dev/null
+++ b/tests/target/issue_5428.rs
@@ -0,0 +1,6 @@
+// cfg-if: version 1.0.0
+cfg_if::cfg_if! {
+    if #[cfg(windows)] {
+        compile_error!{"..."};
+    }
+}
diff --git a/tests/target/issue_6215.rs b/tests/target/issue_6215.rs
new file mode 100644
index 00000000000..abfce77b4f4
--- /dev/null
+++ b/tests/target/issue_6215.rs
@@ -0,0 +1,9 @@
+cfg_if!(
+    if #[cfg(feature = "xxxx")] {
+        if #[cfg(feature = "yyyy")] {
+            pub const C1: u8 = 1;
+        } else {
+            pub const C2: u8 = 2;
+        }
+    }
+);