Index: clang/lib/AST/Interp/ByteCodeStmtGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeStmtGen.h +++ clang/lib/AST/Interp/ByteCodeStmtGen.h @@ -58,6 +58,8 @@ 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); /// 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,10 @@ 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::NullStmtClass: return true; default: { @@ -276,6 +280,47 @@ 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 + + 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(); + + this->emitLabel(StartLabel); + if (!this->visitStmt(Body)) + return false; + if (!this->visitBool(Cond)) + return false; + if (!this->jumpTrue(StartLabel)) + return false; + return true; +} + 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,47 @@ +// 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, ""); +}; + +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, ""); +};