[clang] [clang][AST] Fix crash on labeled break/continue within switch condition statement expression (PR #226754)

via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 26 21:57:35 PDT 2026


https://github.com/Expertcoderz created https://github.com/llvm/llvm-project/pull/226754

This PR fixes the issue described in #184060: having a labeled `continue` (or `break`) statement in a statement expression within the condition of a `switch` statement would cause Clang to crash:

```c
void foo() {
l1: for (;;) {
    switch (({ continue l1; 1; })) {}
  }
}
```

The issue seems to be caused by a null pointer dereference in `clang/lib/AST/Stmt.cpp`. I've checked the generated IR after applying the fix to ensure that the `break`/`continue` statements are working as expected. Also added regression tests.

>From d8e4dea61c21ad3fbaa2c3d24273ccd8240af71d Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 27 Sep 2026 04:36:04 +0000
Subject: [PATCH] [clang][AST] Fix crash on labeled break/continue within
 switch condition

---
 clang/docs/ReleaseNotes.md                  |  3 ++
 clang/lib/AST/Stmt.cpp                      |  4 +-
 clang/test/CodeGen/labeled-break-continue.c | 50 +++++++++++++++++++++
 3 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 3c6acf353f93f..8fd1bd5497baa 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -775,6 +775,9 @@ features cannot lower the translation-unit ABI level;
 - Added missed information to the AST node representing the member function
   when calling a explicit object member function. (#GH218829)
 
+- Fixed a crash when encountering C2y labeled `break`/`continue` statements
+  in a statement expression within a `switch` conditon.
+
 #### Miscellaneous Bug Fixes
 
 #### Miscellaneous Clang Crashes Fixed
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index 15d0e6435aaf3..cad8ebb9d854e 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -1535,7 +1535,9 @@ const Stmt *LabelStmt::getInnermostLabeledStmt() const {
 const Stmt *LoopControlStmt::getNamedLoopOrSwitch() const {
   if (!hasLabelTarget())
     return nullptr;
-  return getLabelDecl()->getStmt()->getInnermostLabeledStmt();
+
+  LabelStmt *Label = getLabelDecl()->getStmt();
+  return Label ? Label->getInnermostLabeledStmt() : nullptr;
 }
 
 DeferStmt::DeferStmt(EmptyShell Empty) : Stmt(DeferStmtClass, Empty) {}
diff --git a/clang/test/CodeGen/labeled-break-continue.c b/clang/test/CodeGen/labeled-break-continue.c
index f307a1bd79ab8..3d050a5cc6e44 100644
--- a/clang/test/CodeGen/labeled-break-continue.c
+++ b/clang/test/CodeGen/labeled-break-continue.c
@@ -279,3 +279,53 @@ void f7() {
     }
   }
 }
+
+/// https://github.com/llvm/llvm-project/issues/184060
+// CHECK-LABEL: define {{.*}} void @f8()
+// CHECK: entry:
+// CHECK:   %tmp = alloca i32, align 4
+// CHECK:   br label %l1
+// CHECK: l1:
+// CHECK:   br label %for.cond
+// CHECK: for.cond:
+// CHECK:   br label %for.end
+// CHECK: 0:
+// CHECK:   store i32 1, ptr %tmp, align 4
+// CHECK:   %1 = load i32, ptr %tmp, align 4
+// CHECK:   switch i32 %1, label %sw.epilog [
+// CHECK:   ]
+// CHECK: sw.epilog:
+// CHECK:   call {{.*}} i1 @g1()
+// CHECK:   br label %for.cond
+// CHECK: for.end:
+// CHECK:   ret void
+void f8() {
+l1: for (;;) {
+    switch (({ break l1; 1; })) {}
+    g1();
+  }
+}
+
+/// https://github.com/llvm/llvm-project/issues/184060
+// CHECK-LABEL: define {{.*}} void @f9()
+// CHECK: entry:
+// CHECK:   %tmp = alloca i32, align 4
+// CHECK:   br label %l1
+// CHECK: l1:
+// CHECK:   br label %for.cond
+// CHECK: for.cond:
+// CHECK:   br label %for.cond
+// CHECK: 0:
+// CHECK:   store i32 1, ptr %tmp, align 4
+// CHECK:   %1 = load i32, ptr %tmp, align 4
+// CHECK:   switch i32 %1, label %sw.epilog [
+// CHECK:   ]
+// CHECK: sw.epilog:
+// CHECK:   call {{.*}} i1 @g1()
+// CHECK:   br label %for.cond
+void f9() {
+l1: for (;;) {
+    switch (({ continue l1; 1; })) {}
+    g1();
+  }
+}



More information about the cfe-commits mailing list