From 30c256fc1848e5c7045a5a6c0af29a4ebd518020 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Mon, 30 May 2022 16:44:35 +0200
Subject: [PATCH] Fix symbol table management for do...while and while loops

In case of empty blocks or single instruction statement, the symbol
table could be cleared unexpectedly.
---
 src/language/ast/ASTSymbolTableBuilder.cpp |  3 +-
 tests/test_DoWhileProcessor.cpp            | 35 ++++++++++++++++++++++
 tests/test_WhileProcessor.cpp              | 34 +++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/src/language/ast/ASTSymbolTableBuilder.cpp b/src/language/ast/ASTSymbolTableBuilder.cpp
index d2eb7d77c..ac7d03155 100644
--- a/src/language/ast/ASTSymbolTableBuilder.cpp
+++ b/src/language/ast/ASTSymbolTableBuilder.cpp
@@ -8,7 +8,8 @@
 void
 ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable>& symbol_table)
 {
-  if (n.is_type<language::block>() or (n.is_type<language::for_statement>())) {
+  if (n.is_type<language::block>() or (n.is_type<language::for_statement>()) or
+      (n.is_type<language::while_statement>()) or (n.is_type<language::do_while_statement>())) {
     if (!n.children.empty()) {
       std::shared_ptr block_symbol_table = std::make_shared<SymbolTable>(symbol_table);
       n.m_symbol_table                   = block_symbol_table;
diff --git a/tests/test_DoWhileProcessor.cpp b/tests/test_DoWhileProcessor.cpp
index 8e4f7a2c9..9ef421988 100644
--- a/tests/test_DoWhileProcessor.cpp
+++ b/tests/test_DoWhileProcessor.cpp
@@ -105,6 +105,41 @@ do {
     CHECK_WHILE_PROCESSOR_RESULT(data, "i", 12ul);
   }
 
+  SECTION("do-while lifetime variable")
+  {
+    std::string_view data = R"(
+let i:N, i = 3;
+let j:N, j = 0;
+do {
+  j = 5;
+  let j:N, j = 2;
+  i = j;
+} while(false);
+)";
+    CHECK_WHILE_PROCESSOR_RESULT(data, "i", 2ul);
+    CHECK_WHILE_PROCESSOR_RESULT(data, "j", 5ul);
+  }
+
+  SECTION("empty do-while symbol table untouched")
+  {
+    std::string_view data = R"(
+let i:N, i = 3;
+do {} while(false);
+)";
+    CHECK_WHILE_PROCESSOR_RESULT(data, "i", 3ul);
+  }
+
+  SECTION("single instruction do-while symbol table untouched")
+  {
+    std::string_view data = R"(
+let i:N, i = 3;
+do
+  i = 2;
+while(false);
+)";
+    CHECK_WHILE_PROCESSOR_RESULT(data, "i", 2ul);
+  }
+
   SECTION("errors")
   {
     SECTION("bad test type")
diff --git a/tests/test_WhileProcessor.cpp b/tests/test_WhileProcessor.cpp
index e886b6213..028d8eae0 100644
--- a/tests/test_WhileProcessor.cpp
+++ b/tests/test_WhileProcessor.cpp
@@ -101,6 +101,40 @@ while(i<10) {
     CHECK_WHILE_PROCESSOR_RESULT(data, "i", 12ul);
   }
 
+  SECTION("while lifetime variable")
+  {
+    std::string_view data = R"(
+let i:N, i = 3;
+let j:N, j = 0;
+while(i != 2) {
+  j = 5;
+  let j:N, j = 2;
+  i = j;
+}
+)";
+    CHECK_WHILE_PROCESSOR_RESULT(data, "i", 2ul);
+    CHECK_WHILE_PROCESSOR_RESULT(data, "j", 5ul);
+  }
+
+  SECTION("while symbol table untouched")
+  {
+    std::string_view data = R"(
+let i:N, i = 3;
+while(i != 3);
+)";
+    CHECK_WHILE_PROCESSOR_RESULT(data, "i", 3ul);
+  }
+
+  SECTION("single instruction while symbol table untouched")
+  {
+    std::string_view data = R"(
+let i:N, i = 3;
+while (i == 3)
+  i = 2;
+)";
+    CHECK_WHILE_PROCESSOR_RESULT(data, "i", 2ul);
+  }
+
   SECTION("errors")
   {
     SECTION("bad test type")
-- 
GitLab