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

>From ce432df0abadee6cec9eedcfa44f8f9f70663c69 Mon Sep 17 00:00:00 2001
From: Sirraide <[email protected]>
Date: Tue, 25 Nov 2025 20:47:23 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 3)

---
 .../clang/Basic/DiagnosticSemaKinds.td        |   2 +
 clang/include/clang/Sema/Sema.h               |  22 +++
 clang/lib/Frontend/FrontendActions.cpp        |   2 +
 clang/lib/Sema/SemaExpand.cpp                 | 151 ++++++++++++++++++
 clang/lib/Sema/SemaTemplateInstantiate.cpp    |  29 +++-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  38 ++++-
 clang/lib/Sema/SemaTemplateVariadic.cpp       |   8 +-
 clang/lib/Sema/TreeTransform.h                |  83 +++++++++-
 .../Parser/cxx2c-expansion-statements.cpp     |  80 +++++-----
 9 files changed, 365 insertions(+), 50 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ca862316a2f27..d4783c1c9677d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5827,6 +5827,8 @@ def note_template_nsdmi_here : Note<
   "in instantiation of default member initializer %q0 requested here">;
 def note_template_type_alias_instantiation_here : Note<
   "in instantiation of template type alias %0 requested here">;
+def note_expansion_stmt_instantiation_here : Note<
+  "in instantiation of expansion statement requested here">;
 def note_template_exception_spec_instantiation_here : Note<
   "in instantiation of exception specification for %0 requested here">;
 def note_template_requirement_instantiation_here : Note<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 786e53a2e179a..4d25143cffaf4 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13176,6 +13176,9 @@ class Sema final : public SemaBase {
 
       /// We are performing partial ordering for template template parameters.
       PartialOrderingTTP,
+
+      /// We are instantiating an expansion statement.
+      ExpansionStmtInstantiation,
     } Kind;
 
     /// Whether we're substituting into constraints.
@@ -13371,6 +13374,12 @@ class Sema final : public SemaBase {
                           concepts::Requirement *Req,
                           SourceRange InstantiationRange = SourceRange());
 
+    /// \brief Note that we are substituting the body of an expansion 
statement.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          CXXExpansionStmtPattern *ExpansionStmt,
+                          ArrayRef<TemplateArgument> TArgs,
+                          SourceRange InstantiationRange);
+
     /// \brief Note that we are checking the satisfaction of the constraint
     /// expression inside of a nested requirement.
     InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -15643,6 +15652,19 @@ class Sema final : public SemaBase {
       ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps);
 
   StmtResult FinishCXXExpansionStmt(Stmt *Expansion, Stmt *Body);
+
+  StmtResult BuildCXXEnumeratingExpansionStmtPattern(Decl *ESD, Stmt *Init,
+                                                     Stmt *ExpansionVar,
+                                                     SourceLocation LParenLoc,
+                                                     SourceLocation ColonLoc,
+                                                     SourceLocation RParenLoc);
+
+  ExprResult
+  BuildCXXExpansionInitListSelectExpr(CXXExpansionInitListExpr *Range,
+                                      Expr *Idx);
+
+  std::optional<uint64_t>
+  ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
   ///@}
 };
 
diff --git a/clang/lib/Frontend/FrontendActions.cpp 
b/clang/lib/Frontend/FrontendActions.cpp
index e0c1d304e8290..75d5a76c04a32 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -476,6 +476,8 @@ class DefaultTemplateInstCallback : public 
TemplateInstantiationCallback {
       return "TypeAliasTemplateInstantiation";
     case CodeSynthesisContext::PartialOrderingTTP:
       return "PartialOrderingTTP";
+    case CodeSynthesisContext::ExpansionStmtInstantiation:
+      return "ExpansionStmtInstantiation";
     }
     return "";
   }
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 96c0d9be9451c..f1cd2baa9ae39 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -24,6 +24,23 @@
 using namespace clang;
 using namespace sema;
 
+// Build a 'DeclRefExpr' designating the template parameter '__N'.
+static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
+  return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
+                            S.Context.getPointerDiffType(), VK_PRValue,
+                            ESD->getBeginLoc());
+}
+
+static bool FinaliseExpansionVar(Sema &S, VarDecl *ExpansionVar,
+                                 ExprResult Initializer) {
+  if (Initializer.isInvalid()) {
+    S.ActOnInitializerError(ExpansionVar);
+    return true;
+  }
+
+  S.AddInitializerToDecl(ExpansionVar, Initializer.get(), 
/*DirectInit=*/false);
+  return ExpansionVar->isInvalidDecl();
+}
 
 CXXExpansionStmtDecl *
 Sema::ActOnCXXExpansionStmtDecl(unsigned TemplateDepth,
@@ -66,13 +83,147 @@ StmtResult Sema::ActOnCXXExpansionStmtPattern(
     Expr *ExpansionInitializer, SourceLocation LParenLoc,
     SourceLocation ColonLoc, SourceLocation RParenLoc,
     ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps) {
+  if (!ExpansionInitializer || !ExpansionVarStmt)
+    return StmtError();
+
+  assert(CurContext->isExpansionStmt());
+  auto *DS = cast<DeclStmt>(ExpansionVarStmt);
+  if (!DS->isSingleDecl()) {
+    Diag(DS->getBeginLoc(), diag::err_type_defined_in_for_range);
+    return StmtError();
+  }
+
+  VarDecl *ExpansionVar = dyn_cast<VarDecl>(DS->getSingleDecl());
+  if (!ExpansionVar || ExpansionVar->isInvalidDecl() ||
+      ExpansionInitializer->containsErrors())
+    return StmtError();
+
+  // This is an enumerating expansion statement.
+  if (auto *ILE = dyn_cast<CXXExpansionInitListExpr>(ExpansionInitializer)) {
+    ExprResult Initializer =
+        BuildCXXExpansionInitListSelectExpr(ILE, BuildIndexDRE(*this, ESD));
+    if (FinaliseExpansionVar(*this, ExpansionVar, Initializer))
+      return StmtError();
+
+    // Note that lifetime extension only applies to destructuring expansion
+    // statements, so we just ignore 'LifetimeExtendedTemps' entirely for other
+    // types of expansion statements (this is CWG 3043).
+    return BuildCXXEnumeratingExpansionStmtPattern(ESD, Init, DS, LParenLoc,
+                                                   ColonLoc, RParenLoc);
+  }
+
   Diag(ESD->getLocation(), diag::err_expansion_statements_todo);
   return StmtError();
 }
 
+StmtResult Sema::BuildCXXEnumeratingExpansionStmtPattern(
+    Decl *ESD, Stmt *Init, Stmt *ExpansionVar, SourceLocation LParenLoc,
+    SourceLocation ColonLoc, SourceLocation RParenLoc) {
+  return new (Context) CXXEnumeratingExpansionStmtPattern(
+      cast<CXXExpansionStmtDecl>(ESD), Init, cast<DeclStmt>(ExpansionVar),
+      LParenLoc, ColonLoc, RParenLoc);
+}
+
 StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt *Body) {
   if (!Exp || !Body)
     return StmtError();
 
+  auto *Expansion = cast<CXXExpansionStmtPattern>(Exp);
+  assert(!Expansion->getDecl()->getInstantiations() &&
+         "should not rebuild expansion statement after instantiation");
+
+  Expansion->setBody(Body);
+  if (Expansion->hasDependentSize())
+    return Expansion;
+
+  // This can fail if this is an iterating expansion statement.
+  std::optional<uint64_t> NumInstantiations = ComputeExpansionSize(Expansion);
+  if (!NumInstantiations)
+    return StmtError();
+
+  // Collect shared statements.
+  SmallVector<Stmt *, 1> Shared;
+  if (Expansion->getInit())
+    Shared.push_back(Expansion->getInit());
+
+  assert(isa<CXXEnumeratingExpansionStmtPattern>(Expansion) && "TODO");
+
+  // Return an empty statement if the range is empty.
+  if (*NumInstantiations == 0) {
+    Expansion->getDecl()->setInstantiations(
+        CXXExpansionStmtInstantiation::Create(
+            Context, Expansion->getBeginLoc(), Expansion->getEndLoc(),
+            /*Instantiations=*/{}, Shared,
+            isa<CXXDestructuringExpansionStmtPattern>(Expansion)));
+    return Expansion;
+  }
+
+  // Create a compound statement binding the expansion variable and body.
+  Stmt *VarAndBody[] = {Expansion->getExpansionVarStmt(), Body};
+  Stmt *CombinedBody =
+      CompoundStmt::Create(Context, VarAndBody, FPOptionsOverride(),
+                           Body->getBeginLoc(), Body->getEndLoc());
+
+  // Expand the body for each instantiation.
+  SmallVector<Stmt *, 4> Instantiations;
+  CXXExpansionStmtDecl *ESD = Expansion->getDecl();
+  for (uint64_t I = 0; I < *NumInstantiations; ++I) {
+    // Now that we're expanding this, exit the context of the expansion stmt
+    // so that we no longer treat this as dependent.
+    ContextRAII CtxGuard(*this, CurContext->getParent(),
+                         /*NewThis=*/false);
+
+    TemplateArgument Arg{Context, llvm::APSInt::get(I),
+                         Context.getPointerDiffType()};
+    MultiLevelTemplateArgumentList MTArgList(ESD, Arg, true);
+    MTArgList.addOuterRetainedLevels(
+        Expansion->getDecl()->getIndexTemplateParm()->getDepth());
+
+    LocalInstantiationScope LIScope(*this, /*CombineWithOuterScope=*/true);
+    NonSFINAEContext _(*this);
+    InstantiatingTemplate Inst(*this, Body->getBeginLoc(), Expansion, Arg,
+                               Body->getSourceRange());
+
+    StmtResult Instantiation = SubstStmt(CombinedBody, MTArgList);
+    if (Instantiation.isInvalid())
+      return StmtError();
+    Instantiations.push_back(Instantiation.get());
+  }
+
+  auto *InstantiationsStmt = CXXExpansionStmtInstantiation::Create(
+      Context, Expansion->getBeginLoc(), Expansion->getEndLoc(), 
Instantiations,
+      Shared, isa<CXXDestructuringExpansionStmtPattern>(Expansion));
+
+  Expansion->getDecl()->setInstantiations(InstantiationsStmt);
+  return Expansion;
+}
+
+ExprResult
+Sema::BuildCXXExpansionInitListSelectExpr(CXXExpansionInitListExpr *Range,
+                                          Expr *Idx) {
+  if (Range->containsPackExpansion() || Idx->isValueDependent())
+    return new (Context) CXXExpansionInitListSelectExpr(Context, Range, Idx);
+
+  // The index is a DRE to a template parameter; we should never
+  // fail to evaluate it.
+  Expr::EvalResult ER;
+  if (!Idx->EvaluateAsInt(ER, Context))
+    llvm_unreachable("Failed to evaluate expansion index");
+
+  uint64_t I = ER.Val.getInt().getZExtValue();
+  return Range->getExprs()[I];
+}
+
+std::optional<uint64_t>
+Sema::ComputeExpansionSize(CXXExpansionStmtPattern *Expansion) {
+  assert(!Expansion->hasDependentSize());
+
+  if (isa<CXXEnumeratingExpansionStmtPattern>(Expansion))
+    return cast<CXXExpansionInitListSelectExpr>(
+               Expansion->getExpansionVariable()->getInit())
+        ->getRangeExpr()
+        ->getExprs()
+        .size();
+
   llvm_unreachable("TODO");
 }
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 35205f40cbcef..5957af710d38e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -573,6 +573,7 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() 
const {
   case PriorTemplateArgumentSubstitution:
   case ConstraintsCheck:
   case NestedRequirementConstraintsCheck:
+  case ExpansionStmtInstantiation:
     return true;
 
   case RequirementInstantiation:
@@ -759,6 +760,15 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
           PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
           /*Template=*/nullptr, /*TemplateArgs=*/{}) {}
 
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+    Sema &SemaRef, SourceLocation PointOfInstantiation,
+    CXXExpansionStmtPattern *ExpansionStmt, ArrayRef<TemplateArgument> TArgs,
+    SourceRange InstantiationRange)
+    : InstantiatingTemplate(
+          SemaRef, CodeSynthesisContext::ExpansionStmtInstantiation,
+          PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
+          /*Template=*/nullptr, /*TemplateArgs=*/TArgs) {}
+
 Sema::InstantiatingTemplate::InstantiatingTemplate(
     Sema &SemaRef, SourceLocation PointOfInstantiation,
     concepts::NestedRequirement *Req, ConstraintsCheck,
@@ -1260,6 +1270,9 @@ void 
Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) {
                                << /*isTemplateTemplateParam=*/true
                                << Active->InstantiationRange);
       break;
+    case CodeSynthesisContext::ExpansionStmtInstantiation:
+      Diags.Report(Active->PointOfInstantiation,
+                   diag::note_expansion_stmt_instantiation_here);
     }
   }
 }
@@ -1894,6 +1907,12 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation 
Loc, Decl *D) {
       maybeInstantiateFunctionParameterToScope(PVD))
     return nullptr;
 
+  if (isa<CXXExpansionStmtDecl>(D)) {
+    assert(SemaRef.CurrentInstantiationScope);
+    return cast<Decl *>(
+        *SemaRef.CurrentInstantiationScope->findInstantiationOf(D));
+  }
+
   return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
 }
 
@@ -2288,9 +2307,13 @@ ExprResult
 TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
                                                        ValueDecl *PD) {
   typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
-  llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
-    = getSema().CurrentInstantiationScope->findInstantiationOf(PD);
-  assert(Found && "no instantiation for parameter pack");
+  llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found =
+      getSema().CurrentInstantiationScope->getInstantiationOfIfExists(PD);
+
+  // This can happen when instantiating an expansion statement that contains
+  // a pack (e.g. `template for (auto x : {{ts...}})`).
+  if (!Found)
+    return E;
 
   Decl *TransformedDecl;
   if (DeclArgumentPack *Pack = dyn_cast<DeclArgumentPack *>(*Found)) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f8136c3c24a52..f88ddcb40adf7 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2089,7 +2089,37 @@ Decl 
*TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
 
 Decl *TemplateDeclInstantiator::VisitCXXExpansionStmtDecl(
     CXXExpansionStmtDecl *OldESD) {
-  llvm_unreachable("TODO");
+  Decl *Index = VisitNonTypeTemplateParmDecl(OldESD->getIndexTemplateParm());
+  CXXExpansionStmtDecl *NewESD = SemaRef.BuildCXXExpansionStmtDecl(
+      Owner, OldESD->getBeginLoc(), cast<NonTypeTemplateParmDecl>(Index));
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldESD, NewESD);
+
+  // If this was already expanded, only instantiate the expansion and
+  // don't touch the unexpanded expansion statement.
+  if (CXXExpansionStmtInstantiation *OldInst = OldESD->getInstantiations()) {
+    StmtResult NewInst = SemaRef.SubstStmt(OldInst, TemplateArgs);
+    if (NewInst.isInvalid())
+      return nullptr;
+
+    NewESD->setInstantiations(NewInst.getAs<CXXExpansionStmtInstantiation>());
+    NewESD->setExpansionPattern(OldESD->getExpansionPattern());
+    return NewESD;
+  }
+
+  // Enter the scope of this expansion statement; don't do this if we've
+  // already expanded it, as in that case we no longer want to treat its
+  // content as dependent.
+  Sema::ContextRAII Context(SemaRef, NewESD, /*NewThis=*/false);
+
+  StmtResult Expansion =
+      SemaRef.SubstStmt(OldESD->getExpansionPattern(), TemplateArgs);
+  if (Expansion.isInvalid())
+    return nullptr;
+
+  // The code that handles CXXExpansionStmtPattern takes care of calling
+  // setInstantiation() on the ESD if there was an expansion.
+  NewESD->setExpansionPattern(cast<CXXExpansionStmtPattern>(Expansion.get()));
+  return NewESD;
 }
 
 Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
@@ -7093,6 +7123,12 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation 
Loc, NamedDecl *D,
     // anonymous unions in class templates).
   }
 
+  if (CurrentInstantiationScope) {
+    if (auto Found = CurrentInstantiationScope->getInstantiationOfIfExists(D))
+      if (auto *FD = dyn_cast<NamedDecl>(cast<Decl *>(*Found)))
+        return FD;
+  }
+
   if (!ParentDependsOnArgs)
     return D;
 
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp 
b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 5b1aad3fa8470..b61148bf95738 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -912,10 +912,14 @@ bool Sema::CheckParameterPacksForExpansion(
     unsigned NewPackSize, PendingPackExpansionSize = 0;
     if (IsVarDeclPack) {
       // Figure out whether we're instantiating to an argument pack or not.
+      //
+      // The instantiation may not exist; this can happen when instantiating an
+      // expansion statement that contains a pack (e.g.
+      // `template for (auto x : {{ts...}})`).
       llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
-          CurrentInstantiationScope->findInstantiationOf(
+          CurrentInstantiationScope->getInstantiationOfIfExists(
               cast<NamedDecl *>(ParmPack.first));
-      if (isa<DeclArgumentPack *>(*Instantiation)) {
+      if (Instantiation && isa<DeclArgumentPack *>(*Instantiation)) {
         // We could expand this function parameter pack.
         NewPackSize = cast<DeclArgumentPack *>(*Instantiation)->size();
       } else {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index df25b1701207f..514a404c16ce5 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -9295,19 +9295,94 @@ 
TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
 template <typename Derived>
 StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtPattern(
     CXXExpansionStmtPattern *S) {
-  llvm_unreachable("TOOD");
+  CXXExpansionStmtDecl *NewESD = nullptr;
+  Stmt *Init = nullptr;
+  DeclStmt *ExpansionVarStmt = nullptr;
+  Decl *ESD =
+      getDerived().TransformDecl(S->getDecl()->getLocation(), S->getDecl());
+  if (!ESD || ESD->isInvalidDecl())
+    return StmtError();
+  NewESD = cast<CXXExpansionStmtDecl>(ESD);
+
+  Init = S->getInit();
+  if (Init) {
+    StmtResult SR = getDerived().TransformStmt(Init);
+    if (SR.isInvalid())
+      return StmtError();
+    Init = SR.get();
+  }
+
+  StmtResult ExpansionVar =
+      getDerived().TransformStmt(S->getExpansionVarStmt());
+  if (ExpansionVar.isInvalid())
+    return StmtError();
+  ExpansionVarStmt = cast<DeclStmt>(ExpansionVar.get());
+
+  CXXExpansionStmtPattern *NewPattern = nullptr;
+  if (S->isEnumerating()) {
+    NewPattern = CXXExpansionStmtPattern::CreateEnumerating(
+        SemaRef.Context, NewESD, Init, ExpansionVarStmt, S->getLParenLoc(),
+        S->getColonLoc(), S->getRParenLoc());
+  } else {
+    llvm_unreachable("TODO");
+  }
+
+  StmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return StmtError();
+
+  return SemaRef.FinishCXXExpansionStmt(NewPattern, Body.get());
 }
 
 template <typename Derived>
 StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtInstantiation(
     CXXExpansionStmtInstantiation *S) {
-  llvm_unreachable("TOOD");
+  bool SubStmtChanged = false;
+  auto TransformStmts = [&](SmallVectorImpl<Stmt *> &NewStmts,
+                            ArrayRef<Stmt *> OldStmts) {
+    for (Stmt *OldDS : OldStmts) {
+      StmtResult NewDS = getDerived().TransformStmt(OldDS);
+      if (NewDS.isInvalid())
+        return true;
+
+      SubStmtChanged |= NewDS.get() != OldDS;
+      NewStmts.push_back(NewDS.get());
+    }
+
+    return false;
+  };
+
+  SmallVector<Stmt *> SharedStmts;
+  SmallVector<Stmt *> Instantiations;
+
+  if (TransformStmts(SharedStmts, S->getSharedStmts()))
+    return StmtError();
+
+  if (TransformStmts(Instantiations, S->getInstantiations()))
+    return StmtError();
+
+  if (!getDerived().AlwaysRebuild() && !SubStmtChanged)
+    return S;
+
+  return CXXExpansionStmtInstantiation::Create(
+      SemaRef.Context, S->getBeginLoc(), S->getEndLoc(), Instantiations,
+      SharedStmts, S->shouldApplyLifetimeExtensionToSharedStmts());
 }
 
 template <typename Derived>
 ExprResult TreeTransform<Derived>::TransformCXXExpansionSelectExpr(
     CXXExpansionSelectExpr *E) {
-  llvm_unreachable("TOOD");
+  ExprResult Range = getDerived().TransformExpr(E->getRangeExpr());
+  ExprResult Idx = getDerived().TransformExpr(E->getIndexExpr());
+  if (Range.isInvalid() || Idx.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() && Range.get() == E->getRangeExpr() &&
+      Idx.get() == E->getIndexExpr())
+    return E;
+
+  return SemaRef.BuildCXXExpansionSelectExpr(
+      Range.getAs<InitListExpr>(), Idx.get());
 }
 
 template<typename Derived>
@@ -15642,7 +15717,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr 
*E) {
   // will be deemed as dependent even if there are no dependent template
   // arguments.
   // (A ClassTemplateSpecializationDecl is always a dependent context.)
-  while (DC->isRequiresExprBody())
+  while (DC->isRequiresExprBody() || isa<CXXExpansionStmtDecl>(DC))
     DC = DC->getParent();
   if ((getSema().isUnevaluatedContext() ||
        getSema().isConstantEvaluatedContext()) &&
diff --git a/clang/test/Parser/cxx2c-expansion-statements.cpp 
b/clang/test/Parser/cxx2c-expansion-statements.cpp
index 658257922b734..e58b9a189041c 100644
--- a/clang/test/Parser/cxx2c-expansion-statements.cpp
+++ b/clang/test/Parser/cxx2c-expansion-statements.cpp
@@ -10,56 +10,56 @@ struct initializer_list {
 
 void bad() {
   template for; // expected-error {{expected '(' after 'for'}}
-  template for (); // expected-error {{expected expression}} expected-error 
{{expected ';' in 'for' statement specifier}} expected-error {{expansion 
statement must be a range-based for loop}} expected-error {{TODO (expansion 
statements)}}
-  template for (;); // expected-error {{expected ';' in 'for' statement 
specifier}} expected-error {{expansion statement must be a range-based for 
loop}} expected-error {{TODO (expansion statements)}}
-  template for (;;); // expected-error {{expansion statement must be a 
range-based for loop}} expected-error {{TODO (expansion statements)}}
-  template for (int x;;); // expected-error {{expansion statement must be a 
range-based for loop}} expected-error {{TODO (expansion statements)}}
-  template for (x : {1}); // expected-error {{expansion statement requires 
type for expansion variable}} expected-error {{TODO (expansion statements)}}
-  template for (: {1}); // expected-error {{expected expression}} 
expected-error {{expected ';' in 'for' statement specifier}} expected-error 
{{expansion statement must be a range-based for loop}} expected-error {{TODO 
(expansion statements)}}
-  template for (auto y : {1})]; // expected-error {{expected expression}} 
expected-error {{TODO (expansion statements)}}
-  template for (auto y : {1}; // expected-error {{expected ')'}} expected-note 
{{to match this '('}} expected-error {{TODO (expansion statements)}}
-  template for (extern auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'extern'}} expected-error {{TODO (expansion 
statements)}}
-  template for (extern static auto y : {1, 2}); // expected-error {{cannot 
combine with previous 'extern' declaration specifier}} expected-error 
{{expansion variable 'y' may not be declared 'extern'}} expected-error {{TODO 
(expansion statements)}}
-  template for (static auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'static'}} expected-error {{TODO (expansion 
statements)}}
-  template for (thread_local auto y : {1, 2}); // expected-error 
{{'thread_local' variables must have global storage}} expected-error {{TODO 
(expansion statements)}}
-  template for (static thread_local auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'thread_local'}} expected-error 
{{TODO (expansion statements)}}
-  template for (__thread auto y : {1, 2}); // expected-error {{'__thread' 
variables must have global storage}} expected-error {{TODO (expansion 
statements)}}
-  template for (static __thread auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'static'}} expected-error {{TODO 
(expansion statements)}}
-  template for (constinit auto y : {1, 2}); // expected-error {{local variable 
cannot be declared 'constinit'}} expected-error {{TODO (expansion statements)}}
-  template for (consteval auto y : {1, 2});  // expected-error {{consteval can 
only be used in function declarations}} expected-error {{TODO (expansion 
statements)}}
-  template for (int x; extern auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'extern'}} expected-error {{TODO (expansion 
statements)}}
-  template for (int x; extern static auto y : {1, 2}); // expected-error 
{{cannot combine with previous 'extern' declaration specifier}} expected-error 
{{expansion variable 'y' may not be declared 'extern'}} expected-error {{TODO 
(expansion statements)}}
-  template for (int x; static auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'static'}} expected-error {{TODO (expansion 
statements)}}
-  template for (int x; thread_local auto y : {1, 2}); // expected-error 
{{'thread_local' variables must have global storage}} expected-error {{TODO 
(expansion statements)}}
-  template for (int x; static thread_local auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'thread_local'}} expected-error 
{{TODO (expansion statements)}}
-  template for (int x; __thread auto y : {1, 2}); // expected-error 
{{'__thread' variables must have global storage}} expected-error {{TODO 
(expansion statements)}}
-  template for (int x; static __thread auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'static'}} expected-error {{TODO 
(expansion statements)}}
-  template for (int x; constinit auto y : {1, 2}); // expected-error {{local 
variable cannot be declared 'constinit'}} expected-error {{TODO (expansion 
statements)}}
-  template for (int x; consteval auto y : {1, 2});  // expected-error 
{{consteval can only be used in function declarations}} expected-error {{TODO 
(expansion statements)}}
-  template for (auto y : {abc, -+, }); // expected-error {{use of undeclared 
identifier 'abc'}} expected-error {{expected expression}} expected-error {{TODO 
(expansion statements)}}
+  template for (); // expected-error {{expected expression}} expected-error 
{{expected ';' in 'for' statement specifier}} expected-error {{expansion 
statement must be a range-based for loop}}
+  template for (;); // expected-error {{expected ';' in 'for' statement 
specifier}} expected-error {{expansion statement must be a range-based for 
loop}}
+  template for (;;); // expected-error {{expansion statement must be a 
range-based for loop}}
+  template for (int x;;); // expected-error {{expansion statement must be a 
range-based for loop}}
+  template for (x : {1}); // expected-error {{expansion statement requires 
type for expansion variable}}
+  template for (: {1}); // expected-error {{expected expression}} 
expected-error {{expected ';' in 'for' statement specifier}} expected-error 
{{expansion statement must be a range-based for loop}}
+  template for (auto y : {1})]; // expected-error {{expected expression}}
+  template for (auto y : {1}; // expected-error {{expected ')'}} expected-note 
{{to match this '('}}
+  template for (extern auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'extern'}}
+  template for (extern static auto y : {1, 2}); // expected-error {{cannot 
combine with previous 'extern' declaration specifier}} expected-error 
{{expansion variable 'y' may not be declared 'extern'}}
+  template for (static auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'static'}}
+  template for (thread_local auto y : {1, 2}); // expected-error 
{{'thread_local' variables must have global storage}}
+  template for (static thread_local auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'thread_local'}}
+  template for (__thread auto y : {1, 2}); // expected-error {{'__thread' 
variables must have global storage}}
+  template for (static __thread auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'static'}}
+  template for (constinit auto y : {1, 2}); // expected-error {{local variable 
cannot be declared 'constinit'}}
+  template for (consteval auto y : {1, 2});  // expected-error {{consteval can 
only be used in function declarations}}
+  template for (int x; extern auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'extern'}}
+  template for (int x; extern static auto y : {1, 2}); // expected-error 
{{cannot combine with previous 'extern' declaration specifier}} expected-error 
{{expansion variable 'y' may not be declared 'extern'}}
+  template for (int x; static auto y : {1, 2}); // expected-error {{expansion 
variable 'y' may not be declared 'static'}}
+  template for (int x; thread_local auto y : {1, 2}); // expected-error 
{{'thread_local' variables must have global storage}}
+  template for (int x; static thread_local auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'thread_local'}}
+  template for (int x; __thread auto y : {1, 2}); // expected-error 
{{'__thread' variables must have global storage}}
+  template for (int x; static __thread auto y : {1, 2}); // expected-error 
{{expansion variable 'y' may not be declared 'static'}}
+  template for (int x; constinit auto y : {1, 2}); // expected-error {{local 
variable cannot be declared 'constinit'}}
+  template for (int x; consteval auto y : {1, 2});  // expected-error 
{{consteval can only be used in function declarations}}
+  template for (auto y : {abc, -+, }); // expected-error {{use of undeclared 
identifier 'abc'}} expected-error {{expected expression}}
   template for (3 : "error") // expected-error {{expansion statement 
declaration must declare a variable}} \
-                                expected-error {{expansion statement must be a 
range-based for loop}} expected-error {{TODO (expansion statements)}}
+                                expected-error {{expansion statement must be a 
range-based for loop}}
     ;
   template while (true) {} // expected-error {{'template while' is invalid}}
   template do {} while (true); // expected-error {{'template do' is invalid}}
-  for template (int x : {}) {} // expected-error {{'for template' is invalid; 
use 'template for' instead}} expected-error {{TODO (expansion statements)}}
+  for template (int x : {}) {} // expected-error {{'for template' is invalid; 
use 'template for' instead}}
 }
 
 void good() {
-  template for (auto y : {}); // expected-error {{TODO (expansion statements)}}
-  template for (auto y : {1, 2}); // expected-error {{TODO (expansion 
statements)}}
-  template for (int x; auto y : {1, 2}); // expected-error {{TODO (expansion 
statements)}}
-  template for (int x; int y : {1, 2}); // expected-error {{TODO (expansion 
statements)}}
-  template for (int x; constexpr auto y : {1, 2}); // expected-error {{TODO 
(expansion statements)}}
-  template for (int x; constexpr int y : {1, 2}); // expected-error {{TODO 
(expansion statements)}}
-  template for (constexpr int a : {1, 2}) { // expected-error {{TODO 
(expansion statements)}}
-    template for (constexpr int b : {1, 2}) { // expected-error {{TODO 
(expansion statements)}}
-      template for (constexpr int c : {1, 2}); // expected-error {{TODO 
(expansion statements)}}
+  template for (auto y : {});
+  template for (auto y : {1, 2});
+  template for (int x; auto y : {1, 2});
+  template for (int x; int y : {1, 2});
+  template for (int x; constexpr auto y : {1, 2});
+  template for (int x; constexpr int y : {1, 2});
+  template for (constexpr int a : {1, 2}) {
+    template for (constexpr int b : {1, 2}) {
+      template for (constexpr int c : {1, 2});
     }
   }
 }
 
 void trailing_comma() {
-  template for (int x : {1, 2,}) {} // expected-error {{TODO (expansion 
statements)}}
-  template for (int x : {,}) {} // expected-error {{expected expression}} 
expected-error {{TODO (expansion statements)}}
+  template for (int x : {1, 2,}) {}
+  template for (int x : {,}) {} // expected-error {{expected expression}}
 }

>From fc78491092ba0ee3de1370be7fd1b56b844e57d2 Mon Sep 17 00:00:00 2001
From: Sirraide <[email protected]>
Date: Wed, 3 Dec 2025 18:20:19 +0100
Subject: [PATCH 2/4] Eliminate CXXExpansionInitListExpr

---
 clang/include/clang/Sema/Sema.h |  5 ++---
 clang/lib/Sema/SemaExpand.cpp   | 34 +++++++++++++++++++++++----------
 2 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4d25143cffaf4..e99f42b5e8f9f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15659,9 +15659,8 @@ class Sema final : public SemaBase {
                                                      SourceLocation ColonLoc,
                                                      SourceLocation RParenLoc);
 
-  ExprResult
-  BuildCXXExpansionInitListSelectExpr(CXXExpansionInitListExpr *Range,
-                                      Expr *Idx);
+  ExprResult BuildCXXExpansionInitListSelectExpr(InitListExpr *Range,
+                                                 Expr *Idx);
 
   std::optional<uint64_t>
   ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index f1cd2baa9ae39..7dd57ca86c36d 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -42,6 +42,21 @@ static bool FinaliseExpansionVar(Sema &S, VarDecl 
*ExpansionVar,
   return ExpansionVar->isInvalidDecl();
 }
 
+static auto InitListContainsPack(const InitListExpr *ILE) {
+  return llvm::any_of(ArrayRef(ILE->getInits(), ILE->getNumInits()),
+                      [](const Expr *E) { return isa<PackExpansionExpr>(E); });
+}
+
+static bool HasDependentSize(const CXXExpansionStmtPattern* pattern) {
+  if (isa<CXXEnumeratingExpansionStmtPattern>(pattern)) {
+    auto *SelectExpr = cast<CXXExpansionInitListSelectExpr>(
+        pattern->getExpansionVariable()->getInit());
+    return InitListContainsPack(SelectExpr->getRangeExpr());
+  }
+
+  llvm_unreachable("Invalid expansion statement class");
+}
+
 CXXExpansionStmtDecl *
 Sema::ActOnCXXExpansionStmtDecl(unsigned TemplateDepth,
                                 SourceLocation TemplateKWLoc) {
@@ -74,8 +89,7 @@ Sema::BuildCXXExpansionStmtDecl(DeclContext *Ctx, 
SourceLocation TemplateKWLoc,
 ExprResult Sema::ActOnCXXExpansionInitList(MultiExprArg SubExprs,
                                            SourceLocation LBraceLoc,
                                            SourceLocation RBraceLoc) {
-  return CXXExpansionInitListExpr::Create(Context, SubExprs, LBraceLoc,
-                                          RBraceLoc);
+  return new (Context) InitListExpr(Context, LBraceLoc, SubExprs, RBraceLoc);
 }
 
 StmtResult Sema::ActOnCXXExpansionStmtPattern(
@@ -99,7 +113,8 @@ StmtResult Sema::ActOnCXXExpansionStmtPattern(
     return StmtError();
 
   // This is an enumerating expansion statement.
-  if (auto *ILE = dyn_cast<CXXExpansionInitListExpr>(ExpansionInitializer)) {
+  if (auto *ILE = dyn_cast<InitListExpr>(ExpansionInitializer)) {
+    assert(ILE->isSyntacticForm());
     ExprResult Initializer =
         BuildCXXExpansionInitListSelectExpr(ILE, BuildIndexDRE(*this, ESD));
     if (FinaliseExpansionVar(*this, ExpansionVar, Initializer))
@@ -133,7 +148,7 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt 
*Body) {
          "should not rebuild expansion statement after instantiation");
 
   Expansion->setBody(Body);
-  if (Expansion->hasDependentSize())
+  if (HasDependentSize(Expansion))
     return Expansion;
 
   // This can fail if this is an iterating expansion statement.
@@ -199,9 +214,9 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt 
*Body) {
 }
 
 ExprResult
-Sema::BuildCXXExpansionInitListSelectExpr(CXXExpansionInitListExpr *Range,
+Sema::BuildCXXExpansionInitListSelectExpr(InitListExpr *Range,
                                           Expr *Idx) {
-  if (Range->containsPackExpansion() || Idx->isValueDependent())
+  if (Idx->isValueDependent() || InitListContainsPack(Range))
     return new (Context) CXXExpansionInitListSelectExpr(Context, Range, Idx);
 
   // The index is a DRE to a template parameter; we should never
@@ -211,19 +226,18 @@ 
Sema::BuildCXXExpansionInitListSelectExpr(CXXExpansionInitListExpr *Range,
     llvm_unreachable("Failed to evaluate expansion index");
 
   uint64_t I = ER.Val.getInt().getZExtValue();
-  return Range->getExprs()[I];
+  return Range->getInit(I);
 }
 
 std::optional<uint64_t>
 Sema::ComputeExpansionSize(CXXExpansionStmtPattern *Expansion) {
-  assert(!Expansion->hasDependentSize());
+  assert(!HasDependentSize(Expansion));
 
   if (isa<CXXEnumeratingExpansionStmtPattern>(Expansion))
     return cast<CXXExpansionInitListSelectExpr>(
                Expansion->getExpansionVariable()->getInit())
         ->getRangeExpr()
-        ->getExprs()
-        .size();
+        ->getNumInits();
 
   llvm_unreachable("TODO");
 }

>From 48718a4319bff8a75a3a1a384d3a4c2185468c04 Mon Sep 17 00:00:00 2001
From: Sirraide <[email protected]>
Date: Wed, 3 Dec 2025 20:38:22 +0100
Subject: [PATCH 3/4] Merge all pattern kinds into a single AST node

---
 clang/lib/Sema/SemaExpand.cpp | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 7dd57ca86c36d..83231ecaa835a 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -47,14 +47,21 @@ static auto InitListContainsPack(const InitListExpr *ILE) {
                       [](const Expr *E) { return isa<PackExpansionExpr>(E); });
 }
 
-static bool HasDependentSize(const CXXExpansionStmtPattern* pattern) {
-  if (isa<CXXEnumeratingExpansionStmtPattern>(pattern)) {
+static bool HasDependentSize(const CXXExpansionStmtPattern *Pattern) {
+  switch (Pattern->getKind()) {
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Enumerating: {
     auto *SelectExpr = cast<CXXExpansionInitListSelectExpr>(
-        pattern->getExpansionVariable()->getInit());
+        Pattern->getExpansionVariable()->getInit());
     return InitListContainsPack(SelectExpr->getRangeExpr());
   }
 
-  llvm_unreachable("Invalid expansion statement class");
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Iterating:
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Destructuring:
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Dependent:
+    llvm_unreachable("TODO");
+  }
+
+  llvm_unreachable("invalid pattern kind");
 }
 
 CXXExpansionStmtDecl *
@@ -134,9 +141,9 @@ StmtResult Sema::ActOnCXXExpansionStmtPattern(
 StmtResult Sema::BuildCXXEnumeratingExpansionStmtPattern(
     Decl *ESD, Stmt *Init, Stmt *ExpansionVar, SourceLocation LParenLoc,
     SourceLocation ColonLoc, SourceLocation RParenLoc) {
-  return new (Context) CXXEnumeratingExpansionStmtPattern(
-      cast<CXXExpansionStmtDecl>(ESD), Init, cast<DeclStmt>(ExpansionVar),
-      LParenLoc, ColonLoc, RParenLoc);
+  return CXXExpansionStmtPattern::CreateEnumerating(
+      Context, cast<CXXExpansionStmtDecl>(ESD), Init,
+      cast<DeclStmt>(ExpansionVar), LParenLoc, ColonLoc, RParenLoc);
 }
 
 StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt *Body) {
@@ -161,15 +168,14 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt 
*Body) {
   if (Expansion->getInit())
     Shared.push_back(Expansion->getInit());
 
-  assert(isa<CXXEnumeratingExpansionStmtPattern>(Expansion) && "TODO");
+  assert(Expansion->isEnumerating() && "TODO");
 
   // Return an empty statement if the range is empty.
   if (*NumInstantiations == 0) {
     Expansion->getDecl()->setInstantiations(
         CXXExpansionStmtInstantiation::Create(
             Context, Expansion->getBeginLoc(), Expansion->getEndLoc(),
-            /*Instantiations=*/{}, Shared,
-            isa<CXXDestructuringExpansionStmtPattern>(Expansion)));
+            /*Instantiations=*/{}, Shared, Expansion->isDestructuring()));
     return Expansion;
   }
 
@@ -207,7 +213,7 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt 
*Body) {
 
   auto *InstantiationsStmt = CXXExpansionStmtInstantiation::Create(
       Context, Expansion->getBeginLoc(), Expansion->getEndLoc(), 
Instantiations,
-      Shared, isa<CXXDestructuringExpansionStmtPattern>(Expansion));
+      Shared, Expansion->isDestructuring());
 
   Expansion->getDecl()->setInstantiations(InstantiationsStmt);
   return Expansion;
@@ -233,7 +239,7 @@ std::optional<uint64_t>
 Sema::ComputeExpansionSize(CXXExpansionStmtPattern *Expansion) {
   assert(!HasDependentSize(Expansion));
 
-  if (isa<CXXEnumeratingExpansionStmtPattern>(Expansion))
+  if (Expansion->isEnumerating())
     return cast<CXXExpansionInitListSelectExpr>(
                Expansion->getExpansionVariable()->getInit())
         ->getRangeExpr()

>From 2a9bd94f9305ba1c00071a9a2c784a04de61491a Mon Sep 17 00:00:00 2001
From: Sirraide <[email protected]>
Date: Wed, 3 Dec 2025 22:07:58 +0100
Subject: [PATCH 4/4] Only use a single CXXExpansionSelectExpr

---
 clang/include/clang/Sema/Sema.h |  3 +--
 clang/lib/Sema/SemaExpand.cpp   | 12 +++++-------
 clang/lib/Sema/TreeTransform.h  |  4 ++--
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e99f42b5e8f9f..c5711ab7ea751 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15659,8 +15659,7 @@ class Sema final : public SemaBase {
                                                      SourceLocation ColonLoc,
                                                      SourceLocation RParenLoc);
 
-  ExprResult BuildCXXExpansionInitListSelectExpr(InitListExpr *Range,
-                                                 Expr *Idx);
+  ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx);
 
   std::optional<uint64_t>
   ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 83231ecaa835a..a0f5e852ebdb1 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -50,7 +50,7 @@ static auto InitListContainsPack(const InitListExpr *ILE) {
 static bool HasDependentSize(const CXXExpansionStmtPattern *Pattern) {
   switch (Pattern->getKind()) {
   case CXXExpansionStmtPattern::ExpansionStmtKind::Enumerating: {
-    auto *SelectExpr = cast<CXXExpansionInitListSelectExpr>(
+    auto *SelectExpr = cast<CXXExpansionSelectExpr>(
         Pattern->getExpansionVariable()->getInit());
     return InitListContainsPack(SelectExpr->getRangeExpr());
   }
@@ -123,7 +123,7 @@ StmtResult Sema::ActOnCXXExpansionStmtPattern(
   if (auto *ILE = dyn_cast<InitListExpr>(ExpansionInitializer)) {
     assert(ILE->isSyntacticForm());
     ExprResult Initializer =
-        BuildCXXExpansionInitListSelectExpr(ILE, BuildIndexDRE(*this, ESD));
+        BuildCXXExpansionSelectExpr(ILE, BuildIndexDRE(*this, ESD));
     if (FinaliseExpansionVar(*this, ExpansionVar, Initializer))
       return StmtError();
 
@@ -219,11 +219,9 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt 
*Body) {
   return Expansion;
 }
 
-ExprResult
-Sema::BuildCXXExpansionInitListSelectExpr(InitListExpr *Range,
-                                          Expr *Idx) {
+ExprResult Sema::BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx) {
   if (Idx->isValueDependent() || InitListContainsPack(Range))
-    return new (Context) CXXExpansionInitListSelectExpr(Context, Range, Idx);
+    return new (Context) CXXExpansionSelectExpr(Context, Range, Idx);
 
   // The index is a DRE to a template parameter; we should never
   // fail to evaluate it.
@@ -240,7 +238,7 @@ Sema::ComputeExpansionSize(CXXExpansionStmtPattern 
*Expansion) {
   assert(!HasDependentSize(Expansion));
 
   if (Expansion->isEnumerating())
-    return cast<CXXExpansionInitListSelectExpr>(
+    return cast<CXXExpansionSelectExpr>(
                Expansion->getExpansionVariable()->getInit())
         ->getRangeExpr()
         ->getNumInits();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 514a404c16ce5..fc646f5051905 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -9381,8 +9381,8 @@ ExprResult 
TreeTransform<Derived>::TransformCXXExpansionSelectExpr(
       Idx.get() == E->getIndexExpr())
     return E;
 
-  return SemaRef.BuildCXXExpansionSelectExpr(
-      Range.getAs<InitListExpr>(), Idx.get());
+  return SemaRef.BuildCXXExpansionSelectExpr(Range.getAs<InitListExpr>(),
+                                             Idx.get());
 }
 
 template<typename Derived>

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to