Author: Timm Bäder Date: 2022-10-26T08:48:36+02:00 New Revision: f6f02e090072002674c85c9d015b42f61c41656e
URL: https://github.com/llvm/llvm-project/commit/f6f02e090072002674c85c9d015b42f61c41656e DIFF: https://github.com/llvm/llvm-project/commit/f6f02e090072002674c85c9d015b42f61c41656e.diff LOG: [clang][Interp] Implement for loops Differential Revision: https://reviews.llvm.org/D135764 Added: Modified: clang/lib/AST/Interp/ByteCodeStmtGen.cpp clang/lib/AST/Interp/ByteCodeStmtGen.h clang/test/AST/Interp/loops.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index addcb4dff1ff8..4f54193dcf3af 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -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) diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.h b/clang/lib/AST/Interp/ByteCodeStmtGen.h index 49a7b79b1c4b5..10452079c65bd 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.h +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.h @@ -60,6 +60,7 @@ class ByteCodeStmtGen final : public ByteCodeExprGen<Emitter> { 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); diff --git a/clang/test/AST/Interp/loops.cpp b/clang/test/AST/Interp/loops.cpp index 30a38ca573b28..4157f65e21688 100644 --- a/clang/test/AST/Interp/loops.cpp +++ b/clang/test/AST/Interp/loops.cpp @@ -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 + +}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits