From c6fc5d774cf5f7dd4f01d010d38d91ae18fad816 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Fri, 11 Nov 2022 22:13:04 +0000 Subject: [PATCH] Fix wrong overload selection with condition conversion. Issue #570 --- src/names.c | 30 ++++++++++++++++++++++++++++++ test/regress/issue570.vhd | 36 ++++++++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + 3 files changed, 67 insertions(+) create mode 100644 test/regress/issue570.vhd diff --git a/src/names.c b/src/names.c index c593eab6..5c405c00 100644 --- a/src/names.c +++ b/src/names.c @@ -151,6 +151,7 @@ typedef A(tracked_type_t) tracked_type_list_t; struct type_set { tracked_type_list_t members; type_set_t *down; + bool cconv; }; static type_t _solve_types(nametab_t *tab, tree_t expr); @@ -2218,6 +2219,33 @@ static tree_t finish_overload_resolution(overload_t *o) overload_trace_candidates(o, "before final pruning"); + // If this call appears in a context that allows condition + // conversion, and there are multiple candidates at least one of + // which returns BOOLEAN, then prune the others that were only + // considered due to condition conversion. + if (o->candidates.count > 1 && o->nametab->top_type_set->cconv) { + type_t boolean = std_type(NULL, STD_BOOLEAN); + + int nboolean = 0; + for (unsigned i = 0; i < o->candidates.count; i++) { + type_t rtype = type_result(tree_type(o->candidates.items[i])); + if (type_eq(rtype, boolean)) + nboolean++; + } + + if (nboolean > 0) { + unsigned wptr = 0; + for (unsigned i = 0; i < o->candidates.count; i++) { + type_t rtype = type_result(tree_type(o->candidates.items[i])); + if (!type_eq(rtype, boolean)) + overload_prune_candidate(o, i); + else + o->candidates.items[wptr++] = o->candidates.items[i]; + } + ATRIM(o->candidates, wptr); + } + } + // Allow explicitly defined operators to hide implicitly defined ones // in different scopes. This is required behaviour in VHDL-2008 (see // section 12.4) and an optional rule relaxation in earlier revisions. @@ -3901,6 +3929,8 @@ type_t solve_condition(nametab_t *tab, tree_t *expr, type_t constraint) type_set_add(tab, p0_type, dd->tree); } } + + tab->top_type_set->cconv = true; } } diff --git a/test/regress/issue570.vhd b/test/regress/issue570.vhd new file mode 100644 index 00000000..143af6e0 --- /dev/null +++ b/test/regress/issue570.vhd @@ -0,0 +1,36 @@ +package pack is + function "=" (L: bit; R: bit) return bit; +end package; + +package body pack is + function "=" (L: bit; R: bit) return bit is + begin + if L = R then + return '1'; + else + return '0'; + end if; + end function; +end package body; + +------------------------------------------------------------------------------- + +use work.pack.all; + +entity issue570 is +end entity; + +architecture test of issue570 is + signal x : bit := '1'; +begin + + p1: process is + begin + assert (bit'( '1' ) = bit'( '1' )) = '1'; + if x = '0' then + assert false; + end if; + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index c4f961af..a4565814 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -688,3 +688,4 @@ case14 normal,2008 cmdline4 shell record38 fail,gold,2008 issue560 normal,2008 +issue570 normal,2008 -- 2.39.2