[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-06-01 Thread Corentin Jabot via llvm-branch-commits


@@ -751,8 +751,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);

cor3ntin wrote:

Am i missing something or is this always true?

https://github.com/llvm/llvm-project/pull/169688
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-05-07 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From a901f4390ef621a19d385a381286e9f885becdc6 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 --
 clang/lib/Sema/SemaStmt.cpp   |  30 +++-
 .../cxx2c-expansion-stmts-control-flow.cpp| 135 ++
 7 files changed, 223 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index eeb5edf5d8cb8..59ff2571b1445 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3747,6 +3747,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index f334f58ebd0a7..260ed1f55b44a 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e75cda8473cbd..b479cd297a301 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9623,7 +9623,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index a11aece69d525..3c4537f98f8d9 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -751,8 +751,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -796,6 +797,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 9502b440dbe97..a715ef4404cf5 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4468,7 +4468,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 // 

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-05-07 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From a901f4390ef621a19d385a381286e9f885becdc6 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 --
 clang/lib/Sema/SemaStmt.cpp   |  30 +++-
 .../cxx2c-expansion-stmts-control-flow.cpp| 135 ++
 7 files changed, 223 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index eeb5edf5d8cb8..59ff2571b1445 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3747,6 +3747,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index f334f58ebd0a7..260ed1f55b44a 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e75cda8473cbd..b479cd297a301 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9623,7 +9623,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index a11aece69d525..3c4537f98f8d9 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -751,8 +751,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -796,6 +797,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 9502b440dbe97..a715ef4404cf5 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4468,7 +4468,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 // 

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-31 Thread via llvm-branch-commits


@@ -3738,6 +3738,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;

Sirraide wrote:

Apparently we really don’t

https://github.com/llvm/llvm-project/pull/169688
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-24 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From c33d4df1c7ff384ffb2dcf7643b640a66f1ba7fb Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7f6fd47b3bb71..ee53b489fce35 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3738,6 +3738,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index f334f58ebd0a7..260ed1f55b44a 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 89f8f4deb091a..1df7e7a87e586 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9602,7 +9602,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index a6e3e055896c2..fc635db70920d 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -752,8 +752,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -797,6 +798,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 6167ba1943735..3e75474ae9c03 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4468,7 +4468,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-24 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From c33d4df1c7ff384ffb2dcf7643b640a66f1ba7fb Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7f6fd47b3bb71..ee53b489fce35 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3738,6 +3738,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index f334f58ebd0a7..260ed1f55b44a 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 89f8f4deb091a..1df7e7a87e586 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9602,7 +9602,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index a6e3e055896c2..fc635db70920d 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -752,8 +752,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -797,6 +798,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 6167ba1943735..3e75474ae9c03 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4468,7 +4468,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-23 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 25ca853332bac6e747372857c7e0127affb3c7c9 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7f6fd47b3bb71..ee53b489fce35 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3738,6 +3738,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index f334f58ebd0a7..260ed1f55b44a 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 89f8f4deb091a..1df7e7a87e586 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9602,7 +9602,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index a6e3e055896c2..fc635db70920d 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -752,8 +752,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -797,6 +798,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 6167ba1943735..3e75474ae9c03 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4468,7 +4468,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-18 Thread via llvm-branch-commits

github-actions[bot] wrote:


# :window: Windows x64 Test Results

* 53294 tests passed
* 1029 tests skipped
* 1 test failed

## Failed Tests
(click on a test name to see its output)

### Clang

Clang.SemaTemplate/GH176155.cpp

```
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
c:\_work\llvm-project\llvm-project\build\bin\clang.exe -cc1 -internal-isystem 
C:\_work\llvm-project\llvm-project\build\lib\clang\23\include -nostdsysteminc 
-std=c++20 -fsyntax-only -verify 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\clang.exe' 
-cc1 -internal-isystem 
'C:\_work\llvm-project\llvm-project\build\lib\clang\23\include' -nostdsysteminc 
-std=c++20 -fsyntax-only -verify 
'C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp'
# .---command stderr
# | error: 'expected-error' diagnostics expected but not seen: 
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:12): 
variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:15): 
variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# | error: 'expected-note' diagnostics expected but not seen: 
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:6): 
while substituting into a lambda expression here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:7): 
capture 'i' by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:7): 
capture 'i' by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:8): 
capture 'i' by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:8): 
capture 'i' by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:9): 
default capture by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:9): 
default capture by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:10): 
default capture by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:10): 
default capture by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:13): 
'i' declared here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:14): 
lambda expression begins here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:16): 
'i' declared here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:17): 
lambda expression begins here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 
23: in instantiation of default argument for 'f' required here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 
26: while substituting deduced template arguments into function template 'f'
# | 17 errors generated.
# `-
# error: command failed with exit status: 1

--

```


If these failures are unrelated to your changes (for example tests are broken 
or flaky at HEAD), please open an issue at 
https://github.com/llvm/llvm-project/issues and add the `infrastructure` label.

https://github.com/llvm/llvm-project/pull/169688
__

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-18 Thread via llvm-branch-commits

github-actions[bot] wrote:


# :penguin: Linux x64 Test Results

* 87002 tests passed
* 1328 tests skipped
* 1 test failed

## Failed Tests
(click on a test name to see its output)

### Clang

Clang.SemaTemplate/GH176155.cpp

```
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 
-internal-isystem 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/23/include
 -nostdsysteminc -std=c++20 -fsyntax-only -verify 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
# executed command: 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 
-internal-isystem 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/23/include
 -nostdsysteminc -std=c++20 -fsyntax-only -verify 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
# .---command stderr
# | error: 'expected-error' diagnostics expected but not seen: 
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:12):
 variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:15):
 variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# | error: 'expected-note' diagnostics expected but not seen: 
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:6):
 while substituting into a lambda expression here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:7):
 capture 'i' by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:7):
 capture 'i' by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:8):
 capture 'i' by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:8):
 capture 'i' by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:9):
 default capture by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:9):
 default capture by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:10):
 default capture by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:10):
 default capture by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:13):
 'i' declared here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:14):
 lambda expression begins here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:16):
 'i' declared here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llv

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-18 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From c9e4f2dee86593281b4d09fa7dbf24cb874295da Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7f6fd47b3bb71..ee53b489fce35 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3738,6 +3738,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index f334f58ebd0a7..260ed1f55b44a 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 89f8f4deb091a..1df7e7a87e586 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9602,7 +9602,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index f4f2d6c7a249d..9e6a66db596df 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -752,8 +752,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -797,6 +798,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 6167ba1943735..3e75474ae9c03 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4468,7 +4468,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2026-03-18 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From c9e4f2dee86593281b4d09fa7dbf24cb874295da Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7f6fd47b3bb71..ee53b489fce35 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3738,6 +3738,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index f334f58ebd0a7..260ed1f55b44a 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 89f8f4deb091a..1df7e7a87e586 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9602,7 +9602,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index f4f2d6c7a249d..9e6a66db596df 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -752,8 +752,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -797,6 +798,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 6167ba1943735..3e75474ae9c03 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4468,7 +4468,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 31dfa44cec804e7f9850524ef0b60f8ccfcedc3b Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 208c885909b00..6994cd88fba21 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3720,6 +3720,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0adc570c73011..5a3603c284cd1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9531,7 +9531,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 90eee36d7dbe6..169e1d1cf1cb5 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4466,7 +4466,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 31dfa44cec804e7f9850524ef0b60f8ccfcedc3b Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 208c885909b00..6994cd88fba21 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3720,6 +3720,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0adc570c73011..5a3603c284cd1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9531,7 +9531,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 90eee36d7dbe6..169e1d1cf1cb5 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4466,7 +4466,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-03 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 3cf63f47cd71cefb1abf2784ab38041ff959a921 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d91e1526ae47f..bf6d017e845fc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3708,6 +3708,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f5a36626a9dad..a4a4fd287ab12 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9530,7 +9530,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-03 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 3cf63f47cd71cefb1abf2784ab38041ff959a921 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d91e1526ae47f..bf6d017e845fc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3708,6 +3708,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f5a36626a9dad..a4a4fd287ab12 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9530,7 +9530,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-02 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 0a945e66ca01c3a5f9d8914cfb6c7f0459a866b3 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d91e1526ae47f..bf6d017e845fc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3708,6 +3708,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 268c81351e744..c90ddf91a663b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9530,7 +9530,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-02 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 0a945e66ca01c3a5f9d8914cfb6c7f0459a866b3 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d91e1526ae47f..bf6d017e845fc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3708,6 +3708,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 268c81351e744..c90ddf91a663b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9530,7 +9530,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-01 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 20da66c4ce7543e65d42fce8a0acfc43a749c1aa Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0ddaa461deff5..5115c175849e1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3706,6 +3706,12 @@ def err_expansion_stmt_invalid_init : Error<
   "cannot expand expression of type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b102544342416..82fc2875e2abf 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9519,7 +9519,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 39751c79c6852..7b0e0ff17733b 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -715,8 +715,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -760,6 +761,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 // Local l

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 162cc15dff58d47852cc0d88311754395bec12f5 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0ddaa461deff5..5115c175849e1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3706,6 +3706,12 @@ def err_expansion_stmt_invalid_init : Error<
   "cannot expand expression of type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b102544342416..82fc2875e2abf 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9519,7 +9519,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 39751c79c6852..7b0e0ff17733b 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -715,8 +715,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -760,6 +761,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 // Local l

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 162cc15dff58d47852cc0d88311754395bec12f5 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0ddaa461deff5..5115c175849e1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3706,6 +3706,12 @@ def err_expansion_stmt_invalid_init : Error<
   "cannot expand expression of type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b102544342416..82fc2875e2abf 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9519,7 +9519,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 39751c79c6852..7b0e0ff17733b 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -715,8 +715,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -760,6 +761,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 // Local l

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide edited 
https://github.com/llvm/llvm-project/pull/169688
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide ready_for_review 
https://github.com/llvm/llvm-project/pull/169688
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-11-28 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: None (Sirraide)


Changes



---
Full diff: https://github.com/llvm/llvm-project/pull/169688.diff


7 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+6) 
- (modified) clang/include/clang/Sema/ScopeInfo.h (+5-1) 
- (modified) clang/include/clang/Sema/Sema.h (+2-1) 
- (modified) clang/lib/Parse/ParseStmt.cpp (+9-2) 
- (modified) clang/lib/Sema/SemaLookup.cpp (+38-9) 
- (modified) clang/lib/Sema/SemaStmt.cpp (+28-2) 
- (added) clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp (+117) 


``diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0ddaa461deff5..5115c175849e1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3706,6 +3706,12 @@ def err_expansion_stmt_invalid_init : Error<
   "cannot expand expression of type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b102544342416..82fc2875e2abf 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9519,7 +9519,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 39751c79c6852..7b0e0ff17733b 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -715,8 +715,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -760,6 +761,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 88dcd27d45ad2..576ec6c80770e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4463,7 +4463,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 // Local label definitions always shadow existing labels.
 auto *Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc);
@@ -4472,15 +4473,43 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo 
*II, SourceLocati

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide edited 
https://github.com/llvm/llvm-project/pull/169688
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits