From 888ae4e303ea6670f3f1cccfec409d92333ce7a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com> Date: Fri, 3 Jun 2022 18:24:25 +0200 Subject: [PATCH] Check that natural integer cannot become negative on decrement --- .../IncDecExpressionProcessor.hpp | 17 +++++++++++- tests/test_IncDecExpressionProcessor.cpp | 27 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/language/node_processor/IncDecExpressionProcessor.hpp b/src/language/node_processor/IncDecExpressionProcessor.hpp index 9e50106e5..199d3ebb8 100644 --- a/src/language/node_processor/IncDecExpressionProcessor.hpp +++ b/src/language/node_processor/IncDecExpressionProcessor.hpp @@ -16,6 +16,11 @@ struct IncDecOp<language::unary_minusminus> PUGS_INLINE A eval(A& a) { + if constexpr (std::is_same_v<A, uint64_t>) { + if (a == 0) { + throw std::domain_error("decrement would produce negative value"); + } + } return --a; } }; @@ -38,6 +43,11 @@ struct IncDecOp<language::post_minusminus> PUGS_INLINE A eval(A& a) { + if constexpr (std::is_same_v<A, uint64_t>) { + if (a == 0) { + throw std::domain_error("decrement would produce negative value"); + } + } return a--; } }; @@ -64,7 +74,12 @@ class IncDecExpressionProcessor final : public INodeProcessor DataVariant execute(ExecutionPolicy&) { - return IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); + try { + return IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); + } + catch (std::domain_error& e) { + throw ParseError(e.what(), m_node.children[0]->begin()); + } } IncDecExpressionProcessor(ASTNode& node) : m_node{node} diff --git a/tests/test_IncDecExpressionProcessor.cpp b/tests/test_IncDecExpressionProcessor.cpp index a69d9d951..ba04c7ab2 100644 --- a/tests/test_IncDecExpressionProcessor.cpp +++ b/tests/test_IncDecExpressionProcessor.cpp @@ -58,6 +58,23 @@ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ } +#define CHECK_INCDEC_THROWS_WITH(data, error_message) \ + { \ + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ + \ + ASTNodeExpressionBuilder{*ast}; \ + ExecutionPolicy exec_policy; \ + \ + REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_message); \ + } + // clazy:excludeall=non-pod-global-static TEST_CASE("IncDecExpressionProcessor", "[language]") @@ -124,6 +141,16 @@ TEST_CASE("IncDecExpressionProcessor", "[language]") SECTION("errors") { + SECTION("negative pre -- operator for N") + { + CHECK_INCDEC_THROWS_WITH(R"(let n:N, n=0;--n;)", "decrement would produce negative value"); + } + + SECTION("negative post -- operator for N") + { + CHECK_INCDEC_THROWS_WITH(R"(let n:N, n=0;n--;)", "decrement would produce negative value"); + } + SECTION("undefined pre -- operator") { auto error_message = [](std::string type_name) { -- GitLab