[clang] [clang][AST] Fix crash on labeled break/continue within switch condition statement expression (PR #228655)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 6 01:21:01 PDT 2026
https://github.com/Expertcoderz updated https://github.com/llvm/llvm-project/pull/228655
>From 13a9873c60b9e047514509b0f3b2671af89077df Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 27 Sep 2026 04:36:04 +0000
Subject: [PATCH 01/15] [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 929892fd34f7f..99645faae1afb 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -822,6 +822,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();
+ }
+}
>From 5f8f3640d4f20c14d0e25f34858f478a7ca3f34f Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 27 Sep 2026 07:13:17 +0000
Subject: [PATCH 02/15] Apply typo fix from @kazutakahirata
Co-authored-by: Kazu Hirata <kazu at google.com>
---
clang/docs/ReleaseNotes.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 99645faae1afb..2c5d6dbfb4b05 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -823,7 +823,7 @@ features cannot lower the translation-unit ABI level;
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.
+ in a statement expression within a `switch` condition.
#### Miscellaneous Bug Fixes
>From 81a8f14edb6e6bbccdacb8c2f85a35dcb4dd5e4f Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Tue, 29 Sep 2026 00:06:34 +0000
Subject: [PATCH 03/15] Add constant evaluation tests for labeled
break/continue
---
clang/test/SemaCXX/labeled-break-continue.cpp | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/clang/test/SemaCXX/labeled-break-continue.cpp b/clang/test/SemaCXX/labeled-break-continue.cpp
index 3d34211ed745a..d600ec5ff3caf 100644
--- a/clang/test/SemaCXX/labeled-break-continue.cpp
+++ b/clang/test/SemaCXX/labeled-break-continue.cpp
@@ -49,3 +49,21 @@ void f3() {
};
}
}
+
+void f4() {
+ l1: for (;;) {
+ constexpr int x = ({ // expected-error {{constexpr variable 'x' must be initialized by a constant expression}}
+ break l1; // expected-note {{not supported in a constant expression}}
+ 1;
+ });
+ }
+}
+
+void f5() {
+ l1: for (;;) {
+ constexpr int x = ({ // expected-error {{constexpr variable 'x' must be initialized by a constant expression}}
+ continue l1; // expected-note {{not supported in a constant expression}}
+ 1;
+ });
+ }
+}
>From 6739068e91b5d53c1e5b024967f7587b015b8c74 Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sat, 3 Oct 2026 02:47:14 +0000
Subject: [PATCH 04/15] Move hasLabelTarget() check out of
LoopControlStmt::getNamedLoopOrSwitch()
---
clang/lib/AST/ByteCode/Compiler.cpp | 6 ++++--
clang/lib/AST/ExprConstant.cpp | 3 ++-
clang/lib/AST/Stmt.cpp | 4 +---
clang/lib/CodeGen/CGStmt.cpp | 2 +-
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 01daace5b3c83..df37b705d495f 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -7184,7 +7184,8 @@ bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
return false;
OptLabelTy TargetLabel = std::nullopt;
- const Stmt *TargetLoop = S->getNamedLoopOrSwitch();
+ const Stmt *TargetLoop =
+ S->hasLabelTarget() ? S->getNamedLoopOrSwitch() : nullptr;
const VariableScope<Emitter> *BreakScope = nullptr;
if (!TargetLoop) {
@@ -7224,7 +7225,8 @@ bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
return false;
OptLabelTy TargetLabel = std::nullopt;
- const Stmt *TargetLoop = S->getNamedLoopOrSwitch();
+ const Stmt *TargetLoop =
+ S->hasLabelTarget() ? S->getNamedLoopOrSwitch() : nullptr;
const VariableScope<Emitter> *ContinueScope = nullptr;
if (!TargetLoop) {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 3f295f35d1361..46c408c794f96 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6385,7 +6385,8 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
case Stmt::ContinueStmtClass:
case Stmt::BreakStmtClass: {
auto *B = cast<LoopControlStmt>(S);
- Info.BreakContinueStack.push_back(B->getNamedLoopOrSwitch());
+ Info.BreakContinueStack.push_back(
+ B->hasLabelTarget() ? B->getNamedLoopOrSwitch() : nullptr);
return isa<ContinueStmt>(S) ? ESR_Continue : ESR_Break;
}
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index cad8ebb9d854e..a8c17676d56f3 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -1533,9 +1533,7 @@ const Stmt *LabelStmt::getInnermostLabeledStmt() const {
}
const Stmt *LoopControlStmt::getNamedLoopOrSwitch() const {
- if (!hasLabelTarget())
- return nullptr;
-
+ assert(hasLabelTarget());
LabelStmt *Label = getLabelDecl()->getStmt();
return Label ? Label->getInnermostLabeledStmt() : nullptr;
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 03b6e84a1c136..617929e1e613d 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1703,7 +1703,7 @@ auto CodeGenFunction::GetDestForLoopControlStmt(const LoopControlStmt &S)
return &BreakContinueStack.back();
const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
- assert(LoopOrSwitch && "break/continue target not set?");
+ assert(LoopOrSwitch && "break/continue target label not available?");
for (const BreakContinue &BC : llvm::reverse(BreakContinueStack))
if (BC.LoopOrSwitch == LoopOrSwitch)
return &BC;
>From 42a778088d3fedab9187f40d97adac16c41185cf Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sat, 3 Oct 2026 02:48:18 +0000
Subject: [PATCH 05/15] Add comment on return value of
LoopControlStmt::getNamedLoopOrSwitch()
---
clang/include/clang/AST/Stmt.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 5d27ded64082d..34bca3706f0a9 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3109,7 +3109,8 @@ class LoopControlStmt : public Stmt {
void setLabelDecl(LabelDecl *S) { TargetLabel = S; }
/// If this is a named break/continue, get the loop or switch statement
- /// that this targets.
+ /// that this targets. May return null if the target LabelStmt has not
+ /// yet been created.
const Stmt *getNamedLoopOrSwitch() const;
// Iterators
>From 98d12a0395a8a94ba4cdaba06512bca5d51c6582 Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 4 Oct 2026 15:15:45 +0000
Subject: [PATCH 06/15] Apply `\pre` comment suggestion from @tbaederr
Co-authored-by: Timm Baeder <tbaeder at redhat.com>
---
clang/include/clang/AST/Stmt.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 34bca3706f0a9..6123c1c084fc1 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3111,6 +3111,7 @@ class LoopControlStmt : public Stmt {
/// If this is a named break/continue, get the loop or switch statement
/// that this targets. May return null if the target LabelStmt has not
/// yet been created.
+ /// \pre `hasLabelTarget()`
const Stmt *getNamedLoopOrSwitch() const;
// Iterators
>From b38c73b80e14e485d91f74cced598240b17d26df Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 4 Oct 2026 15:17:58 +0000
Subject: [PATCH 07/15] Apply `\pre` comment suggestion from @tbaederr
Co-authored-by: Timm Baeder <tbaeder at redhat.com>
---
clang/include/clang/AST/Stmt.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 6123c1c084fc1..019cbcb307a2a 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3113,6 +3113,7 @@ class LoopControlStmt : public Stmt {
/// yet been created.
/// \pre `hasLabelTarget()`
const Stmt *getNamedLoopOrSwitch() const;
+ const Stmt *getNamedLoopOrSwitch() const;
// Iterators
child_range children() {
>From cc8fd00b44ccf74241f882d423cbfe2c578d509b Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 4 Oct 2026 15:19:39 +0000
Subject: [PATCH 08/15] Add `\pre` comment
Co-authored-by: Timm Baeder <tbaeder at redhat.com>
---
clang/include/clang/AST/Stmt.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 019cbcb307a2a..b54ce9eddf9e1 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3114,6 +3114,7 @@ class LoopControlStmt : public Stmt {
/// \pre `hasLabelTarget()`
const Stmt *getNamedLoopOrSwitch() const;
const Stmt *getNamedLoopOrSwitch() const;
+ const Stmt *getNamedLoopOrSwitch() const;
// Iterators
child_range children() {
>From d4f3afadb532d11aab7bd9aaea7c74102f4c6289 Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 4 Oct 2026 15:20:46 +0000
Subject: [PATCH 09/15] Update clang/include/clang/AST/Stmt.h
Co-authored-by: Timm Baeder <tbaeder at redhat.com>
---
clang/include/clang/AST/Stmt.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index b54ce9eddf9e1..acede8dd211ea 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3115,6 +3115,7 @@ class LoopControlStmt : public Stmt {
const Stmt *getNamedLoopOrSwitch() const;
const Stmt *getNamedLoopOrSwitch() const;
const Stmt *getNamedLoopOrSwitch() const;
+ const Stmt *getNamedLoopOrSwitch() const;
// Iterators
child_range children() {
>From 8aaf3a53b13a025daa9d493c1467d594e3dc3ae5 Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 4 Oct 2026 15:51:37 +0000
Subject: [PATCH 10/15] Add `\pre` comment suggestion frmo @tbaederr
Co-authored-by: Timm Baeder <tbaeder at redhat.com>
---
clang/include/clang/AST/Stmt.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index acede8dd211ea..1a5de1f056cc5 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3116,6 +3116,7 @@ class LoopControlStmt : public Stmt {
const Stmt *getNamedLoopOrSwitch() const;
const Stmt *getNamedLoopOrSwitch() const;
const Stmt *getNamedLoopOrSwitch() const;
+ const Stmt *getNamedLoopOrSwitch() const;
// Iterators
child_range children() {
>From a2aedac4073f9a1499391295c7848b89e39260af Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 4 Oct 2026 16:28:38 +0000
Subject: [PATCH 11/15] Add proper hasLabelTarget() checks in Compiler.cpp
---
clang/lib/AST/ByteCode/Compiler.cpp | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index df37b705d495f..15157db807a9d 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -7184,11 +7184,10 @@ bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
return false;
OptLabelTy TargetLabel = std::nullopt;
- const Stmt *TargetLoop =
- S->hasLabelTarget() ? S->getNamedLoopOrSwitch() : nullptr;
const VariableScope<Emitter> *BreakScope = nullptr;
- if (!TargetLoop) {
+ if (!S->hasLabelTarget()) {
+
for (const auto &LI : llvm::reverse(LabelInfoStack)) {
if (LI.BreakLabel) {
TargetLabel = *LI.BreakLabel;
@@ -7197,6 +7196,9 @@ bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
}
}
} else {
+ const Stmt *TargetLoop = S->getNamedLoopOrSwitch();
+ assert(TargetLoop && "break target label not available");
+
for (const auto &LI : LabelInfoStack) {
if (LI.Name == TargetLoop) {
TargetLabel = *LI.BreakLabel;
@@ -7225,11 +7227,9 @@ bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
return false;
OptLabelTy TargetLabel = std::nullopt;
- const Stmt *TargetLoop =
- S->hasLabelTarget() ? S->getNamedLoopOrSwitch() : nullptr;
const VariableScope<Emitter> *ContinueScope = nullptr;
- if (!TargetLoop) {
+ if (!S->hasLabelTarget()) {
for (const auto &LI : llvm::reverse(LabelInfoStack)) {
if (LI.ContinueLabel) {
TargetLabel = *LI.ContinueLabel;
@@ -7238,6 +7238,9 @@ bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
}
}
} else {
+ const Stmt *TargetLoop = S->getNamedLoopOrSwitch();
+ assert(TargetLoop && "continue target label not available");
+
for (auto LI : LabelInfoStack) {
if (LI.Name == TargetLoop) {
TargetLabel = *LI.ContinueLabel;
>From 86548035313614fcd7bcfccdcf6c72e33741dbf5 Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Sun, 4 Oct 2026 16:48:27 +0000
Subject: [PATCH 12/15] Fix duplicated function declaration due to github bug
---
clang/include/clang/AST/Stmt.h | 4 ----
1 file changed, 4 deletions(-)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 1a5de1f056cc5..6123c1c084fc1 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3113,10 +3113,6 @@ class LoopControlStmt : public Stmt {
/// yet been created.
/// \pre `hasLabelTarget()`
const Stmt *getNamedLoopOrSwitch() const;
- const Stmt *getNamedLoopOrSwitch() const;
- const Stmt *getNamedLoopOrSwitch() const;
- const Stmt *getNamedLoopOrSwitch() const;
- const Stmt *getNamedLoopOrSwitch() const;
// Iterators
child_range children() {
>From a273c6909fd8b504649cae8ffff1720cadffb14b Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Tue, 6 Oct 2026 07:28:55 +0000
Subject: [PATCH 13/15] Add labeled-break-continue test run with new constant
interpreter
---
clang/test/CodeGen/labeled-break-continue.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/test/CodeGen/labeled-break-continue.c b/clang/test/CodeGen/labeled-break-continue.c
index 3d050a5cc6e44..9c76a9ea7e887 100644
--- a/clang/test/CodeGen/labeled-break-continue.c
+++ b/clang/test/CodeGen/labeled-break-continue.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c2y -triple x86_64-unknown-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c2y -triple x86_64-unknown-linux -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
bool g1();
bool g2();
>From 1e0bba2816f3d4bdd69ac94030c7f04829010706 Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Tue, 6 Oct 2026 07:34:01 +0000
Subject: [PATCH 14/15] Rename hasLabelTarget() to isNamed() for better clarity
---
clang/include/clang/AST/Stmt.h | 6 +++---
clang/lib/AST/ASTImporter.cpp | 4 ++--
clang/lib/AST/ByteCode/Compiler.cpp | 4 ++--
clang/lib/AST/ExprConstant.cpp | 4 ++--
clang/lib/AST/JSONNodeDumper.cpp | 2 +-
clang/lib/AST/Stmt.cpp | 2 +-
clang/lib/AST/StmtPrinter.cpp | 4 ++--
clang/lib/AST/TextNodeDumper.cpp | 2 +-
clang/lib/CodeGen/CGStmt.cpp | 2 +-
clang/lib/Sema/TreeTransform.h | 4 ++--
clang/lib/Serialization/ASTWriterStmt.cpp | 4 ++--
11 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 6123c1c084fc1..00a415560b899 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -3096,10 +3096,10 @@ class LoopControlStmt : public Stmt {
SourceLocation getBeginLoc() const { return getKwLoc(); }
SourceLocation getEndLoc() const {
- return hasLabelTarget() ? getLabelLoc() : getKwLoc();
+ return isNamed() ? getLabelLoc() : getKwLoc();
}
- bool hasLabelTarget() const { return TargetLabel != nullptr; }
+ bool isNamed() const { return TargetLabel != nullptr; }
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
@@ -3111,7 +3111,7 @@ class LoopControlStmt : public Stmt {
/// If this is a named break/continue, get the loop or switch statement
/// that this targets. May return null if the target LabelStmt has not
/// yet been created.
- /// \pre `hasLabelTarget()`
+ /// \pre `isNamed()`
const Stmt *getNamedLoopOrSwitch() const;
// Iterators
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 4c296b6829b1b..9d6c824fe627d 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -7333,10 +7333,10 @@ static ExpectedStmt ImportLoopControlStmt(ASTNodeImporter &NodeImporter,
ASTImporter &Importer, StmtClass *S) {
Error Err = Error::success();
auto ToLoc = NodeImporter.importChecked(Err, S->getKwLoc());
- auto ToLabelLoc = S->hasLabelTarget()
+ auto ToLabelLoc = S->isNamed()
? NodeImporter.importChecked(Err, S->getLabelLoc())
: SourceLocation();
- auto ToDecl = S->hasLabelTarget()
+ auto ToDecl = S->isNamed()
? NodeImporter.importChecked(Err, S->getLabelDecl())
: nullptr;
if (Err)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 15157db807a9d..94c12c15339da 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -7186,7 +7186,7 @@ bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
OptLabelTy TargetLabel = std::nullopt;
const VariableScope<Emitter> *BreakScope = nullptr;
- if (!S->hasLabelTarget()) {
+ if (!S->isNamed()) {
for (const auto &LI : llvm::reverse(LabelInfoStack)) {
if (LI.BreakLabel) {
@@ -7229,7 +7229,7 @@ bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
OptLabelTy TargetLabel = std::nullopt;
const VariableScope<Emitter> *ContinueScope = nullptr;
- if (!S->hasLabelTarget()) {
+ if (!S->isNamed()) {
for (const auto &LI : llvm::reverse(LabelInfoStack)) {
if (LI.ContinueLabel) {
TargetLabel = *LI.ContinueLabel;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 46c408c794f96..7eff997d414d6 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6385,8 +6385,8 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
case Stmt::ContinueStmtClass:
case Stmt::BreakStmtClass: {
auto *B = cast<LoopControlStmt>(S);
- Info.BreakContinueStack.push_back(
- B->hasLabelTarget() ? B->getNamedLoopOrSwitch() : nullptr);
+ Info.BreakContinueStack.push_back(B->isNamed() ? B->getNamedLoopOrSwitch()
+ : nullptr);
return isa<ContinueStmt>(S) ? ESR_Continue : ESR_Break;
}
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 4cea437db4150..75abc4777f717 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -1750,7 +1750,7 @@ void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
}
void JSONNodeDumper::VisitLoopControlStmt(const LoopControlStmt *LS) {
- if (LS->hasLabelTarget())
+ if (LS->isNamed())
JOS.attribute("targetLabelDeclId",
createPointerRepresentation(LS->getLabelDecl()));
}
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index a8c17676d56f3..10dd9e247c135 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -1533,7 +1533,7 @@ const Stmt *LabelStmt::getInnermostLabeledStmt() const {
}
const Stmt *LoopControlStmt::getNamedLoopOrSwitch() const {
- assert(hasLabelTarget());
+ assert(isNamed());
LabelStmt *Label = getLabelDecl()->getStmt();
return Label ? Label->getInnermostLabeledStmt() : nullptr;
}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index fcc7ee74474cf..4f184868659f4 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -507,7 +507,7 @@ void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) {
void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) {
Indent();
- if (Node->hasLabelTarget())
+ if (Node->isNamed())
OS << "continue " << Node->getLabelDecl()->getIdentifier()->getName()
<< ';';
else
@@ -517,7 +517,7 @@ void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) {
void StmtPrinter::VisitBreakStmt(BreakStmt *Node) {
Indent();
- if (Node->hasLabelTarget())
+ if (Node->isNamed())
OS << "break " << Node->getLabelDecl()->getIdentifier()->getName() << ';';
else
OS << "break;";
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index d7476eacbd27a..497fca228e428 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1522,7 +1522,7 @@ void TextNodeDumper::dumpLinkageAndVisibility(const NamedDecl *ND) {
}
void TextNodeDumper::VisitLoopControlStmt(const LoopControlStmt *Node) {
- if (!Node->hasLabelTarget())
+ if (!Node->isNamed())
return;
OS << " '" << Node->getLabelDecl()->getIdentifier()->getName() << "' (";
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 617929e1e613d..b08220c5ed627 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1699,7 +1699,7 @@ void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) {
auto CodeGenFunction::GetDestForLoopControlStmt(const LoopControlStmt &S)
-> const BreakContinue * {
- if (!S.hasLabelTarget())
+ if (!S.isNamed())
return &BreakContinueStack.back();
const Stmt *LoopOrSwitch = S.getNamedLoopOrSwitch();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 73367d6bea063..628dd62a65c1c 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -8792,7 +8792,7 @@ TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) {
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) {
- if (!S->hasLabelTarget())
+ if (!S->isNamed())
return S;
Decl *LD = getDerived().TransformDecl(S->getLabelDecl()->getLocation(),
@@ -8807,7 +8807,7 @@ TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) {
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) {
- if (!S->hasLabelTarget())
+ if (!S->isNamed())
return S;
Decl *LD = getDerived().TransformDecl(S->getLabelDecl()->getLocation(),
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 4b4d179fb406a..c6f04336f806e 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -314,8 +314,8 @@ void ASTStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
void ASTStmtWriter::VisitLoopControlStmt(LoopControlStmt *S) {
VisitStmt(S);
Record.AddSourceLocation(S->getKwLoc());
- Record.push_back(S->hasLabelTarget());
- if (S->hasLabelTarget()) {
+ Record.push_back(S->isNamed());
+ if (S->isNamed()) {
Record.AddDeclRef(S->getLabelDecl());
Record.AddSourceLocation(S->getLabelLoc());
}
>From b582bae944bda3600bf64a44aad5d37066f26015 Mon Sep 17 00:00:00 2001
From: Expertcoderz <expertcoderzx at gmail.com>
Date: Tue, 6 Oct 2026 08:20:30 +0000
Subject: [PATCH 15/15] Fix test
---
clang/test/CodeGen/labeled-break-continue.c | 1 -
clang/test/SemaCXX/labeled-break-continue.cpp | 3 ++-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/CodeGen/labeled-break-continue.c b/clang/test/CodeGen/labeled-break-continue.c
index 9c76a9ea7e887..3d050a5cc6e44 100644
--- a/clang/test/CodeGen/labeled-break-continue.c
+++ b/clang/test/CodeGen/labeled-break-continue.c
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -std=c2y -triple x86_64-unknown-linux -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -std=c2y -triple x86_64-unknown-linux -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
bool g1();
bool g2();
diff --git a/clang/test/SemaCXX/labeled-break-continue.cpp b/clang/test/SemaCXX/labeled-break-continue.cpp
index d600ec5ff3caf..7d1511a5a9e3d 100644
--- a/clang/test/SemaCXX/labeled-break-continue.cpp
+++ b/clang/test/SemaCXX/labeled-break-continue.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -fnamed-loops %s
+// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -fnamed-loops %s -fno-experimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -fnamed-loops %s -fexperimental-new-constant-interpreter
int a[10]{};
struct S {
More information about the cfe-commits
mailing list