Skip to content

Commit

Permalink
Fix parsing alias of enumeration literal with signature
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Jun 12, 2021
1 parent 8feca16 commit c7f6aed
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 31 deletions.
12 changes: 9 additions & 3 deletions src/names.c
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ static tree_t resolve_ref(nametab_t *tab, tree_t ref)
{
type_t constraint;
if (type_set_uniq(tab, &constraint) && type_is_subprogram(constraint)) {
// Reference to subprogram with signature
// Reference to subprogram or enumeration literal with signature

ident_t full_name = tree_ident(ref);
tree_t prefix = NULL;
Expand All @@ -882,6 +882,9 @@ static tree_t resolve_ref(nametab_t *tab, tree_t ref)
full_name = ident_from(full_name, '.');
}

const bool allow_enum =
type_kind(constraint) == T_FUNC && type_params(constraint) == 0;

bool match = false;
tree_t decl = NULL;
for (int n = 0;
Expand All @@ -890,12 +893,15 @@ static tree_t resolve_ref(nametab_t *tab, tree_t ref)
n++) {
if (is_subprogram(decl))
match = type_eq(constraint, tree_type(decl));
else if (allow_enum && tree_kind(decl) == T_ENUM_LIT)
match = type_eq(type_result(constraint), tree_type(decl));
}

if (!match) {
const char *signature = strchr(type_pp(constraint), '[');
error_at(tree_loc(ref), "no visible subprogram %s matches "
"signature %s", istr(tree_ident(ref)), signature);
error_at(tree_loc(ref), "no visible subprogram%s %s matches "
"signature %s", allow_enum ? " or enumeration literal" : "",
istr(tree_ident(ref)), signature);
return NULL;
}
else
Expand Down
37 changes: 14 additions & 23 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1334,14 +1334,6 @@ static void binary_op(tree_t expr, tree_t left, tree_t (*right_fn)(void))
add_param(expr, right, P_POS, NULL);
}

static bool bare_subprogram_name(void)
{
// Context in which a function name appears as a reference rather
// than a call (i.e. before a signature or as a resolution function
// name in a subtype declaration)
return peek() == tLSQUARE || peek() == tID || peek() == tTICK;
}

static tree_t implicit_dereference(tree_t t)
{
type_t access = type_access(tree_type(t));
Expand Down Expand Up @@ -1492,27 +1484,26 @@ static tree_t select_decl(tree_t prefix, ident_t suffix)
parse_error(CURRENT_LOC, "name %s not found in %s", istr(suffix),
istr(tree_ident(prefix)));
}
else if (is_subprogram(d)) {
if (bare_subprogram_name()) {
// Overload will be resolved after signature has been parsed
tree_t ref = tree_new(T_REF);
tree_set_ident(ref, qual);
tree_set_loc(ref, CURRENT_LOC);
return ref;
}
else {
tree_t f = p_function_call(suffix, prefix);
tree_set_ident(f, qual);
return f;
}
else if (is_subprogram(d) && peek() != tLSQUARE) {
tree_t f = p_function_call(suffix, prefix);
tree_set_ident(f, qual);
return f;
}

tree_t ref = tree_new(T_REF);
tree_set_ident(ref, qual);
tree_set_ref(ref, d);
tree_set_type(ref, d ? tree_type(d) : type_new(T_NONE));
tree_set_loc(ref, CURRENT_LOC);

// If the name is followed by a signature we need to parse that
// before resolving the overload
const bool need_signature =
peek() == tLSQUARE && (is_subprogram(d) || tree_kind(d) == T_ENUM_LIT);

if (!need_signature) {
tree_set_ref(ref, d);
tree_set_type(ref, d ? tree_type(d) : type_new(T_NONE));
}

return ref;
}

Expand Down
3 changes: 1 addition & 2 deletions src/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -856,10 +856,9 @@ static bool sem_check_alias(tree_t t)
if (type_is_none(type))
return false;
else if (type_is_subprogram(type)) {
// Alias of subprogram
// Alias of subprogram or enumeration literal
// Rules for matching signatures are in LRM 93 section 2.3.2
assert(tree_kind(value) == T_REF);
assert(!tree_has_ref(value) || type_eq(type, tree_type(tree_ref(value))));
}
else if (tree_kind(value) == T_REF
&& tree_kind(tree_ref(value)) == T_TYPE_DECL) {
Expand Down
File renamed without changes.
33 changes: 33 additions & 0 deletions test/sem/osvvm2.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package OsvvmGlobalPkg is
type OsvvmOptionsType is (OPT_INIT_PARM_DETECT, OPT_USE_DEFAULT, DISABLED, FALSE, ENABLED, TRUE) ;

-- Defaults for String values
constant OSVVM_DEFAULT_ALERT_PREFIX : string := "%% Alert" ;
constant OSVVM_DEFAULT_LOG_PREFIX : string := "%% Log " ;
constant OSVVM_DEFAULT_WRITE_PREFIX : string := "%% " ;
constant OSVVM_DEFAULT_DONE_NAME : string := "DONE" ;
constant OSVVM_DEFAULT_PASS_NAME : string := "PASSED" ;
constant OSVVM_DEFAULT_FAIL_NAME : string := "FAILED" ;
constant OSVVM_STRING_INIT_PARM_DETECT : string := NUL & NUL & NUL ;
constant OSVVM_STRING_USE_DEFAULT : string := NUL & "" ;

-- Coverage Settings
constant OSVVM_DEFAULT_WRITE_PASS_FAIL : OsvvmOptionsType := FALSE ;
constant OSVVM_DEFAULT_WRITE_BIN_INFO : OsvvmOptionsType := TRUE ;
constant OSVVM_DEFAULT_WRITE_COUNT : OsvvmOptionsType := TRUE ;
constant OSVVM_DEFAULT_WRITE_ANY_ILLEGAL : OsvvmOptionsType := FALSE ;

end OsvvmGlobalPkg ;

use work.OsvvmGlobalPkg.all ;

package CoveragePkg is

-- type OsvvmOptionsType is (OPT_DEFAULT, FALSE, TRUE) ;
alias CovOptionsType is work.OsvvmGlobalPkg.OsvvmOptionsType ;
constant COV_OPT_INIT_PARM_DETECT : CovOptionsType := work.OsvvmGlobalPkg.OPT_INIT_PARM_DETECT ;
-- For backward compatibility. Don't add to other packages.
alias DISABLED is work.OsvvmGlobalPkg.DISABLED [return work.OsvvmGlobalPkg.OsvvmOptionsType ];
alias ENABLED is work.OsvvmGlobalPkg.ENABLED [return work.OsvvmGlobalPkg.OsvvmOptionsType ];

end package CoveragePkg ;
18 changes: 15 additions & 3 deletions test/test_sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2206,17 +2206,28 @@ START_TEST(test_resolution)
}
END_TEST

START_TEST(test_osvmm1)
START_TEST(test_osvvm1)
{
set_standard(STD_08);
input_from_file(TESTDIR "/sem/osvmm1.vhd");
input_from_file(TESTDIR "/sem/osvvm1.vhd");

parse_and_check(T_PACKAGE, T_PACK_BODY);

fail_if_errors();
}
END_TEST

START_TEST(test_osvvm2)
{
set_standard(STD_08);
input_from_file(TESTDIR "/sem/osvvm2.vhd");

parse_and_check(T_PACKAGE, T_PACKAGE);

fail_if_errors();
}
END_TEST

Suite *get_sem_tests(void)
{
Suite *s = suite_create("sem");
Expand Down Expand Up @@ -2327,7 +2338,8 @@ Suite *get_sem_tests(void)
tcase_add_test(tc_core, test_block);
tcase_add_test(tc_core, test_issue407);
tcase_add_test(tc_core, test_resolution);
tcase_add_test(tc_core, test_osvmm1);
tcase_add_test(tc_core, test_osvvm1);
tcase_add_test(tc_core, test_osvvm2);
suite_add_tcase(s, tc_core);

return s;
Expand Down

0 comments on commit c7f6aed

Please sign in to comment.