Remove error on missing forward declarations of typedef in class (#6207).

This commit is contained in:
Wilson Snyder 2025-07-30 09:14:13 -04:00
parent 9d2adf3e49
commit 9d38e63269
7 changed files with 55 additions and 4 deletions

View File

@ -1833,6 +1833,7 @@ class AstTypedef final : public AstNode {
bool m_attrPublic = false; bool m_attrPublic = false;
bool m_isHideLocal : 1; // Verilog local bool m_isHideLocal : 1; // Verilog local
bool m_isHideProtected : 1; // Verilog protected bool m_isHideProtected : 1; // Verilog protected
bool m_isUnderClass : 1; // Underneath class
public: public:
AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType,
@ -1841,7 +1842,8 @@ public:
, m_name{name} , m_name{name}
, m_declTokenNum{fl->tokenNum()} , m_declTokenNum{fl->tokenNum()}
, m_isHideLocal{false} , m_isHideLocal{false}
, m_isHideProtected{false} { , m_isHideProtected{false}
, m_isUnderClass{false} {
childDTypep(dtp); // Only for parser childDTypep(dtp); // Only for parser
addAttrsp(attrsp); addAttrsp(attrsp);
dtypep(nullptr); // V3Width will resolve dtypep(nullptr); // V3Width will resolve
@ -1868,6 +1870,8 @@ public:
void isHideLocal(bool flag) { m_isHideLocal = flag; } void isHideLocal(bool flag) { m_isHideLocal = flag; }
bool isHideProtected() const { return m_isHideProtected; } bool isHideProtected() const { return m_isHideProtected; }
void isHideProtected(bool flag) { m_isHideProtected = flag; } void isHideProtected(bool flag) { m_isHideProtected = flag; }
bool isUnderClass() const { return m_isUnderClass; }
void isUnderClass(bool flag) { m_isUnderClass = flag; }
void tag(const string& text) override { m_tag = text; } void tag(const string& text) override { m_tag = text; }
string tag() const override { return m_tag; } string tag() const override { return m_tag; }
}; };

View File

@ -2169,6 +2169,7 @@ void AstTimeImport::dumpJson(std::ostream& str) const {
void AstTypedef::dump(std::ostream& str) const { void AstTypedef::dump(std::ostream& str) const {
this->AstNode::dump(str); this->AstNode::dump(str);
if (attrPublic()) str << " [PUBLIC]"; if (attrPublic()) str << " [PUBLIC]";
if (isUnderClass()) str << " [UNDCLS]";
if (subDTypep()) { if (subDTypep()) {
str << " -> "; str << " -> ";
subDTypep()->dump(str); subDTypep()->dump(str);
@ -2177,6 +2178,7 @@ void AstTypedef::dump(std::ostream& str) const {
void AstTypedef::dumpJson(std::ostream& str) const { void AstTypedef::dumpJson(std::ostream& str) const {
// dumpJsonNumFunc(str, declTokenNum); // Not dumped as adding token changes whole file // dumpJsonNumFunc(str, declTokenNum); // Not dumped as adding token changes whole file
dumpJsonBoolFunc(str, attrPublic); dumpJsonBoolFunc(str, attrPublic);
dumpJsonBoolFunc(str, isUnderClass);
dumpJsonGen(str); dumpJsonGen(str);
} }
void AstTypedefFwd::dump(std::ostream& str) const { void AstTypedefFwd::dump(std::ostream& str) const {

View File

@ -1564,6 +1564,7 @@ class LinkDotFindVisitor final : public VNVisitor {
} }
void visit(AstTypedef* nodep) override { // FindVisitor:: void visit(AstTypedef* nodep) override { // FindVisitor::
UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit");
if (VN_IS(m_classOrPackagep, Class)) nodep->isUnderClass(true);
iterateChildren(nodep); iterateChildren(nodep);
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep);
} }
@ -4580,7 +4581,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (AstTypedef* const defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : nullptr) { if (AstTypedef* const defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : nullptr) {
// Don't check if typedef is to a <type T>::<reference> as might not be resolved // Don't check if typedef is to a <type T>::<reference> as might not be resolved
// yet // yet
if (!nodep->classOrPackagep()) checkDeclOrder(nodep, defp); if (!nodep->classOrPackagep() && !defp->isUnderClass())
checkDeclOrder(nodep, defp);
nodep->typedefp(defp); nodep->typedefp(defp);
nodep->classOrPackagep(foundp->classOrPackagep()); nodep->classOrPackagep(foundp->classOrPackagep());
} else if (AstParamTypeDType* const defp } else if (AstParamTypeDType* const defp

View File

@ -865,7 +865,7 @@
],"extendsp": []}, ],"extendsp": []},
{"type":"CLASS","name":"process","addr":"(SN)","loc":"d,124:4,124:9","isExtended":false,"isInterfaceClass":false,"isVirtual":false,"origName":"process","level":5,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"NONE","classOrPackagep":"UNLINKED","inlinesp": [], {"type":"CLASS","name":"process","addr":"(SN)","loc":"d,124:4,124:9","isExtended":false,"isInterfaceClass":false,"isVirtual":false,"origName":"process","level":5,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"NONE","classOrPackagep":"UNLINKED","inlinesp": [],
"stmtsp": [ "stmtsp": [
{"type":"TYPEDEF","name":"state","addr":"(TN)","loc":"d,131:9,131:14","dtypep":"UNLINKED","attrPublic":false, {"type":"TYPEDEF","name":"state","addr":"(TN)","loc":"d,131:9,131:14","dtypep":"UNLINKED","attrPublic":false,"isUnderClass":false,
"childDTypep": [ "childDTypep": [
{"type":"DEFIMPLICITDTYPE","name":"__typeimpenum0","addr":"(UN)","loc":"d,125:15,125:19","dtypep":"UNLINKED","generic":false, {"type":"DEFIMPLICITDTYPE","name":"__typeimpenum0","addr":"(UN)","loc":"d,125:15,125:19","dtypep":"UNLINKED","generic":false,
"childDTypep": [ "childDTypep": [

View File

@ -5,7 +5,7 @@
{"type":"VAR","name":"clk_ip","addr":"(F)","loc":"d,14:11,14:17","dtypep":"(G)","origName":"clk_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"clk_ip","addr":"(F)","loc":"d,14:11,14:17","dtypep":"(G)","origName":"clk_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"rst_ip","addr":"(H)","loc":"d,15:11,15:17","dtypep":"(G)","origName":"rst_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"rst_ip","addr":"(H)","loc":"d,15:11,15:17","dtypep":"(G)","origName":"rst_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"foo_op","addr":"(I)","loc":"d,16:11,16:17","dtypep":"(G)","origName":"foo_op","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"foo_op","addr":"(I)","loc":"d,16:11,16:17","dtypep":"(G)","origName":"foo_op","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"TYPEDEF","name":"my_struct","addr":"(J)","loc":"d,25:6,25:15","dtypep":"(K)","attrPublic":false,"childDTypep": [],"attrsp": []}, {"type":"TYPEDEF","name":"my_struct","addr":"(J)","loc":"d,25:6,25:15","dtypep":"(K)","attrPublic":false,"isUnderClass":false,"childDTypep": [],"attrsp": []},
{"type":"CELL","name":"itop","addr":"(L)","loc":"d,29:8,29:12","origName":"itop","recursive":false,"modp":"(M)","pinsp": [],"paramsp": [],"rangep": [],"intfRefsp": []}, {"type":"CELL","name":"itop","addr":"(L)","loc":"d,29:8,29:12","origName":"itop","recursive":false,"modp":"(M)","pinsp": [],"paramsp": [],"rangep": [],"intfRefsp": []},
{"type":"VAR","name":"itop","addr":"(N)","loc":"d,29:8,29:12","dtypep":"(O)","origName":"itop__Viftop","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"IFACEREF","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"itop","addr":"(N)","loc":"d,29:8,29:12","dtypep":"(O)","origName":"itop__Viftop","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"IFACEREF","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"this_struct","addr":"(P)","loc":"d,31:14,31:25","dtypep":"(Q)","origName":"this_struct","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"VAR","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"this_struct","addr":"(P)","loc":"d,31:14,31:25","dtypep":"(Q)","origName":"this_struct","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"VAR","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,25 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
typedef logic [3:0] T;
class Cls;
extern static function int f(T x);
// This is after the usage above, but to match other simulators,
// no error about use after declaration
typedef logic [7:0] T;
endclass
function int Cls::f(T x);
return $bits(x);
endfunction
module t;
initial begin
if (Cls::f('1) != 8) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule