@@ -204,6 +204,14 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
204204 case Stmt::CXXForRangeStmtClass:
205205 EmitCXXForRangeStmt (cast<CXXForRangeStmt>(*S), Attrs);
206206 break ;
207+ case Stmt::CXXEnumeratingExpansionStmtPatternClass:
208+ case Stmt::CXXIteratingExpansionStmtPatternClass:
209+ case Stmt::CXXDestructuringExpansionStmtPatternClass:
210+ case Stmt::CXXDependentExpansionStmtPatternClass:
211+ llvm_unreachable (" unexpanded expansion statements should not be emitted" );
212+ case Stmt::CXXExpansionStmtInstantiationClass:
213+ EmitCXXExpansionStmtInstantiation (cast<CXXExpansionStmtInstantiation>(*S));
214+ break ;
207215 case Stmt::SEHTryStmtClass:
208216 EmitSEHTryStmt (cast<SEHTryStmt>(*S));
209217 break ;
@@ -1556,6 +1564,44 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
15561564 }
15571565}
15581566
1567+ void CodeGenFunction::EmitCXXExpansionStmtInstantiation (
1568+ const CXXExpansionStmtInstantiation &S) {
1569+ // FIXME: For reasons beyond my understanding, two scopes are required to emit
1570+ // the destructors of lifetime-extended temporaries in the right place, but
1571+ // only in some templates. There are some other issues with lifetime-extended
1572+ // temporaries currently (https://github.com/llvm/llvm-project/issues/165182);
1573+ // perhaps resolving those will allow us to remove the second scope here
1574+ // because there really ought to be a better way of doing this.
1575+ LexicalScope Scope (*this , S.getSourceRange ());
1576+ LexicalScope Scope2 (*this , S.getSourceRange ());
1577+
1578+ for (const Stmt *DS : S.getSharedStmts ())
1579+ EmitStmt (DS);
1580+
1581+ if (S.getInstantiations ().empty () || !HaveInsertPoint ())
1582+ return ;
1583+
1584+ JumpDest ExpandExit = getJumpDestInCurrentScope (" expand.end" );
1585+ JumpDest ContinueDest;
1586+ for (auto [N, Inst] : enumerate(S.getInstantiations ())) {
1587+ if (!HaveInsertPoint ()) {
1588+ EmitBlock (ExpandExit.getBlock (), true );
1589+ return ;
1590+ }
1591+
1592+ if (N == S.getInstantiations ().size () - 1 )
1593+ ContinueDest = ExpandExit;
1594+ else
1595+ ContinueDest = getJumpDestInCurrentScope (" expand.next" );
1596+
1597+ LexicalScope ExpansionScope (*this , S.getSourceRange ());
1598+ BreakContinueStack.push_back (BreakContinue (S, ExpandExit, ContinueDest));
1599+ EmitStmt (Inst);
1600+ BreakContinueStack.pop_back ();
1601+ EmitBlock (ContinueDest.getBlock (), true );
1602+ }
1603+ }
1604+
15591605void CodeGenFunction::EmitReturnOfRValue (RValue RV, QualType Ty) {
15601606 if (RV.isScalar ()) {
15611607 Builder.CreateStore (RV.getScalarVal (), ReturnValue);
0 commit comments