diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 89abc2c2a..ebe022bd2 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2195,7 +2195,8 @@ private: if (AstNode* interfaceSubp = it->second->nodep()) { UINFO(8, " SymFunc " << interfaceSubp << endl); if (VN_IS(interfaceSubp, NodeFTask)) { - bool existsInChild = m_curSymp->findIdFlat(interfaceSubp->name()); + const VSymEnt* const foundp = m_curSymp->findIdFlat(interfaceSubp->name()); + bool existsInChild = foundp && !foundp->imported(); if (!existsInChild && !implementsClassp->isInterfaceClass()) { implementsClassp->v3error( "Class " << implementsClassp->prettyNameQ() << " implements " @@ -2207,8 +2208,7 @@ private: << "... Location of interface class's function\n" << interfaceSubp->warnContextSecondary()); } - if (m_ifClassImpNames.find(interfaceSubp->name()) != m_ifClassImpNames.end() - && !existsInChild) { + if (!existsInChild && m_ifClassImpNames.find(interfaceSubp->name()) != m_ifClassImpNames.end()) { implementsClassp->v3error( "Class " << implementsClassp->prettyNameQ() << " implements " << interfaceClassp->prettyNameQ() @@ -3332,7 +3332,8 @@ private: VSymEnt* const srcp = m_statep->getNodeSym(classp); if (classp->isInterfaceClass()) { importImplementsClass(nodep, srcp, classp); - } else { + } + if (!cextp->isImplements()) { m_curSymp->importFromClass(m_statep->symsp(), srcp); } VL_DO_DANGLING(cpackagerefp->unlinkFrBack()->deleteTree(), diff --git a/test_regress/t/t_implements_collision_bad.out b/test_regress/t/t_implements_collision_bad.out index 09e7a792a..80fecac8e 100644 --- a/test_regress/t/t_implements_collision_bad.out +++ b/test_regress/t/t_implements_collision_bad.out @@ -4,4 +4,10 @@ t/t_implements_collision_bad.v:12:30: ... Location of interface class's function 12 | pure virtual function int icfboth; | ^~~~~~~ +%Error: t/t_implements_collision_bad.v:19:1: Class 'Cls' implements 'IclsBoth' but is missing implementation for 'icfboth' (IEEE 1800-2017 8.26) + 19 | class Cls implements IclsBoth; + | ^~~~~ + t/t_implements_collision_bad.v:8:30: ... Location of interface class's function + 8 | pure virtual function int icfboth; + | ^~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_implements_typed.pl b/test_regress/t/t_implements_typed.pl new file mode 100755 index 000000000..da2e37bda --- /dev/null +++ b/test_regress/t/t_implements_typed.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +ok(1); +1; diff --git a/test_regress/t/t_implements_typed.v b/test_regress/t/t_implements_typed.v new file mode 100644 index 000000000..128e3c7cd --- /dev/null +++ b/test_regress/t/t_implements_typed.v @@ -0,0 +1,41 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icls; + typedef int int_t; + pure virtual function int ifunc(int_t val); +endclass + +interface class IclsExt extends Icls; + // Typedefs seen by extended, but not implements (need ::) + pure virtual function int ifuncExt(int_t v1, int_t v2); +endclass + +class IclsImp implements Icls; + function int ifunc(Icls::int_t val); + return val + 1; + endfunction +endclass + +// Bad, already have error for +// class IclsImp2 implements Icls; +// function int ifunc(int_t val); // Bad int_t not typedefed +// endfunction +// endclass + +module t(/*AUTOARG*/); + + IclsImp i1; + + initial begin + i1 = new; + if (i1.ifunc(2) != 3) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule