Skip to content

Commit

Permalink
Hide homographs within a declaration. Issue #733
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Jul 7, 2023
1 parent dd9ce69 commit 3d2128c
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 13 deletions.
47 changes: 36 additions & 11 deletions src/names.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,13 +553,18 @@ static const symbol_t *symbol_for(scope_t *s, ident_t name)
return NULL;
}

static const decl_t *get_decl(const symbol_t *sym, unsigned nth)
static inline const decl_t *get_decl(const symbol_t *sym, unsigned nth)
{
assert(nth < sym->ndecls);
if (nth < INLINE_DECLS)
return &(sym->decls[nth]);
else
return &(sym->overflow[nth - INLINE_DECLS]);
return (nth < INLINE_DECLS)
? &(sym->decls[nth]) : &(sym->overflow[nth - INLINE_DECLS]);
}

static inline decl_t *get_decl_mutable(symbol_t *sym, unsigned nth)
{
assert(nth < sym->ndecls);
return (nth < INLINE_DECLS)
? &(sym->decls[nth]) : &(sym->overflow[nth - INLINE_DECLS]);
}

static decl_t *add_decl(symbol_t *sym)
Expand Down Expand Up @@ -735,8 +740,7 @@ static symbol_t *make_visible(scope_t *s, ident_t name, tree_t decl,
kind = ATTRIBUTE;

for (int i = 0; i < sym->ndecls; i++) {
decl_t *dd = (i < INLINE_DECLS)
? &(sym->decls[i]) : &(sym->overflow[i - INLINE_DECLS]);
decl_t *dd = get_decl_mutable(sym, i);

if (dd->tree == decl)
return sym; // Ignore duplicates
Expand Down Expand Up @@ -1157,6 +1161,22 @@ void insert_name(nametab_t *tab, tree_t decl, ident_t alias)
make_visible_slow(tab->top_scope, alias ?: tree_ident(decl), decl);
}

void hide_name(nametab_t *tab, ident_t name)
{
const symbol_t *exist = symbol_for(tab->top_scope, name);
if (exist == NULL || exist->owner == tab->top_scope)
return;

symbol_t *sym = local_symbol_for(tab->top_scope, name);

for (int i = 0; i < sym->ndecls; i++) {
decl_t *dd = get_decl_mutable(sym, i);

if (dd->origin != tab->top_scope && dd->visibility == DIRECT)
dd->visibility = HIDDEN;
}
}

void insert_spec(nametab_t *tab, tree_t spec, spec_kind_t kind,
ident_t ident, int depth)
{
Expand Down Expand Up @@ -1471,8 +1491,11 @@ tree_t resolve_name(nametab_t *tab, const loc_t *loc, ident_t name)

return NULL;
}
else if (sym->ndecls == 1)
return get_decl(sym, 0)->tree;
else if (sym->ndecls == 1) {
const decl_t *dd = get_decl(sym, 0);
if (dd->visibility != HIDDEN)
return dd->tree;
}

// Check if all but one declartion is hidden
int hidden = 0, overload = 0, subprograms = 0;
Expand Down Expand Up @@ -1561,7 +1584,9 @@ tree_t resolve_name(nametab_t *tab, const loc_t *loc, ident_t name)
return NULL; // Was an earlier error

diag_t *d = diag_new(DIAG_ERROR, loc);
if (overload == 0)
if (hidden > 0 && hidden == sym->ndecls)
diag_printf(d, "declaration of %s is hidden", istr(name));
else if (overload == 0)
diag_printf(d, "multiple conflicting visible declarations of %s",
istr(name));
else
Expand All @@ -1584,7 +1609,7 @@ tree_t resolve_name(nametab_t *tab, const loc_t *loc, ident_t name)
tb_printf(tb, " declaration of %s", istr(name));

type_t type = get_type_or_null(dd->tree);
if (type != NULL)
if (type != NULL && !is_type_decl(dd->tree))
tb_printf(tb, " as %s", type_pp(tree_type(dd->tree)));

if (dd->origin->container != NULL)
Expand Down
2 changes: 2 additions & 0 deletions src/names.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ void insert_names_for_config(nametab_t *tab, tree_t unit);
void insert_spec(nametab_t *tab, tree_t spec, spec_kind_t kind,
ident_t ident, int depth);

void hide_name(nametab_t *tab, ident_t name);

ident_t get_implicit_label(tree_t t, nametab_t *tab);
void continue_proc_labelling_from(tree_t t, nametab_t *tab);

Expand Down
27 changes: 25 additions & 2 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -6225,6 +6225,7 @@ static void p_type_declaration(tree_t container)
consume(tTYPE);

ident_t id = p_identifier();
hide_name(nametab, id);

// Protected type bodies are broken out here to avoid having to
// return a dummy type for them in p_full_type_declaration
Expand Down Expand Up @@ -6297,9 +6298,14 @@ static tree_t p_subtype_declaration(void)
BEGIN("subtype declaration");

consume(tSUBTYPE);

ident_t id = p_identifier();
hide_name(nametab, id);

consume(tIS);

type_t sub = p_subtype_indication();

consume(tSEMI);

if (type_kind(sub) != T_SUBTYPE || type_has_ident(sub)) {
Expand Down Expand Up @@ -6430,6 +6436,9 @@ static void p_constant_declaration(tree_t parent)

LOCAL_IDENT_LIST ids = p_identifier_list();

for (ident_list_t *it = ids; it != NULL; it = it->next)
hide_name(nametab, it->ident);

consume(tCOLON);

type_t type = p_subtype_indication();
Expand Down Expand Up @@ -6799,6 +6808,9 @@ static void p_variable_declaration(tree_t parent)

LOCAL_IDENT_LIST ids = p_identifier_list();

for (ident_list_t *it = ids; it != NULL; it = it->next)
hide_name(nametab, it->ident);

consume(tCOLON);

type_t type = p_subtype_indication();
Expand Down Expand Up @@ -6856,6 +6868,9 @@ static void p_signal_declaration(tree_t parent)

LOCAL_IDENT_LIST ids = p_identifier_list();

for (ident_list_t *it = ids; it != NULL; it = it->next)
hide_name(nametab, it->ident);

consume(tCOLON);

type_t type = p_subtype_indication();
Expand Down Expand Up @@ -6928,9 +6943,14 @@ static tree_t p_alias_declaration(void)

tree_t t = tree_new(T_ALIAS);

bool has_subtype_indication = false;
consume(tALIAS);
tree_set_ident(t, p_designator());

ident_t id = p_designator();
tree_set_ident(t, id);

hide_name(nametab, id);

bool has_subtype_indication = false;
if (optional(tCOLON)) {
tree_set_type(t, p_subtype_indication());
has_subtype_indication = true;
Expand Down Expand Up @@ -7030,6 +7050,9 @@ static void p_file_declaration(tree_t parent)

LOCAL_IDENT_LIST ids = p_identifier_list();

for (ident_list_t *it = ids; it != NULL; it = it->next)
hide_name(nametab, it->ident);

consume(tCOLON);

type_t type = p_subtype_indication();
Expand Down
31 changes: 31 additions & 0 deletions test/parse/visibility8.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
entity visibility8 is
end entity;

architecture test of visibility8 is
constant c1 : integer := 1;
subtype t1 is integer;
type t2 is range 1 to 3;
signal s1 : bit_vector(1 to 6);
shared variable v1 : integer;
alias a1 is c1;
constant f1 : file_open_kind := READ_MODE;
type ft is file of character;
begin

b1: block is
signal s1 : bit_vector(1 to s1'length); -- Error
begin
end block;

p1: process is
constant c1 : integer := c1; -- Error
subtype t1 is t1; -- Error
type t2 is range t2'left to 5; -- Error
variable v1 : integer := v1; -- Error
alias a1 is a1; -- Error
file f1 : ft open f1 is "x"; -- Error
begin
wait;
end process;

end architecture;
32 changes: 32 additions & 0 deletions test/test_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -5588,6 +5588,37 @@ START_TEST(test_issue727)
}
END_TEST

START_TEST(test_visibility8)
{
input_from_file(TESTDIR "/parse/visibility8.vhd");

const error_t expect[] = {
{ 16, "declaration of S1 is hidden" },
{ 21, "declaration of C1 is hidden" },
{ 22, "declaration of T1 is hidden" },
{ 23, "declaration of T2 is hidden" },
{ 24, "declaration of V1 is hidden" },
{ 25, "declaration of A1 is hidden" },
{ 26, "declaration of F1 is hidden" },
{ -1, NULL }
};
expect_errors(expect);

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");
Expand Down Expand Up @@ -5705,6 +5736,7 @@ Suite *get_parse_tests(void)
tcase_add_test(tc_core, test_issue701);
tcase_add_test(tc_core, test_issue708);
tcase_add_test(tc_core, test_issue727);
tcase_add_test(tc_core, test_visibility8);
suite_add_tcase(s, tc_core);

return s;
Expand Down

0 comments on commit 3d2128c

Please sign in to comment.