[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 6: Destructuring Expansion Statements) (PR #169685)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Dec 5 09:55:09 PST 2025
https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/169685
>From 07d55ff90ee97ed9393f5b2d0aeadc43f0fc196f Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 26 Nov 2025 17:00:57 +0100
Subject: [PATCH 1/6] [Clang] [C++26] Expansion Statements (Part 6)
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 +
clang/include/clang/Sema/Sema.h | 3 +
clang/lib/Sema/SemaExpand.cpp | 100 +++++++++++++++++-
clang/lib/Sema/TreeTransform.h | 81 ++++++++++----
4 files changed, 162 insertions(+), 24 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a92a3a6a7c331..208c885909b00 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3712,6 +3712,8 @@ def err_conflicting_codeseg_attribute : Error<
def warn_duplicate_codeseg_attribute : Warning<
"duplicate code segment specifiers">, InGroup<Section>;
+def err_expansion_stmt_invalid_init : Error<
+ "cannot expand expression of type %0">;
def err_expansion_stmt_vla : Error<
"cannot expand variable length array type %0">;
def err_expansion_stmt_incomplete : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0adc570c73011..409e1d4e1b8ae 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15713,6 +15713,9 @@ class Sema final : public SemaBase {
ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx);
+ ExprResult BuildCXXDestructuringExpansionSelectExpr(DecompositionDecl *DD,
+ Expr *Idx);
+
std::optional<uint64_t>
ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
///@}
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 40891e96e97de..315a4bdfd3a6c 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -220,6 +220,52 @@ TryBuildIterableExpansionStmtInitializer(Sema &S, Expr *ExpansionInitializer,
return Data;
}
+static StmtResult BuildDestructuringCXXExpansionStmt(
+ Sema &S, Expr *ExpansionInitializer, SourceLocation ColonLoc,
+ bool VarIsConstexpr,
+ ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps) {
+ auto Ctx = Sema::ExpressionEvaluationContext::PotentiallyEvaluated;
+ if (VarIsConstexpr)
+ Ctx = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
+ EnterExpressionEvaluationContext ExprEvalCtx(S, Ctx);
+
+ // The declarations should be attached to the parent decl context.
+ Sema::ContextRAII CtxGuard(
+ S, S.CurContext->getEnclosingNonExpansionStatementContext(),
+ /*NewThis=*/false);
+
+ UnsignedOrNone Arity =
+ S.GetDecompositionElementCount(ExpansionInitializer->getType(), ColonLoc);
+
+ if (!Arity) {
+ S.Diag(ExpansionInitializer->getBeginLoc(),
+ diag::err_expansion_stmt_invalid_init)
+ << ExpansionInitializer->getType()
+ << ExpansionInitializer->getSourceRange();
+ return StmtError();
+ }
+
+ QualType AutoRRef = S.Context.getAutoRRefDeductType();
+ SmallVector<BindingDecl *> Bindings;
+ for (unsigned I = 0; I < *Arity; ++I)
+ Bindings.push_back(BindingDecl::Create(
+ S.Context, S.CurContext, ColonLoc,
+ S.getPreprocessor().getIdentifierInfo("__u" + std::to_string(I)),
+ AutoRRef));
+
+ TypeSourceInfo *TSI = S.Context.getTrivialTypeSourceInfo(AutoRRef);
+ auto *DD =
+ DecompositionDecl::Create(S.Context, S.CurContext, ColonLoc, ColonLoc,
+ AutoRRef, TSI, SC_Auto, Bindings);
+
+ if (VarIsConstexpr)
+ DD->setConstexpr(true);
+
+ S.ApplyForRangeOrExpansionStatementLifetimeExtension(DD, LifetimeExtendTemps);
+ S.AddInitializerToDecl(DD, ExpansionInitializer, false);
+ return S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(DD), ColonLoc, ColonLoc);
+}
+
CXXExpansionStmtDecl *
Sema::ActOnCXXExpansionStmtDecl(unsigned TemplateDepth,
SourceLocation TemplateKWLoc) {
@@ -368,8 +414,31 @@ StmtResult Sema::BuildNonEnumeratingCXXExpansionStmtPattern(
Data.EndDecl, LParenLoc, ColonLoc, RParenLoc);
}
- Diag(ESD->getLocation(), diag::err_expansion_statements_todo);
- return StmtError();
+ // If not, try destructuring.
+ StmtResult DecompDeclStmt = BuildDestructuringCXXExpansionStmt(
+ *this, ExpansionInitializer, ColonLoc, ExpansionVar->isConstexpr(),
+ LifetimeExtendTemps);
+ if (DecompDeclStmt.isInvalid()) {
+ ActOnInitializerError(ExpansionVar);
+ return StmtError();
+ }
+
+ auto *DS = DecompDeclStmt.getAs<DeclStmt>();
+ auto *DD = cast<DecompositionDecl>(DS->getSingleDecl());
+ if (DD->isInvalidDecl())
+ return StmtError();
+
+ ExprResult Select = BuildCXXDestructuringExpansionSelectExpr(DD, Index);
+ if (Select.isInvalid()) {
+ ActOnInitializerError(ExpansionVar);
+ return StmtError();
+ }
+
+ if (FinaliseExpansionVar(*this, ExpansionVar, Select))
+ return StmtError();
+
+ return new (Context) CXXDestructuringExpansionStmtPattern(
+ ESD, Init, ExpansionVarStmt, DS, LParenLoc, ColonLoc, RParenLoc);
}
StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt *Body) {
@@ -409,8 +478,8 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt *Body) {
Shared.push_back(Expansion->getRangeVarStmt());
Shared.push_back(Expansion->getBeginVarStmt());
Shared.push_back(Expansion->getEndVarStmt());
- } else {
- assert(Expansion->isEnumerating() && "TODO");
+ } else if (Expansion->isDestructuring()) {
+ Shared.push_back(Expansion->getDecompositionDeclStmt());
}
// Return an empty statement if the range is empty.
@@ -471,6 +540,23 @@ ExprResult Sema::BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx) {
return Range->getInit(I);
}
+ExprResult Sema::BuildCXXDestructuringExpansionSelectExpr(DecompositionDecl *DD,
+ Expr *Idx) {
+ if (Idx->isValueDependent())
+ return new (Context) CXXDestructuringExpansionSelectExpr(Context, DD, Idx);
+
+ Expr::EvalResult ER;
+ if (!Idx->EvaluateAsInt(ER, Context))
+ llvm_unreachable("Failed to evaluate expansion index");
+
+ uint64_t I = ER.Val.getInt().getZExtValue();
+ MarkAnyDeclReferenced(Idx->getBeginLoc(), DD, true);
+ if (auto *BD = DD->bindings()[I]; auto *HVD = BD->getHoldingVar())
+ return HVD->getInit();
+ else
+ return BD->getBinding();
+}
+
std::optional<uint64_t>
Sema::ComputeExpansionSize(CXXExpansionStmtPattern *Expansion) {
assert(!HasDependentSize(Expansion));
@@ -663,5 +749,9 @@ Sema::ComputeExpansionSize(CXXExpansionStmtPattern *Expansion) {
return ER.Val.getInt().getZExtValue();
}
- llvm_unreachable("TODO");
+ if (auto *Destructuring =
+ dyn_cast<CXXDestructuringExpansionStmtPattern>(Expansion))
+ return Destructuring->getDecompositionDecl()->bindings().size();
+
+ llvm_unreachable("Invalid expansion statement class");
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 58ba5fadd6f08..467092593eb20 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -9297,28 +9297,51 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
template <typename Derived>
StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtPattern(
CXXExpansionStmtPattern *S) {
+ ExprResult ExpansionInitializer;
+ SmallVector<MaterializeTemporaryExpr *, 8> LifetimeExtendTemps;
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())
+ // Collect lifetime-extended temporaries in case this ends up being a
+ // destructuring expansion statement (for other kinds of expansion statements,
+ // this should make no difference since we ignore 'LifetimeExtendTemps' for
+ // those).
+ {
+ EnterExpressionEvaluationContext ExprEvalCtx(
+ SemaRef, SemaRef.currentEvaluationContext().Context);
+ SemaRef.currentEvaluationContext().InLifetimeExtendingContext = true;
+ SemaRef.currentEvaluationContext().RebuildDefaultArgOrDefaultInit = true;
+ Decl *ESD =
+ getDerived().TransformDecl(S->getDecl()->getLocation(), S->getDecl());
+ if (!ESD || ESD->isInvalidDecl())
return StmtError();
- Init = SR.get();
- }
+ NewESD = cast<CXXExpansionStmtDecl>(ESD);
- StmtResult ExpansionVar =
- getDerived().TransformStmt(S->getExpansionVarStmt());
- if (ExpansionVar.isInvalid())
- return StmtError();
- ExpansionVarStmt = cast<DeclStmt>(ExpansionVar.get());
+ 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());
+
+ if (S->isDependent()) {
+ ExpansionInitializer =
+ getDerived().TransformExpr(S->getExpansionInitializer());
+ if (ExpansionInitializer.isInvalid())
+ return StmtError();
+
+ LifetimeExtendTemps =
+ SemaRef.currentEvaluationContext().ForRangeLifetimeExtendTemps;
+ }
+ }
CXXExpansionStmtPattern *NewPattern = nullptr;
if (S->isEnumerating()) {
@@ -9355,7 +9378,12 @@ StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtPattern(
NewPattern = cast<CXXExpansionStmtPattern>(Res.get());
} else {
- llvm_unreachable("TODO");
+ // The only time we instantiate an expansion statement is if its expansion
+ // size is dependent (otherwise, we only instantiate the expansions and
+ // leave the underlying CXXExpansionStmtPattern as-is). Since destructuring
+ // expansion statements never have a dependent size, we should never get
+ // here.
+ llvm_unreachable("destructuring pattern should never be instantiated");
}
StmtResult Body = getDerived().TransformStmt(S->getBody());
@@ -9386,8 +9414,23 @@ StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtInstantiation(
SmallVector<Stmt *> SharedStmts;
SmallVector<Stmt *> Instantiations;
- if (TransformStmts(SharedStmts, S->getSharedStmts()))
- return StmtError();
+ // Apply lifetime extension to the shared statements if this was a
+ // destructuring expansion statement.
+ {
+ EnterExpressionEvaluationContext ExprEvalCtx(
+ SemaRef, SemaRef.currentEvaluationContext().Context);
+ SemaRef.currentEvaluationContext().InLifetimeExtendingContext = true;
+ SemaRef.currentEvaluationContext().RebuildDefaultArgOrDefaultInit = true;
+ if (TransformStmts(SharedStmts, S->getSharedStmts()))
+ return StmtError();
+
+ if (S->shouldApplyLifetimeExtensionToSharedStmts()) {
+ auto *VD =
+ cast<VarDecl>(cast<DeclStmt>(SharedStmts.front())->getSingleDecl());
+ SemaRef.ApplyForRangeOrExpansionStatementLifetimeExtension(
+ VD, SemaRef.currentEvaluationContext().ForRangeLifetimeExtendTemps);
+ }
+ }
if (TransformStmts(Instantiations, S->getInstantiations()))
return StmtError();
>From da379a8a60d3a0c64562eae96a3eba8b36fdae3a Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 3 Dec 2025 18:23:18 +0100
Subject: [PATCH 2/6] Eliminate CXXExpansionInitListExpr
---
clang/lib/Sema/SemaExpand.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 315a4bdfd3a6c..45f99530c9f20 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -85,7 +85,7 @@ static bool HasDependentSize(const CXXExpansionStmtPattern *Pattern) {
return true;
case CXXExpansionStmtPattern::ExpansionStmtKind::Destructuring:
- llvm_unreachable("TODO");
+ return false;
}
llvm_unreachable("invalid pattern kind");
>From d2afde884d1b382d47f619af3f09d8bae74081ea Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 3 Dec 2025 20:35:03 +0100
Subject: [PATCH 3/6] Fix more rebase issues
---
clang/lib/Sema/TreeTransform.h | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 467092593eb20..fc314c34a3065 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -9363,15 +9363,10 @@ StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtPattern(
Range.getAs<DeclStmt>(), Begin.getAs<DeclStmt>(), End.getAs<DeclStmt>(),
S->getLParenLoc(), S->getColonLoc(), S->getRParenLoc());
} else if (S->isDependent()) {
- ExprResult ExpansionInitializer =
- getDerived().TransformExpr(S->getExpansionInitializer());
- if (ExpansionInitializer.isInvalid())
- return StmtError();
-
StmtResult Res = SemaRef.BuildNonEnumeratingCXXExpansionStmtPattern(
NewESD, Init, ExpansionVarStmt, ExpansionInitializer.get(),
S->getLParenLoc(), S->getColonLoc(), S->getRParenLoc(),
- /*LifetimeExtendTemps=*/{});
+ LifetimeExtendTemps);
if (Res.isInvalid())
return StmtError();
>From 228c9973c48ab786f4818e79a2dd66da906db096 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 3 Dec 2025 20:44:27 +0100
Subject: [PATCH 4/6] Merge all pattern kinds into a single AST node
---
clang/lib/Sema/SemaExpand.cpp | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 45f99530c9f20..4c9eeac60cdae 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -437,8 +437,8 @@ StmtResult Sema::BuildNonEnumeratingCXXExpansionStmtPattern(
if (FinaliseExpansionVar(*this, ExpansionVar, Select))
return StmtError();
- return new (Context) CXXDestructuringExpansionStmtPattern(
- ESD, Init, ExpansionVarStmt, DS, LParenLoc, ColonLoc, RParenLoc);
+ return CXXExpansionStmtPattern::CreateDestructuring(
+ Context, ESD, Init, ExpansionVarStmt, DS, LParenLoc, ColonLoc, RParenLoc);
}
StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt *Body) {
@@ -749,9 +749,6 @@ Sema::ComputeExpansionSize(CXXExpansionStmtPattern *Expansion) {
return ER.Val.getInt().getZExtValue();
}
- if (auto *Destructuring =
- dyn_cast<CXXDestructuringExpansionStmtPattern>(Expansion))
- return Destructuring->getDecompositionDecl()->bindings().size();
-
- llvm_unreachable("Invalid expansion statement class");
+ assert(Expansion->isDestructuring());
+ return Expansion->getDecompositionDecl()->bindings().size();
}
>From 56c3bfc36f824fc2f6743b790adf0ee742f07b46 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 3 Dec 2025 22:04:53 +0100
Subject: [PATCH 5/6] Only use a single CXXExpansionSelectExpr
---
clang/include/clang/Sema/Sema.h | 3 ---
clang/lib/Sema/SemaExpand.cpp | 33 +++++++++++++++------------------
2 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 409e1d4e1b8ae..0adc570c73011 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15713,9 +15713,6 @@ class Sema final : public SemaBase {
ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx);
- ExprResult BuildCXXDestructuringExpansionSelectExpr(DecompositionDecl *DD,
- Expr *Idx);
-
std::optional<uint64_t>
ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
///@}
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 4c9eeac60cdae..89b9f41cd3330 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -428,7 +428,19 @@ StmtResult Sema::BuildNonEnumeratingCXXExpansionStmtPattern(
if (DD->isInvalidDecl())
return StmtError();
- ExprResult Select = BuildCXXDestructuringExpansionSelectExpr(DD, Index);
+ // Synthesise an InitListExpr to store DREs to the BindingDecls; this
+ // essentially lets us desugar the expansion of a destructuring expansion
+ // statement to that of an enumerating expansion statement.
+ SmallVector<Expr *> Bindings;
+ for (BindingDecl *BD : DD->bindings()) {
+ auto *HVD = BD->getHoldingVar();
+ Bindings.push_back(HVD ? HVD->getInit() : BD->getBinding());
+ }
+
+ ExprResult Select = BuildCXXExpansionSelectExpr(
+ new (Context) InitListExpr(Context, ColonLoc, Bindings, ColonLoc),
+ Index);
+
if (Select.isInvalid()) {
ActOnInitializerError(ExpansionVar);
return StmtError();
@@ -480,6 +492,8 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt *Body) {
Shared.push_back(Expansion->getEndVarStmt());
} else if (Expansion->isDestructuring()) {
Shared.push_back(Expansion->getDecompositionDeclStmt());
+ MarkAnyDeclReferenced(Exp->getBeginLoc(), Expansion->getDecompositionDecl(),
+ true);
}
// Return an empty statement if the range is empty.
@@ -540,23 +554,6 @@ ExprResult Sema::BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx) {
return Range->getInit(I);
}
-ExprResult Sema::BuildCXXDestructuringExpansionSelectExpr(DecompositionDecl *DD,
- Expr *Idx) {
- if (Idx->isValueDependent())
- return new (Context) CXXDestructuringExpansionSelectExpr(Context, DD, Idx);
-
- Expr::EvalResult ER;
- if (!Idx->EvaluateAsInt(ER, Context))
- llvm_unreachable("Failed to evaluate expansion index");
-
- uint64_t I = ER.Val.getInt().getZExtValue();
- MarkAnyDeclReferenced(Idx->getBeginLoc(), DD, true);
- if (auto *BD = DD->bindings()[I]; auto *HVD = BD->getHoldingVar())
- return HVD->getInit();
- else
- return BD->getBinding();
-}
-
std::optional<uint64_t>
Sema::ComputeExpansionSize(CXXExpansionStmtPattern *Expansion) {
assert(!HasDependentSize(Expansion));
>From 36ff60ce041cc48102043520a375deebf1d2995c Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 3 Dec 2025 22:19:52 +0100
Subject: [PATCH 6/6] Rename a function and update a comment
---
clang/lib/Sema/SemaExpand.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 89b9f41cd3330..6fa1ad9856783 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -220,7 +220,7 @@ TryBuildIterableExpansionStmtInitializer(Sema &S, Expr *ExpansionInitializer,
return Data;
}
-static StmtResult BuildDestructuringCXXExpansionStmt(
+static StmtResult BuildDestructuringDecompositionDecl(
Sema &S, Expr *ExpansionInitializer, SourceLocation ColonLoc,
bool VarIsConstexpr,
ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps) {
@@ -415,7 +415,7 @@ StmtResult Sema::BuildNonEnumeratingCXXExpansionStmtPattern(
}
// If not, try destructuring.
- StmtResult DecompDeclStmt = BuildDestructuringCXXExpansionStmt(
+ StmtResult DecompDeclStmt = BuildDestructuringDecompositionDecl(
*this, ExpansionInitializer, ColonLoc, ExpansionVar->isConstexpr(),
LifetimeExtendTemps);
if (DecompDeclStmt.isInvalid()) {
@@ -428,9 +428,9 @@ StmtResult Sema::BuildNonEnumeratingCXXExpansionStmtPattern(
if (DD->isInvalidDecl())
return StmtError();
- // Synthesise an InitListExpr to store DREs to the BindingDecls; this
- // essentially lets us desugar the expansion of a destructuring expansion
- // statement to that of an enumerating expansion statement.
+ // Synthesise an InitListExpr to store the bindings; this essentially lets us
+ // desugar the expansion of a destructuring expansion statement to that of an
+ // enumerating expansion statement.
SmallVector<Expr *> Bindings;
for (BindingDecl *BD : DD->bindings()) {
auto *HVD = BD->getHoldingVar();
More information about the llvm-branch-commits
mailing list