Skip to content

Commit 09588e9

Browse files
authored
[clang][bytecode] Fix an inconsistency with loop condition jumps (#135530)
When emitting the jump for e.g. a for loop condition, we used to jump out of the CondScope, leaving the scope initialized, because we skipped the corresponding Destroy opcode. If that loop was in a loop itself, that outer loop could then iterate once more, leading to us initializing a scope that was still initialized. Fix this by also destroying the scope after the EndLabel.
1 parent beac727 commit 09588e9

File tree

2 files changed

+26
-25
lines changed

2 files changed

+26
-25
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5431,39 +5431,39 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
54315431
this->fallthrough(CondLabel);
54325432
this->emitLabel(CondLabel);
54335433

5434-
{
5435-
LocalScope<Emitter> CondScope(this);
5436-
if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
5437-
if (!visitDeclStmt(CondDecl))
5438-
return false;
5439-
5440-
if (Cond) {
5441-
if (!this->visitBool(Cond))
5442-
return false;
5443-
if (!this->jumpFalse(EndLabel))
5444-
return false;
5445-
}
5446-
5447-
if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
5448-
return false;
5449-
5450-
if (Body && !this->visitStmt(Body))
5434+
// Start of loop body.
5435+
LocalScope<Emitter> CondScope(this);
5436+
if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
5437+
if (!visitDeclStmt(CondDecl))
54515438
return false;
54525439

5453-
this->fallthrough(IncLabel);
5454-
this->emitLabel(IncLabel);
5455-
if (Inc && !this->discard(Inc))
5440+
if (Cond) {
5441+
if (!this->visitBool(Cond))
54565442
return false;
5457-
5458-
if (!CondScope.destroyLocals())
5443+
if (!this->jumpFalse(EndLabel))
54595444
return false;
54605445
}
5446+
if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
5447+
return false;
5448+
5449+
if (Body && !this->visitStmt(Body))
5450+
return false;
5451+
5452+
this->fallthrough(IncLabel);
5453+
this->emitLabel(IncLabel);
5454+
if (Inc && !this->discard(Inc))
5455+
return false;
5456+
5457+
if (!CondScope.destroyLocals())
5458+
return false;
54615459
if (!this->jump(CondLabel))
54625460
return false;
5461+
// End of loop body.
54635462

5464-
this->fallthrough(EndLabel);
54655463
this->emitLabel(EndLabel);
5466-
return true;
5464+
// If we jumped out of the loop above, we still need to clean up the condition
5465+
// scope.
5466+
return CondScope.destroyLocals();
54675467
}
54685468

54695469
template <class Emitter>

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,10 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
531531
if (!Idx)
532532
return true;
533533

534+
// NB: We are *not* resetting Idx here as to allow multiple
535+
// calls to destroyLocals().
534536
bool Success = this->emitDestructors(E);
535537
this->Ctx->emitDestroy(*Idx, E);
536-
this->Idx = std::nullopt;
537538
return Success;
538539
}
539540

0 commit comments

Comments
 (0)