From 4eb6d6f457219af6e7f026af6bd2b9ca2b683048 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 2 Apr 2024 21:18:50 +0100 Subject: [PATCH] Fix several crashes after errors in package generics --- NEWS.md | 1 + src/common.c | 2 +- src/names.c | 6 +++- test/parse/error11.vhd | 33 +++++++++++++++++++ test/parse/error12.vhd | 40 +++++++++++++++++++++++ test/test_parse.c | 73 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 test/parse/error11.vhd create mode 100644 test/parse/error12.vhd diff --git a/NEWS.md b/NEWS.md index cf5e1749..e1bfec4a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -25,6 +25,7 @@ - The `--vhpi-trace` option now implies `--vhpi-debug`. - The bounds of array aggregates are now calculated correctly in several corner cases (#873). +- Added supported for VHPI foreign subprograms. ## Version 1.11.3 - 2024-02-04 - Fixed incorrect effective value when a signal has multiple sources due diff --git a/src/common.c b/src/common.c index 9253df2b..b073f970 100644 --- a/src/common.c +++ b/src/common.c @@ -1843,7 +1843,7 @@ tree_t find_generic_map(tree_t unit, int pos, tree_t g) tree_t name = tree_name(m); assert(tree_kind(name) == T_REF); - if (tree_ref(name) == g) + if (tree_has_ref(name) && tree_ref(name) == g) return tree_value(m); } break; diff --git a/src/names.c b/src/names.c index 8619577b..dc499675 100644 --- a/src/names.c +++ b/src/names.c @@ -1113,7 +1113,9 @@ static scope_t *private_scope_for(nametab_t *tab, tree_t unit) // A single subprogram could be visible both directly // and as a actual generic subprogram tree_t value = find_generic_map(unit, i, g); - if (value != NULL && tree_kind(value) == T_REF) { + if (value == NULL) + assert(error_count() > 0); + else if (tree_kind(value) == T_REF && tree_has_ref(value)) { decl = tree_ref(value); assert(is_subprogram(decl)); } @@ -3676,6 +3678,8 @@ static type_t try_solve_string(nametab_t *tab, tree_t str) { if (tree_has_type(str)) return tree_type(str); + else if (type_set_any(tab, type_is_none)) + return type_new(T_NONE); // Suppress cascading errors // The type must be determinable soley from the context excluding the // literal itself but using the fact that the type must be a one diff --git a/test/parse/error11.vhd b/test/parse/error11.vhd new file mode 100644 index 00000000..45f67aa2 --- /dev/null +++ b/test/parse/error11.vhd @@ -0,0 +1,33 @@ +package generic_sb_pkg is + + generic(type t_element; + function element_match(received_element : t_element; + expected_element : t_element) return boolean; + function to_string_element(element : t_element) return string); + + type t_generic_sb is protected + end protected; + +end package generic_sb_pkg; + +package body generic_sb_pkg is + type t_generic_sb is protected body + end protected body; +end package body; + +------------------------------------------------------------------------------- + +entity issue858 is +end entity; + +architecture tb of issue858 is + package slv_sb_pkg is new work.generic_sb_pkg + generic map(t_element => bit_vector(7 downto 0), + element_match => std_match, -- Error + to_string_element => to_string); + + use slv_sb_pkg.all; + + shared variable sb_under_test : slv_sb_pkg.t_generic_sb; +begin +end architecture; diff --git a/test/parse/error12.vhd b/test/parse/error12.vhd new file mode 100644 index 00000000..e9ca83ea --- /dev/null +++ b/test/parse/error12.vhd @@ -0,0 +1,40 @@ +package generic_queue_pkg is + + generic(type t_generic_element; + GC_QUEUE_COUNT_MAX : natural := 1000; + GC_QUEUE_COUNT_THRESHOLD : natural := 950); + +end package generic_queue_pkg; + +------------------------------------------------------------------------------- + +package generic_sb_pkg is + + generic(type t_element; + function element_match(received_element : t_element; + expected_element : t_element) return boolean; + function to_string_element(element : t_element) return string; + constant GC_QUEUE_COUNT_MAX : natural := 1000; + constant GC_QUEUE_COUNT_THRESHOLD : natural := 950); + +end package generic_sb_pkg; + +package body generic_sb_pkg is + + type t_sb_entry is record + expected_element : t_element; + source : string(1 to 5); + tag : string(1 to 5); + entry_time : time; + end record; + + package sb_queue_pkg is new work.generic_queue_pkg + generic map( + t_generic_element => t_sb_entry, + scope => "SB_queue", + GC_QUEUE_COUNT_MAX => GC_QUEUE_COUNT_MAX, + GC_QUEUE_COUNT_THRESHOLD => GC_QUEUE_COUNT_THRESHOLD); + + use sb_queue_pkg.all; + +end package body generic_sb_pkg; diff --git a/test/test_parse.c b/test/test_parse.c index 56d9c3e9..b51ff71a 100644 --- a/test/test_parse.c +++ b/test/test_parse.c @@ -6286,6 +6286,77 @@ START_TEST(test_issue875) } END_TEST +START_TEST(test_error11) +{ + set_standard(STD_08); + + input_from_file(TESTDIR "/parse/error11.vhd"); + + const error_t expect[] = { + { 26, "no visible subprogram STD_MATCH matches signature [T_ELEMENT, " + "T_ELEMENT return BOOLEAN]" }, + { -1, NULL } + }; + expect_errors(expect); + + tree_t p = parse(); + fail_if(p == NULL); + fail_unless(tree_kind(p) == T_PACKAGE); + lib_put(lib_work(), p); + + tree_t b = parse(); + fail_if(b == NULL); + fail_unless(tree_kind(b) == T_PACK_BODY); + lib_put(lib_work(), b); + + tree_t e = parse(); + fail_if(e == NULL); + fail_unless(tree_kind(e) == T_ENTITY); + lib_put(lib_work(), e); + + tree_t a = parse(); + fail_if(a == NULL); + fail_unless(tree_kind(a) == T_ARCH); + + fail_unless(parse() == NULL); + + check_expected_errors(); +} +END_TEST + +START_TEST(test_error12) +{ + set_standard(STD_08); + + input_from_file(TESTDIR "/parse/error12.vhd"); + + const error_t expect[] = { + { 34, "SB_QUEUE_PKG has no generic named SCOPE" }, + { -1, NULL } + }; + expect_errors(expect); + + tree_t p1 = parse(); + fail_if(p1 == NULL); + fail_unless(tree_kind(p1) == T_PACKAGE); + lib_put(lib_work(), p1); + + tree_t p2 = parse(); + fail_if(p2 == NULL); + fail_unless(tree_kind(p2) == T_PACKAGE); + lib_put(lib_work(), p2); + + tree_t b = parse(); + fail_if(b == NULL); + fail_unless(tree_kind(b) == T_PACK_BODY); + lib_put(lib_work(), b); + + fail_unless(parse() == NULL); + + check_expected_errors(); +} +END_TEST + Suite *get_parse_tests(void) { Suite *s = suite_create("parse"); @@ -6426,6 +6497,8 @@ Suite *get_parse_tests(void) tcase_add_test(tc_core, test_issue870); tcase_add_test(tc_core, test_aggregate); tcase_add_test(tc_core, test_issue875); + tcase_add_test(tc_core, test_error11); + tcase_add_test(tc_core, test_error12); suite_add_tcase(s, tc_core); return s; -- 2.39.2