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