From 4af44589aaf8f344cd7bab69ce01fada9c986289 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 30 Dec 2023 15:43:15 +0000 Subject: [PATCH] Improve checking for expanded names --- src/names.c | 12 ++++++++++++ src/names.h | 1 + src/parse.c | 27 +++++++++++++++++++++++++-- test/parse/visibility11.vhd | 26 ++++++++++++++++++++++++++ test/test_parse.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 test/parse/visibility11.vhd diff --git a/src/names.c b/src/names.c index 12342dc7..129fda17 100644 --- a/src/names.c +++ b/src/names.c @@ -566,6 +566,18 @@ tree_t find_enclosing(nametab_t *tab, scope_kind_t what) return NULL; } +bool is_enclosing(nametab_t *tab, tree_t container) +{ + assert(is_container(container)); + + for (scope_t *s = tab->top_scope; s; s = s->parent) { + if (s->container == container) + return true; + } + + return false; +} + formal_kind_t scope_formal_kind(nametab_t *tab) { return tab->top_scope->formal_kind; diff --git a/src/names.h b/src/names.h index 9b4bb8fe..b6ae09c1 100644 --- a/src/names.h +++ b/src/names.h @@ -70,6 +70,7 @@ formal_kind_t scope_formal_kind(nametab_t *tab); void scope_set_container(nametab_t *tab, tree_t container); void scope_set_subprogram(nametab_t *tab, tree_t subprog); tree_t find_enclosing(nametab_t *tab, scope_kind_t kind); +bool is_enclosing(nametab_t *tab, tree_t container); void suppress_errors(nametab_t *tab); void map_generic_type(nametab_t *tab, type_t generic, type_t actual); diff --git a/src/parse.c b/src/parse.c index b283b29d..93836183 100644 --- a/src/parse.c +++ b/src/parse.c @@ -3178,8 +3178,31 @@ static tree_t p_selected_name(tree_t prefix, name_mask_t *mask) } else if (kind == T_GENERIC_DECL && tree_class(decl) == C_PACKAGE) return select_decl(tree_value(decl), suffix, mask); - else if (is_container(decl)) - return select_decl(prefix, suffix, mask); + else if (is_container(decl)) { + tree_t ref = select_decl(prefix, suffix, mask); + if (!tree_has_ref(ref)) + return ref; // Was error + + // LRM 08 section 8.3 rules for expanded names + tree_t du = find_enclosing(nametab, S_DESIGN_UNIT); + if (du == decl || (kind == T_ENTITY && primary_unit_of(du) == decl)) + return ref; + else if (kind == T_PACKAGE && is_uninstantiated_package(decl)) + parse_error(CURRENT_LOC, "cannot reference %s in uninstantiated " + "package %s outside of the package itself", + istr(suffix), istr(tree_ident(decl))); + else if (kind != T_PACKAGE && kind != T_PACK_INST + && !is_enclosing(nametab, decl)) { + diag_t *d = diag_new(DIAG_ERROR, CURRENT_LOC); + diag_printf(d, "expanded name cannot reference %s in %s %s " + "outside of the construct itself", istr(suffix), + class_str(class_of(decl)), istr(tree_ident(decl))); + diag_lrm(d, STD_08, "8.3"); + diag_emit(d); + } + + return ref; + } } if (scope_formal_kind(nametab) == F_SUBPROGRAM) { diff --git a/test/parse/visibility11.vhd b/test/parse/visibility11.vhd new file mode 100644 index 00000000..c178d06b --- /dev/null +++ b/test/parse/visibility11.vhd @@ -0,0 +1,26 @@ +package pack is + generic ( g : integer ); +end package; + +------------------------------------------------------------------------------- + +entity e is +end entity; + +architecture test of e is + package inst is new work.pack generic map ( 4 ); + use inst.all; + + constant c1 : integer := inst.g; -- OK + constant c2 : integer := g; -- OK + constant c3 : integer := work.pack.g; -- Error +begin + + b: block is + signal s : integer; + begin + end block; + + b.s <= 3; -- Error + +end architecture; diff --git a/test/test_parse.c b/test/test_parse.c index c72e71e4..0764a2f1 100644 --- a/test/test_parse.c +++ b/test/test_parse.c @@ -6042,6 +6042,41 @@ START_TEST(test_issue805) } END_TEST +START_TEST(test_visibility11) +{ + set_standard(STD_08); + + input_from_file(TESTDIR "/parse/visibility11.vhd"); + + const error_t expect[] = { + { 16, "cannot reference G in uninstantiated package WORK.PACK outside " + "of the package itself" }, + { 24, "expanded name cannot reference S in label B outside of the " + "construct itself" }, + { -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 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 + Suite *get_parse_tests(void) { Suite *s = suite_create("parse"); @@ -6175,6 +6210,7 @@ Suite *get_parse_tests(void) tcase_add_test(tc_core, test_slow1); tcase_add_test(tc_core, test_issue802); tcase_add_test(tc_core, test_issue805); + tcase_add_test(tc_core, test_visibility11); suite_add_tcase(s, tc_core); return s; -- 2.39.2