Skip to content

Commit

Permalink
Fixes to handling of staticness of generics and constants
Browse files Browse the repository at this point in the history
Fixes xxx
  • Loading branch information
nickg committed Nov 3, 2024
1 parent eb890b4 commit f19f21d
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1712,7 +1712,7 @@ static bool is_static(tree_t expr)
tree_t decl = tree_ref(expr);
switch (tree_kind(decl)) {
case T_CONST_DECL:
return !(tree_flags(decl) & TREE_F_SEQ_BLOCK);
return !!(tree_flags(decl) & TREE_F_GLOBALLY_STATIC);
case T_UNIT_DECL:
case T_ENUM_LIT:
case T_GENERIC_DECL:
Expand Down
35 changes: 35 additions & 0 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -4997,6 +4997,20 @@ static void p_interface_constant_declaration(tree_t parent, tree_kind_t kind,
if ((mode == PORT_OUT || mode == PORT_INOUT) && !explicit_constant)
class = C_VARIABLE;

if (kind == T_GENERIC_DECL) {
// In the 2008 standard generics in packages or subprograms are
// locally static if they have a locally static subtype subtype
switch (tree_kind(parent)) {
case T_PACKAGE:
case T_FUNC_DECL:
case T_PROC_DECL:
flags |= TREE_F_LOCALLY_STATIC;
break;
default:
break;
}
}

type_t type = p_interface_type_indication(parent);

tree_t init = NULL;
Expand Down Expand Up @@ -6919,12 +6933,33 @@ static void p_constant_declaration(tree_t parent)
solve_known_subtype(nametab, init, type);
}

// According to the LRM all constants are globally static but that
// leads to a number of logical inconsistencies so we retrict to only
// constants in certain regions where the value can be computed
// during elaboration
tree_flags_t flags = 0;
switch (tree_kind(parent)) {
case T_ENTITY:
case T_ARCH:
case T_PACKAGE:
case T_PACK_BODY:
case T_BLOCK:
case T_FOR_GENERATE:
case T_COND_STMT: // If-generate
case T_ALTERNATIVE: // For-generate
flags |= TREE_F_GLOBALLY_STATIC;
break;
default:
break;
}

consume(tSEMI);

for (ident_list_t *it = ids; it != NULL; it = it->next) {
tree_t t = tree_new(T_CONST_DECL);
tree_set_ident(t, it->ident);
tree_set_type(t, type);
tree_set_flag(t, flags);
tree_set_loc(t, &(it->loc));
if (init != NULL)
tree_set_value(t, init);
Expand Down
34 changes: 14 additions & 20 deletions src/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -5541,8 +5541,9 @@ static bool sem_locally_static(tree_t t)
if (dkind == T_ALIAS)
return sem_locally_static(tree_value(decl));

// [2008] A generic reference with a locally static subtype
if (dkind == T_GENERIC_DECL && (standard() >= STD_08 || relaxed_rules()))
// [2008] A formal generic constant of a generic-mapped subprogram
// or package with a locally static subtype
if (dkind == T_GENERIC_DECL && (tree_flags(decl) & TREE_F_LOCALLY_STATIC))
return sem_static_subtype(tree_type(decl), sem_locally_static);
}

Expand Down Expand Up @@ -5794,8 +5795,16 @@ static bool sem_globally_static(tree_t t)

if (kind == T_REF) {
tree_t decl = tree_ref(t);
const tree_kind_t decl_kind = tree_kind(decl);
return decl_kind == T_GENERIC_DECL || decl_kind == T_CONST_DECL;
switch (tree_kind(decl)) {
case T_GENERIC_DECL:
return true;
case T_CONST_DECL:
// Do not treat all constants as globally static, this is a
// defect in the LRM
return !!(tree_flags(decl) & TREE_F_GLOBALLY_STATIC);
default:
return false;
}
}
else if (kind == T_EXTERNAL_NAME)
return tree_class(t) == C_CONSTANT;
Expand Down Expand Up @@ -7157,20 +7166,6 @@ static bool sem_check_cond_value(tree_t t, nametab_t *tab)
return true;
}

static bool sem_check_sequence(tree_t t, nametab_t *tab)
{
const int ndecls = tree_decls(t);
for (int i = 0; i < ndecls; i++) {
// Mark all constant declarations as they need to be treated
// specially when calculating longest static prefix
tree_t d = tree_decl(t, i);
if (tree_kind(d) == T_CONST_DECL)
tree_set_flag(d, TREE_F_SEQ_BLOCK);
}

return true;
}

static bool sem_check_prot_decl(tree_t t, nametab_t *tab)
{
const int ndecls = tree_decls(t);
Expand Down Expand Up @@ -7349,6 +7344,7 @@ bool sem_check(tree_t t, nametab_t *tab)
case T_BOX:
case T_PSL:
case T_LOOP:
case T_SEQUENCE:
return true;
case T_CONV_FUNC:
return sem_check_conv_func(t, tab);
Expand All @@ -7374,8 +7370,6 @@ bool sem_check(tree_t t, nametab_t *tab)
return sem_check_view_decl(t, tab);
case T_COND_VALUE:
return sem_check_cond_value(t, tab);
case T_SEQUENCE:
return sem_check_sequence(t, tab);
case T_PROT_DECL:
return sem_check_prot_decl(t, tab);
case T_INERTIAL:
Expand Down
1 change: 0 additions & 1 deletion src/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,6 @@ typedef enum {
TREE_F_IMPURE_FILE = (1 << 22),
TREE_F_IMPURE_SHARED = (1 << 23),
TREE_F_CALL_NO_ARGS = (1 << 24),
TREE_F_SEQ_BLOCK = (1 << 25),
} tree_flags_t;

typedef enum {
Expand Down
2 changes: 1 addition & 1 deletion test/sem/issue105.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ begin
process (x) is
begin
case x is
when GEN => -- OK in 2008
when GEN => -- Error (used to be allowed)
report "x = GEN";
when others =>
report "x /= GEN";
Expand Down
8 changes: 7 additions & 1 deletion test/test_sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1316,11 +1316,17 @@ START_TEST(test_issue105)
{
set_standard(STD_08);

const error_t expect[] = {
{ 12, "case choice must be locally static" },
{ -1, NULL }
};
expect_errors(expect);

input_from_file(TESTDIR "/sem/issue105.vhd");

parse_and_check(T_ENTITY, T_ARCH, T_ENTITY, T_ARCH);

fail_if_errors();
check_expected_errors();
}
END_TEST

Expand Down

0 comments on commit f19f21d

Please sign in to comment.