[clang] f6f02e0 - [clang][Interp] Implement for loops

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 25 23:55:26 PDT 2022


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
+
+};


        


More information about the cfe-commits mailing list