From f1b22c3cfab96e1a11e8e83246c80ea36adedb2e Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 17 Jan 2024 20:58:06 +0000 Subject: [PATCH] Ensure port map expression has globally static subtype --- src/diag.c | 1 + src/sem.c | 15 +++++++++++++++ test/dist.mk | 1 - test/sem/ports2008.vhd | 12 ------------ test/sem/vhdl2008.vhd | 16 ++++++++++++++++ test/test_sem.c | 22 ++++++++++++---------- 6 files changed, 44 insertions(+), 23 deletions(-) delete mode 100644 test/sem/ports2008.vhd diff --git a/src/diag.c b/src/diag.c index 6b4ec458..fcd56949 100644 --- a/src/diag.c +++ b/src/diag.c @@ -437,6 +437,7 @@ static const struct { [STD_02] = "3.5.1" } }, { "Type conversions", { [STD_93] = "7.3.5", [STD_08] = "9.3.6" } }, { "External names", { [STD_08] = "8.7" } }, + { "Port clauses", { [STD_08] = "6.5.6.3" } }, }; diag_t *diag_new(diag_level_t level, const loc_t *loc) diff --git a/src/sem.c b/src/sem.c index 834b7020..9cc86aaa 100644 --- a/src/sem.c +++ b/src/sem.c @@ -44,6 +44,7 @@ static tree_t sem_check_lvalue(tree_t t); static bool sem_check_same_type(tree_t left, tree_t right); static bool sem_check_type(tree_t t, type_t expect, nametab_t *tab); static bool sem_static_name(tree_t t, static_fn_t check_fn); +static bool sem_static_subtype(type_t type, static_fn_t fn); static bool sem_check_attr_ref(tree_t t, bool allow_range, nametab_t *tab); static bool sem_check_generic_map(tree_t t, tree_t unit, nametab_t *tab); static bool sem_check_port_map(tree_t t, tree_t unit, nametab_t *tab); @@ -4463,6 +4464,20 @@ static bool sem_check_port_actual(formal_map_t *formals, int nformals, // signal assignment to an anonymous signal that is then // associated with the formal if (!is_static && standard() >= STD_08) { + // The rules listed for unconstrained ports in 6.5.6.3 should + // be covered by the check for a globally static subtype in + // addition to the checks above + if (type_is_unconstrained(type) + && !sem_static_subtype(value_type, sem_globally_static)) { + diag_t *d = diag_new(DIAG_ERROR, tree_loc(value)); + diag_printf(d, "expression associated with unconstrained formal " + "port %s must have a globally static subtype", + istr(tree_ident(decl))); + diag_lrm(d, STD_08, "6.5.6.3"); + diag_emit(d); + return false; + } + tree_t w = tree_new(T_WAVEFORM); tree_set_loc(w, tree_loc(value)); tree_set_value(w, value); diff --git a/test/dist.mk b/test/dist.mk index fa64576c..b35708da 100644 --- a/test/dist.mk +++ b/test/dist.mk @@ -1771,7 +1771,6 @@ EXTRA_DIST += \ test/sem/osvvm4.vhd \ test/sem/osvvm5.vhd \ test/sem/physical.vhd \ - test/sem/ports2008.vhd \ test/sem/ports.vhd \ test/sem/procedure.vhd \ test/sem/protected2.vhd \ diff --git a/test/sem/ports2008.vhd b/test/sem/ports2008.vhd deleted file mode 100644 index 271890e7..00000000 --- a/test/sem/ports2008.vhd +++ /dev/null @@ -1,12 +0,0 @@ -entity sub is - port ( - x : in integer ); -end entity; - -entity top is -end entity; - -architecture test of top is -begin - -end architecture; diff --git a/test/sem/vhdl2008.vhd b/test/sem/vhdl2008.vhd index a29dbeac..9144da37 100644 --- a/test/sem/vhdl2008.vhd +++ b/test/sem/vhdl2008.vhd @@ -88,4 +88,20 @@ begin end block; end block; + -- Port maps with non-globally-static expressions + b2: block is + type t_array is array (natural range <>) of integer; + signal s : integer; + function get_array (signal s : integer; constant x : integer) return t_array is + begin + return (1 to 3 => s + x); + end function; + begin + sub1: block is + port ( p1 : t_array ); + port map ( p1 => get_array(s, 5) ); -- Error + begin + end block; + end block; + end architecture; diff --git a/test/test_sem.c b/test/test_sem.c index a2e06a0f..83f23893 100644 --- a/test/test_sem.c +++ b/test/test_sem.c @@ -2522,16 +2522,18 @@ START_TEST(test_vhdl2008) input_from_file(TESTDIR "/sem/vhdl2008.vhd"); const error_t expect[] = { - { 13, "type of condition must be BOOLEAN but have INTEGER" }, - { 14, "expected type of conditional expression to be INTEGER " - "but is BOOLEAN" }, - { 31, "case choice must be locally static" }, - { 40, "no visible declaration for BAZ" }, - { 41, "SUBTYPE attribute is only allowed in a type mark" }, - { 49, "case choice must be globally static" }, - { 59, "range choice expression must have same type as aggregate" }, - { 70, "conversion only allowed between closely related types" }, - { 86, "no visible declaration for Q" }, + { 13, "type of condition must be BOOLEAN but have INTEGER" }, + { 14, "expected type of conditional expression to be INTEGER " + "but is BOOLEAN" }, + { 31, "case choice must be locally static" }, + { 40, "no visible declaration for BAZ" }, + { 41, "SUBTYPE attribute is only allowed in a type mark" }, + { 49, "case choice must be globally static" }, + { 59, "range choice expression must have same type as aggregate" }, + { 70, "conversion only allowed between closely related types" }, + { 86, "no visible declaration for Q" }, + { 102, "expression associated with unconstrained formal port P1 " + "must have a globally static subtype" }, { -1, NULL } }; expect_errors(expect); -- 2.39.2