Skip to content

Commit 160077c

Browse files
committed
[Clang] [C++26] Expansion Statements (Part 8)
1 parent 157da01 commit 160077c

File tree

7 files changed

+3143
-1
lines changed

7 files changed

+3143
-1
lines changed

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
15631602
void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
15641603
if (RV.isScalar()) {
15651604
Builder.CreateStore(RV.getScalarVal(), ReturnValue);

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,6 +3690,9 @@ class CodeGenFunction : public CodeGenTypeCache {
36903690
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
36913691
ArrayRef<const Attr *> Attrs = {});
36923692

3693+
void
3694+
EmitCXXExpansionStmtInstantiation(const CXXExpansionStmtInstantiation &S);
3695+
36933696
/// Controls insertion of cancellation exit blocks in worksharing constructs.
36943697
class OMPCancelStackRAII {
36953698
CodeGenFunction &CGF;

0 commit comments

Comments
 (0)