tbaeder updated this revision to Diff 466022.
tbaeder added a comment.
Add `break` and `continue` support as well.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D135433/new/
https://reviews.llvm.org/D135433
Files:
clang/lib/AST/Interp/ByteCodeStmtGen.cpp
clang/lib/AST/Interp/ByteCodeStmtGen.h
clang/test/AST/Interp/loops.cpp
Index: clang/test/AST/Interp/loops.cpp
===================================================================
--- /dev/null
+++ clang/test/AST/Interp/loops.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++14 -verify %s
+// RUN: %clang_cc1 -std=c++14 -verify=ref %s
+
+// expected-no-diagnostics
+// ref-no-diagnostics
+
+namespace WhileLoop {
+ constexpr int f() {
+ int i = 0;
+ while(false) {
+ i = i + 1;
+ }
+ return i;
+ }
+ static_assert(f() == 0, "");
+
+
+ constexpr int f2() {
+ int i = 0;
+ while(i != 5) {
+ i = i + 1;
+ }
+ return i;
+ }
+ static_assert(f2() == 5, "");
+
+ constexpr int f3() {
+ int i = 0;
+ while(true) {
+ i = i + 1;
+
+ if (i == 5)
+ break;
+ }
+ return i;
+ }
+ static_assert(f3() == 5, "");
+
+ constexpr int f4() {
+ int i = 0;
+ while(i != 5) {
+
+ i = i + 1;
+ continue;
+ i = i - 1;
+ }
+ return i;
+ }
+ static_assert(f4() == 5, "");
+};
+
+namespace DoWhileLoop {
+
+ constexpr int f() {
+ int i = 0;
+ do {
+ i = i + 1;
+ } while(false);
+ return i;
+ }
+ static_assert(f() == 1, "");
+
+ constexpr int f2() {
+ int i = 0;
+ do {
+ i = i + 1;
+ } while(i != 5);
+ return i;
+ }
+ static_assert(f2() == 5, "");
+
+
+ constexpr int f3() {
+ int i = 0;
+ do {
+ i = i + 1;
+ if (i == 5)
+ break;
+ } while(true);
+ return i;
+ }
+ static_assert(f3() == 5, "");
+
+ constexpr int f4() {
+ int i = 0;
+ do {
+ i = i + 1;
+ continue;
+ i = i - 1;
+ } while(i != 5);
+ return i;
+ }
+ static_assert(f4() == 5, "");
+};
Index: clang/lib/AST/Interp/ByteCodeStmtGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeStmtGen.h
+++ clang/lib/AST/Interp/ByteCodeStmtGen.h
@@ -58,6 +58,10 @@
bool visitDeclStmt(const DeclStmt *DS);
bool visitReturnStmt(const ReturnStmt *RS);
bool visitIfStmt(const IfStmt *IS);
+ bool visitWhileStmt(const WhileStmt *S);
+ bool visitDoStmt(const DoStmt *S);
+ bool visitBreakStmt(const BreakStmt *S);
+ bool visitContinueStmt(const ContinueStmt *S);
/// Compiles a variable declaration.
bool visitVarDecl(const VarDecl *VD);
Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ clang/lib/AST/Interp/ByteCodeStmtGen.cpp
@@ -167,6 +167,14 @@
return visitReturnStmt(cast<ReturnStmt>(S));
case Stmt::IfStmtClass:
return visitIfStmt(cast<IfStmt>(S));
+ case Stmt::WhileStmtClass:
+ return visitWhileStmt(cast<WhileStmt>(S));
+ case Stmt::DoStmtClass:
+ return visitDoStmt(cast<DoStmt>(S));
+ case Stmt::BreakStmtClass:
+ return visitBreakStmt(cast<BreakStmt>(S));
+ case Stmt::ContinueStmtClass:
+ return visitContinueStmt(cast<ContinueStmt>(S));
case Stmt::NullStmtClass:
return true;
default: {
@@ -276,6 +284,69 @@
return true;
}
+template <class Emitter>
+bool ByteCodeStmtGen<Emitter>::visitWhileStmt(const WhileStmt *S) {
+ const Expr *Cond = S->getCond();
+ const Stmt *Body = S->getBody();
+
+ LabelTy CondLabel = this->getLabel(); // Label before the condition.
+ LabelTy EndLabel = this->getLabel(); // Label after the loop
+ LoopScope<Emitter> LS(this, EndLabel, CondLabel);
+
+ this->emitLabel(CondLabel);
+ if (!this->visitBool(Cond))
+ return false;
+ if (!this->jumpFalse(EndLabel))
+ return false;
+
+ if (!this->visitStmt(Body))
+ return false;
+ if (!this->jump(CondLabel))
+ return false;
+
+ this->emitLabel(EndLabel);
+
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeStmtGen<Emitter>::visitDoStmt(const DoStmt *S) {
+ const Expr *Cond = S->getCond();
+ const Stmt *Body = S->getBody();
+
+ LabelTy StartLabel = this->getLabel();
+ LabelTy EndLabel = this->getLabel();
+ LabelTy CondLabel = this->getLabel();
+ LoopScope<Emitter> LS(this, EndLabel, CondLabel);
+
+ this->emitLabel(StartLabel);
+ if (!this->visitStmt(Body))
+ return false;
+ this->emitLabel(CondLabel);
+ if (!this->visitBool(Cond))
+ return false;
+ if (!this->jumpTrue(StartLabel))
+ return false;
+ this->emitLabel(EndLabel);
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeStmtGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
+ if (!BreakLabel)
+ return false;
+
+ return this->jump(*BreakLabel);
+}
+
+template <class Emitter>
+bool ByteCodeStmtGen<Emitter>::visitContinueStmt(const ContinueStmt *S) {
+ if (!ContinueLabel)
+ return false;
+
+ return this->jump(*ContinueLabel);
+}
+
template <class Emitter>
bool ByteCodeStmtGen<Emitter>::visitVarDecl(const VarDecl *VD) {
if (!VD->hasLocalStorage()) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits