Skip to content
Snippets Groups Projects
Commit d93dd7ad authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Forbid return value implicit conversion to N of negative integers

Also add a few tests
parent 8ea43b58
No related branches found
No related tags found
1 merge request!145git subrepo clone git@gitlab.com:OlMon/org-themes.git packages/org-themes
......@@ -57,7 +57,13 @@ class FunctionExpressionProcessor final : public INodeProcessor
} else if constexpr (std::is_same_v<ExpressionValueType, ZeroType>) {
return ReturnType{ZeroType::zero};
} else if constexpr (std::is_convertible_v<ExpressionValueType, ReturnType>) {
return static_cast<ReturnType>(std::get<ExpressionValueType>(m_function_expression.execute(exec_policy)));
const ExpressionValueType& v = std::get<ExpressionValueType>(m_function_expression.execute(exec_policy));
if constexpr (std::is_same_v<ReturnType, uint64_t> and std::is_same_v<ExpressionValueType, int64_t>) {
if (v < 0) {
throw std::domain_error("trying to convert negative value (" + std::to_string(v) + ")");
}
}
return static_cast<ReturnType>(v);
} else if constexpr (std::is_arithmetic_v<ExpressionValueType> and
(is_tiny_vector_v<ReturnType> or is_tiny_matrix_v<ReturnType>)) {
static_assert(ReturnType::Dimension == 1, "invalid conversion");
......@@ -105,16 +111,27 @@ class FunctionProcessor : public INodeProcessor
ExecutionPolicy context_exec_policy{exec_policy, context};
if (m_argument_converters.size() == 1) {
try {
m_argument_converters[0]->convert(context_exec_policy, m_argument_node.execute(context_exec_policy));
}
catch (std::domain_error& e) {
throw ParseError(e.what(), m_argument_node.begin());
}
} else {
AggregateDataVariant argument_values{
std::get<AggregateDataVariant>(m_argument_node.execute(context_exec_policy))};
for (size_t i = 0; i < m_argument_converters.size(); ++i) {
try {
m_argument_converters[i]->convert(context_exec_policy, std::move(argument_values[i]));
}
catch (std::domain_error& e) {
throw ParseError(e.what(), m_argument_node.children[i]->begin());
}
}
}
try {
if (m_function_expression_processors.size() == 1) {
return m_function_expression_processors[0]->execute(context_exec_policy);
} else {
......@@ -127,6 +144,10 @@ class FunctionProcessor : public INodeProcessor
return AggregateDataVariant{std::move(list_values)};
}
}
catch (std::domain_error& e) {
throw ParseError(e.what(), m_argument_node.begin());
}
}
FunctionProcessor(ASTNode& argument_node, SymbolTable::Context context)
: m_argument_node{argument_node}, m_context_size{context.size()}, m_context_id{context.id()}
......
......@@ -46,6 +46,26 @@
REQUIRE(value == expected_value); \
}
#define CHECK_FUNCTION_EVALUATION_THROWS(data, error_msg) \
{ \
TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \
auto ast = ASTBuilder::build(input); \
\
ASTModulesImporter{*ast}; \
ASTNodeTypeCleaner<language::import_instruction>{*ast}; \
\
ASTSymbolTableBuilder{*ast}; \
ASTNodeDataTypeBuilder{*ast}; \
\
ASTNodeDeclarationToAffectationConverter{*ast}; \
ASTNodeTypeCleaner<language::var_declaration>{*ast}; \
ASTNodeTypeCleaner<language::fct_declaration>{*ast}; \
\
ASTNodeExpressionBuilder{*ast}; \
ExecutionPolicy exec_policy; \
REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_msg); \
}
// clazy:excludeall=non-pod-global-static
TEST_CASE("FunctionProcessor", "[language]")
......@@ -730,4 +750,54 @@ let x:R, x = g(f(3));
A33(2, 0) * A33(0, 2) - A22(1, 1)});
}
}
SECTION("errors")
{
SECTION("negative value to N")
{
SECTION("single N argument")
{
std::string_view data = R"(
let f : N -> N, n -> 2;
f(2);
f(-1);
)";
CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-1)");
}
SECTION("multiple N arguments")
{
std::string_view data = R"(
let f : R*N -> R, (n,x) -> n*x;
f(-2, 3);
f(-1,-4);
)";
CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-4)");
}
SECTION("single N return value")
{
std::string_view data = R"(
let f : N*N -> N, (m,n) -> m-n;
f(2, 1);
f(1, 3);
)";
CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-2)");
}
SECTION("compound N return value")
{
std::string_view data = R"(
let f : N*N -> N*N, (m,n) -> (m+n, m-n);
f(3, 2);
f(1, 4);
)";
CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-3)");
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment