From 8c1d736cd9b4ebc7e97d7c2dd299332408ffb4dd Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 16 Sep 2024 18:37:26 +0100 Subject: [PATCH] Fix calculation of constrained array index type. Fixes xxx --- NEWS.md | 2 +- src/names.c | 7 +++++-- src/parse.c | 6 ++++-- test/bounds/issue975.vhd | 11 +++++++++++ test/test_bounds.c | 20 ++++++++++++++++++++ test/test_jit.c | 4 +--- test/test_parse.c | 18 +++++++++++++----- 7 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 test/bounds/issue975.vhd diff --git a/NEWS.md b/NEWS.md index 8081dc41f..d38e9bbe4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -43,7 +43,7 @@ - Limited maximum instantiation depth to prevent crashes due to stack overflow when elaborating a design that has unbounded recursive entity instantiation (#969). -- Several other minor bugs were resolved (#961, #962, #971). +- Several other minor bugs were resolved (#961, #962, #971, #975). ## Version 1.13.3 - 2024-08-24 - Type checking was not performed correctly for conversion function diff --git a/src/names.c b/src/names.c index 0675998cc..892121c73 100644 --- a/src/names.c +++ b/src/names.c @@ -4769,6 +4769,8 @@ static type_t solve_range(nametab_t *tab, tree_t r) tree_t left = tree_left(r); tree_t right = tree_right(r); + const bool has_context = tab->top_type_set->members.count > 0; + type_t ltype; if (is_unambiguous(left)) ltype = _solve_types(tab, left); @@ -4792,8 +4794,9 @@ static type_t solve_range(nametab_t *tab, tree_t r) rtype = _solve_types(tab, right); } - tree_set_type(r, ltype); - return ltype; + type_t result = has_context ? ltype : type_base_recur(ltype); + tree_set_type(r, result); + return result; } default: fatal_trace("invalid range subkind"); diff --git a/src/parse.c b/src/parse.c index a725cbd0a..4ee81880d 100644 --- a/src/parse.c +++ b/src/parse.c @@ -6374,12 +6374,14 @@ static type_t p_constrained_array_definition(type_t base, tree_t head) mangle_type(nametab, sub); - type_t index_type = std_type(NULL, STD_INTEGER); do { tree_t r = p_discrete_range(head); - solve_types(nametab, r, index_type); + solve_types(nametab, r, NULL); + convert_universal_bounds(r); + tree_add_range(constraint, r); type_add_index(base, tree_type(r)); + head = NULL; } while (optional(tCOMMA)); diff --git a/test/bounds/issue975.vhd b/test/bounds/issue975.vhd new file mode 100644 index 000000000..ee4f978dc --- /dev/null +++ b/test/bounds/issue975.vhd @@ -0,0 +1,11 @@ +entity array_issue is +end entity array_issue; + +architecture rtl of array_issue is + constant C_LENGTH : positive := 7; + type t_array1 is array (C_LENGTH downto 0) of bit; -- OK + type t_array2 is array (0 to C_LENGTH) of bit; -- OK + type t_array3 is array (positive range 0 to C_LENGTH) of bit; -- Error + type t_array4 is array (positive range C_LENGTH downto 0) of bit; -- Error +begin +end architecture rtl; diff --git a/test/test_bounds.c b/test/test_bounds.c index a4c6fe3fd..b7b4e3272 100644 --- a/test/test_bounds.c +++ b/test/test_bounds.c @@ -804,6 +804,25 @@ START_TEST(test_issue966) } END_TEST +START_TEST(test_issue975) +{ + input_from_file(TESTDIR "/bounds/issue975.vhd"); + + const error_t expect[] = { + { 8, "left index 0 violates constraint POSITIVE" }, + { 9, "right index 0 violates constraint POSITIVE" }, + { -1, NULL } + }; + expect_errors(expect); + + parse_check_and_simplify(T_ENTITY, T_ARCH); + + fail_unless(parse() == NULL); + + check_expected_errors(); +} +END_TEST + Suite *get_bounds_tests(void) { Suite *s = suite_create("bounds"); @@ -846,6 +865,7 @@ Suite *get_bounds_tests(void) tcase_add_test(tc_core, test_subtype); tcase_add_test(tc_core, test_issue951); tcase_add_test(tc_core, test_issue966); + tcase_add_test(tc_core, test_issue975); suite_add_tcase(s, tc_core); return s; diff --git a/test/test_jit.c b/test/test_jit.c index 25460ad32..d39e2358f 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -910,9 +910,7 @@ START_TEST(test_layout) input_from_file(TESTDIR "/jit/layout.vhd"); - tree_t p = parse(); - fail_if(p == NULL); - fail_unless(tree_kind(p) == T_PACKAGE); + tree_t p = parse_check_and_simplify(T_PACKAGE); freeze_global_arena(); fail_unless(parse() == NULL); diff --git a/test/test_parse.c b/test/test_parse.c index 901c496b4..c1e4e7d5a 100644 --- a/test/test_parse.c +++ b/test/test_parse.c @@ -1416,7 +1416,7 @@ START_TEST(test_array) { tree_t p, d, a, g, s, e, r; type_t t, i, b; - tree_t x; + tree_t x, left, right; input_from_file(TESTDIR "/parse/array.vhd"); @@ -1478,11 +1478,19 @@ START_TEST(test_array) fail_unless(tree_ranges(type_constraint(t, 0)) == 2); fail_unless(type_indexes(type_base(t)) == 2); r = tree_range(type_constraint(t, 0), 0); - fail_unless(tree_ival(tree_left(r)) == 1); - fail_unless(tree_ival(tree_right(r)) == 3); + left = tree_left(r); + fail_unless(tree_kind(left) == T_TYPE_CONV); + fail_unless(tree_ival(tree_value(left)) == 1); + right = tree_right(r); + fail_unless(tree_kind(right) == T_TYPE_CONV); + fail_unless(tree_ival(tree_value(right)) == 3); r = tree_range(type_constraint(t, 0), 1); - fail_unless(tree_ival(tree_left(r)) == 4); - fail_unless(tree_ival(tree_right(r)) == 6); + left = tree_left(r); + fail_unless(tree_kind(left) == T_TYPE_CONV); + fail_unless(tree_ival(tree_value(left)) == 4); + right = tree_right(r); + fail_unless(tree_kind(right) == T_TYPE_CONV); + fail_unless(tree_ival(tree_value(right)) == 6); e = parse(); fail_if(e == NULL);