[clang][Interp] Implement for loops
Differential Revision: https://reviews.llvm.org/D135764
This commit is contained in:
parent
4a5184f4c3
commit
f6f02e0900
|
@ -171,6 +171,8 @@ bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
|
|||
return visitWhileStmt(cast<WhileStmt>(S));
|
||||
case Stmt::DoStmtClass:
|
||||
return visitDoStmt(cast<DoStmt>(S));
|
||||
case Stmt::ForStmtClass:
|
||||
return visitForStmt(cast<ForStmt>(S));
|
||||
case Stmt::BreakStmtClass:
|
||||
return visitBreakStmt(cast<BreakStmt>(S));
|
||||
case Stmt::ContinueStmtClass:
|
||||
|
@ -331,6 +333,39 @@ bool ByteCodeStmtGen<Emitter>::visitDoStmt(const DoStmt *S) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <class Emitter>
|
||||
bool ByteCodeStmtGen<Emitter>::visitForStmt(const ForStmt *S) {
|
||||
// for (Init; Cond; Inc) { Body }
|
||||
const Stmt *Init = S->getInit();
|
||||
const Expr *Cond = S->getCond();
|
||||
const Expr *Inc = S->getInc();
|
||||
const Stmt *Body = S->getBody();
|
||||
|
||||
LabelTy EndLabel = this->getLabel();
|
||||
LabelTy CondLabel = this->getLabel();
|
||||
LabelTy IncLabel = this->getLabel();
|
||||
LoopScope<Emitter> LS(this, EndLabel, IncLabel);
|
||||
|
||||
if (Init && !this->visitStmt(Init))
|
||||
return false;
|
||||
this->emitLabel(CondLabel);
|
||||
if (Cond) {
|
||||
if (!this->visitBool(Cond))
|
||||
return false;
|
||||
if (!this->jumpFalse(EndLabel))
|
||||
return false;
|
||||
}
|
||||
if (Body && !this->visitStmt(Body))
|
||||
return false;
|
||||
this->emitLabel(IncLabel);
|
||||
if (Inc && !this->discard(Inc))
|
||||
return false;
|
||||
if (!this->jump(CondLabel))
|
||||
return false;
|
||||
this->emitLabel(EndLabel);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Emitter>
|
||||
bool ByteCodeStmtGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
|
||||
if (!BreakLabel)
|
||||
|
|
|
@ -60,6 +60,7 @@ private:
|
|||
bool visitIfStmt(const IfStmt *IS);
|
||||
bool visitWhileStmt(const WhileStmt *S);
|
||||
bool visitDoStmt(const DoStmt *S);
|
||||
bool visitForStmt(const ForStmt *S);
|
||||
bool visitBreakStmt(const BreakStmt *S);
|
||||
bool visitContinueStmt(const ContinueStmt *S);
|
||||
|
||||
|
|
|
@ -187,3 +187,91 @@ namespace DoWhileLoop {
|
|||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace ForLoop {
|
||||
constexpr int f() {
|
||||
int i = 0;
|
||||
for (;false;) {
|
||||
i = i + 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
static_assert(f() == 0, "");
|
||||
|
||||
constexpr int f2() {
|
||||
int m = 0;
|
||||
for (int i = 0; i < 10; i = i + 1){
|
||||
m = i;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
static_assert(f2() == 9, "");
|
||||
|
||||
constexpr int f3() {
|
||||
int i = 0;
|
||||
for (; i != 5; i = i + 1);
|
||||
return i;
|
||||
}
|
||||
static_assert(f3() == 5, "");
|
||||
|
||||
constexpr int f4() {
|
||||
int i = 0;
|
||||
for (;;) {
|
||||
i = i + 1;
|
||||
|
||||
if (i == 5)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
static_assert(f4() == 5, "");
|
||||
|
||||
constexpr int f5() {
|
||||
int i = 0;
|
||||
for (;i != 5;) {
|
||||
i = i + 1;
|
||||
continue;
|
||||
i = i - 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
static_assert(f5() == 5, "");
|
||||
|
||||
constexpr int f6(bool b) {
|
||||
int i = 0;
|
||||
|
||||
for (;true;) {
|
||||
if (!b) {
|
||||
if (i == 5)
|
||||
break;
|
||||
}
|
||||
|
||||
if (b) {
|
||||
for (; i != 10; i = i + 1) {
|
||||
if (i == 8)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (b)
|
||||
break;
|
||||
|
||||
i = i + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
static_assert(f6(true) == 8, "");
|
||||
static_assert(f6(false) == 5, "");
|
||||
|
||||
#if 0
|
||||
/// FIXME: This is an infinite loop, which should
|
||||
/// be rejected.
|
||||
constexpr int f6() {
|
||||
for(;;);
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue