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(S)); case Stmt::IfStmtClass: return visitIfStmt(cast(S)); + case Stmt::WhileStmtClass: + return visitWhileStmt(cast(S)); + case Stmt::DoStmtClass: + return visitDoStmt(cast(S)); + case Stmt::BreakStmtClass: + return visitBreakStmt(cast(S)); + case Stmt::ContinueStmtClass: + return visitContinueStmt(cast(S)); case Stmt::NullStmtClass: return true; default: { @@ -276,6 +284,69 @@ return true; } +template +bool ByteCodeStmtGen::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 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 +bool ByteCodeStmtGen::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 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 +bool ByteCodeStmtGen::visitBreakStmt(const BreakStmt *S) { + if (!BreakLabel) + return false; + + return this->jump(*BreakLabel); +} + +template +bool ByteCodeStmtGen::visitContinueStmt(const ContinueStmt *S) { + if (!ContinueLabel) + return false; + + return this->jump(*ContinueLabel); +} + template bool ByteCodeStmtGen::visitVarDecl(const VarDecl *VD) { if (!VD->hasLocalStorage()) { 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, ""); +};