diff --git a/src/diag.c b/src/diag.c index 8c2569e7c..df601a380 100644 --- a/src/diag.c +++ b/src/diag.c @@ -412,6 +412,7 @@ static const struct { { "Interface package declarations", { [STD_08] = "6.5.5" } }, { "Selected names", { [STD_08] = "8.3", [STD_93] = "6.3" } }, { "Simple variable assignments", { [STD_08] = "10.6.2" } }, + { "Configuration declarations", { [STD_08] = "3.4", [STD_93] = "1.4" } }, }; diag_t *diag_new(diag_level_t level, const loc_t *loc) diff --git a/src/parse.c b/src/parse.c index 00a324128..0f1cc51f6 100644 --- a/src/parse.c +++ b/src/parse.c @@ -494,44 +494,6 @@ static tree_t error_expr(void) return t; } -static tree_t find_unit(const loc_t *where, ident_t name, const char *hint) -{ - // TODO: should be able to replace this with resolve_name - - ident_t lname = ident_until(name, '.'); - lib_t lib = lib_loaded(lname); - if (lib != NULL) { - bool error; - tree_t unit = lib_get_allow_error(lib, name, &error); - if (unit == NULL) { - if (hint != NULL) - parse_error(where, "missing declaration for %s %s", - hint, istr(name)); - else - parse_error(where, "cannot find unit %s", istr(name)); - } - else if (error) { - parse_error(where, "design unit depends on %s which was analysed" - " with errors", istr(name)); - suppress_errors(nametab); - return NULL; - } - - return unit; - } - else if (name == error_marker()) - return NULL; - else if (lname == name) { - parse_error(where, "%s does not name a visible component or design unit", - istr(name)); - return NULL; - } - else { - parse_error(where, "missing library clause for %s", istr(lname)); - return NULL; - } -} - static tree_t find_binding(tree_t inst) { ident_t name; @@ -2578,14 +2540,14 @@ static void p_context_reference(tree_t unit) tree_set_ident(c, name); tree_set_loc(c, CURRENT_LOC); - tree_t ctx = find_unit(CURRENT_LOC, name, "context"); + tree_t ctx = resolve_name(nametab, CURRENT_LOC, name); if (ctx != NULL && tree_kind(ctx) == T_CONTEXT) { insert_names_from_context(nametab, ctx); tree_set_ref(c, ctx); } else if (ctx != NULL) - parse_error(CURRENT_LOC, "unit %s is not a context declaration", - istr(name)); + parse_error(CURRENT_LOC, "%s%s is not a context declaration", + is_design_unit(ctx) ? "design unit " : "", istr(name)); tree_add_context(unit, c); } while (optional(tCOMMA)); @@ -3195,7 +3157,7 @@ static tree_t p_selected_name(tree_t prefix, name_mask_t *mask) const tree_kind_t kind = tree_kind(decl); if (kind == T_LIBRARY) { ident_t unit_name = ident_prefix(tree_ident(decl), suffix, '.'); - tree_t unit = find_unit(CURRENT_LOC, unit_name, NULL); + tree_t unit = resolve_name(nametab, CURRENT_LOC, unit_name); if (unit == NULL) { tree_t dummy = tree_new(T_REF); tree_set_ident(dummy, unit_name); @@ -5304,7 +5266,7 @@ static void p_interface_package_declaration(tree_t parent, tree_kind_t kind) ident_t unit_name = p_selected_identifier(); - tree_t pack = find_unit(CURRENT_LOC, unit_name, "package"); + tree_t pack = resolve_name(nametab, CURRENT_LOC, unit_name); if (pack != NULL && !is_uninstantiated_package(pack)) { parse_error(CURRENT_LOC, "unit %s is not an uninstantiated package", istr(unit_name)); @@ -8699,7 +8661,7 @@ static tree_t p_block_configuration(tree_t of) case T_ENTITY: { ident_t qual = ident_prefix(tree_ident(of), tree_ident(b), '-'); - sub = find_unit(CURRENT_LOC, qual, NULL); + sub = resolve_name(nametab, CURRENT_LOC, qual); } break; case T_ARCH: @@ -8763,6 +8725,34 @@ static tree_t p_block_configuration(tree_t of) return b; } +static ident_t p_entity_name(tree_t *entity) +{ + // name + + BEGIN("entity name"); + + ident_t ename = p_selected_identifier(); + + ident_t qual = ename; + if (ident_runtil(ename, '.') == ename) + qual = ident_prefix(lib_name(lib_work()), ename, '.'); + + *entity = resolve_name(nametab, CURRENT_LOC, qual); + + if (*entity != NULL && tree_kind(*entity) != T_ENTITY) { + diag_t *d = diag_new(DIAG_ERROR, CURRENT_LOC); + diag_printf(d, "%s%s is not an entity", + is_design_unit(*entity) ? "design unit " : "", istr(ename)); + diag_hint(d, tree_loc(*entity), "%s is a %s", istr(ename), + class_str(class_of(*entity))); + diag_emit(d); + *entity = NULL; + return ename; + } + + return ename; +} + static void p_configuration_declaration(tree_t unit) { // configuration identifier of name is configuration_declarative_part @@ -8781,17 +8771,11 @@ static void p_configuration_declaration(tree_t unit) consume(tOF); - ident_t ename = p_identifier(); - ident_t qual = ident_prefix(lib_name(lib_work()), ename, '.'); - tree_set_ident2(unit, qual); + tree_t of = NULL; + ident_t ename = p_entity_name(&of); + tree_set_ident2(unit, ename); - tree_t of = find_unit(CURRENT_LOC, qual, "entity"); - if (of != NULL && tree_kind(of) != T_ENTITY) { - parse_error(CURRENT_LOC, "%s does not name an entity in library %s", - istr(ename), istr(lib_name(lib_work()))); - of = NULL; - } - else if (of != NULL) { + if (of != NULL) { tree_set_primary(unit, of); insert_name(nametab, of, ename); insert_decls(nametab, of); @@ -12202,27 +12186,23 @@ static void p_architecture_body(tree_t unit) consume(tOF); - ident_t entity_name = p_identifier(); + tree_t e = NULL; + ident_t entity_name = p_entity_name(&e); tree_set_ident2(unit, entity_name); consume(tIS); - ident_t ename = ident_prefix(lib_name(lib_work()), entity_name, '.'); - tree_t e = find_unit(CURRENT_LOC, ename, "entity"); - if (e != NULL && tree_kind(e) == T_ENTITY) { + if (e != NULL) { tree_set_primary(unit, e); insert_names_from_context(nametab, e); } - else if (e != NULL) { - parse_error(CURRENT_LOC, "unit %s is not an entity", istr(ename)); - e = NULL; - } push_scope(nametab); if (entity_name != arch_name && e != NULL) insert_name(nametab, e, entity_name); + ident_t ename = ident_prefix(lib_name(lib_work()), entity_name, '.'); ident_t qual = ident_prefix(ename, arch_name, '-'); scope_set_prefix(nametab, qual); diff --git a/src/sem.c b/src/sem.c index 2aeeb5161..c5f0eb30c 100644 --- a/src/sem.c +++ b/src/sem.c @@ -5543,6 +5543,31 @@ static bool sem_check_spec(tree_t t, nametab_t *tab) static bool sem_check_configuration(tree_t t, nametab_t *tab) { + if (!tree_has_primary(t)) + return false; // Was parse error + + tree_t of = tree_primary(t); + + // LRM 08 section 3.4.1: for a configuration of a given design + // entity, both the configuration declaration and the corresponding + // entity declaration shall reside in the same library + ident_t elib = ident_until(tree_ident(of), '.'); + if (standard() < STD_19 && elib != lib_name(lib_work())) { + diag_t *d = pedantic_diag(t); + if (d != NULL) { + ident_t ename = ident_rfrom(tree_ident(of), '.'); + diag_printf(d, "configuration declaration %s must reside in the " + "same library as entity %s", istr(tree_ident(t)), + istr(ename)); + diag_hint(d, NULL, "entity %s is in library %s which is not the same " + "as the current working library %s", + istr(ename), istr(elib), istr(lib_name(lib_work()))); + diag_lrm(d, STD_08, "3.4"); + diag_emit(d); + return false; + } + } + return true; } diff --git a/test/sem/lcs2016_23.vhd b/test/sem/lcs2016_23.vhd new file mode 100644 index 000000000..c57de911c --- /dev/null +++ b/test/sem/lcs2016_23.vhd @@ -0,0 +1,18 @@ +-- library foo +entity foo_e is +end entity; + +architecture test of foo_e is +begin +end architecture; + +------------------------------------------------------------------------------- +-- library bar + +library foo; + +configuration foo_cfg of foo.foo_e is + for test + end for; +end configuration; + diff --git a/test/test_charset.c b/test/test_charset.c index 720511832..3c244921c 100644 --- a/test/test_charset.c +++ b/test/test_charset.c @@ -119,7 +119,7 @@ Suite *get_charset_tests(void) TCase *tc = nvc_unit_test(); tcase_add_test(tc, test_iso88591); tcase_add_test(tc, test_utf8); - tcase_add_loop_test(tc, test_strings, STD_93, STD_19); + tcase_add_loop_test(tc, test_strings, STD_93, STD_19 + 1); suite_add_tcase(s, tc); return s; diff --git a/test/test_parse.c b/test/test_parse.c index 60991080a..44366b8d3 100644 --- a/test/test_parse.c +++ b/test/test_parse.c @@ -2892,7 +2892,7 @@ START_TEST(test_error) { 47, "S1 already declared in this region" }, { 50, "B1 already declared in this region" }, { 56, "C1 already declared in this region" }, - { 64, "missing declaration for entity WORK.NOT_HERE" }, + { 64, "design unit NOT_HERE not found in library WORK" }, { -1, NULL } }; expect_errors(expect); @@ -2915,9 +2915,9 @@ START_TEST(test_config) const error_t expect[] = { { 29, "no visible declaration for X" }, - { 38, "CONF does not name an entity in library WORK" }, + { 38, "design unit CONF is not an entity" }, { 39, "no visible declaration for ARCH" }, - { 45, "cannot find unit WORK.ENT-BAD" }, + { 45, "design unit ENT-BAD not found in library WORK" }, { 52, "P is not a block that can be configured" }, { 55, "instance P not found" }, { -1, NULL } @@ -2953,7 +2953,7 @@ START_TEST(test_config) fail_if(c == NULL); fail_unless(tree_kind(c) == T_CONFIGURATION); fail_unless(tree_ident(c) == ident_new("WORK.CONF")); - fail_unless(tree_ident2(c) == ident_new("WORK.ENT")); + fail_unless(tree_ident2(c) == ident_new("ENT")); fail_unless(tree_decls(c) == 3); fail_unless(tree_kind(tree_decl(c, 0)) == T_USE); fail_unless(tree_kind(tree_decl(c, 1)) == T_ATTR_SPEC); @@ -3578,7 +3578,7 @@ START_TEST(test_error2) { 2, "no visible declaration for BAR" }, { 5, "no visible declaration for SDFF" }, { 10, "no visible declaration for SGHBBX" }, - { 17, "cannot find unit STD.NOTHERE" }, + { 17, "design unit NOTHERE not found in library STD" }, { 22, "unexpected identifier while parsing range" }, { 29, "expected physical type definition trailing" }, { 33, "expected record type definition trailing identifier" }, @@ -3931,7 +3931,7 @@ START_TEST(test_badprimary) input_from_file(TESTDIR "/parse/badprimary.vhd"); const error_t expect[] = { - { 17, "missing declaration for entity WORK.NOT_HERE" }, + { 17, "design unit NOT_HERE not found in library WORK" }, { 26, "depends on WORK.NOT_HERE-BAD which was analysed with errors" }, { -1, NULL } }; @@ -4603,7 +4603,7 @@ START_TEST(test_issue468) input_from_file(TESTDIR "/parse/issue468.vhd"); const error_t expect[] = { - { 2, "cannot find unit WORK.TEST3" }, + { 2, "design unit TEST3 not found in library WORK" }, { -1, NULL } }; expect_errors(expect); diff --git a/test/test_sem.c b/test/test_sem.c index 72783a3b2..822439ab2 100644 --- a/test/test_sem.c +++ b/test/test_sem.c @@ -866,7 +866,7 @@ START_TEST(test_entity) const error_t expect[] = { { 23, "design unit E-INVALID not found in library WORK" }, { 26, "design unit WORK.PACK is not an entity" }, - { 30, "unit WORK.PACK is not an entity" }, + { 30, "design unit PACK is not an entity" }, { 61, "signal assignment statement not allowed inside passive process" }, { -1, NULL } }; @@ -1565,8 +1565,8 @@ START_TEST(test_context) input_from_file(TESTDIR "/sem/context.vhd"); const error_t expect[] = { - { 27, "unit FOO.PACK is not a context declaration" }, - { 42, "missing declaration for context WORK.BLAH" }, + { 27, "no visible declaration for FOO.PACK" }, + { 42, "design unit BLAH not found in library WORK" }, { 40, "library clause in a context declaration may not have logical" }, { 41, "context declaration use clause may not have WORK" }, { 42, "context declaration context reference may not have WORK" }, @@ -3172,6 +3172,36 @@ START_TEST(test_lcs2016_07) } END_TEST +START_TEST(test_lcs2016_23) +{ + set_standard(_i); + + input_from_file(TESTDIR "/sem/lcs2016_23.vhd"); + + const error_t expect[] = { + { 14, "configuration declaration FOO_CFG must reside in the same " + "library as entity FOO_E" }, + { -1, NULL } + }; + expect_errors(expect); + + lib_t foo = lib_tmp("foo"); + lib_set_work(foo); + + parse_and_check(T_ENTITY, T_ARCH, -1); + + lib_t bar = lib_tmp("bar"); + lib_set_work(bar); + + parse_and_check(T_CONFIGURATION); + + if (_i < STD_19) + check_expected_errors(); + else + fail_if_errors(); +} +END_TEST + Suite *get_sem_tests(void) { Suite *s = suite_create("sem"); @@ -3326,6 +3356,7 @@ Suite *get_sem_tests(void) tcase_add_test(tc_core, test_lcs2016_14a); tcase_add_test(tc_core, test_lcs2016_19); tcase_add_test(tc_core, test_lcs2016_07); + tcase_add_loop_test(tc_core, test_lcs2016_23, STD_08, STD_19 + 1); suite_add_tcase(s, tc_core); return s; diff --git a/www/features.html.in b/www/features.html.in index 9ee3a8036..7b8bda56c 100644 --- a/www/features.html.in +++ b/www/features.html.in @@ -250,7 +250,7 @@ table below. LCS2016-023 Relax library requirement on configurations - + master