Internals: Defer class extends resolution until link

This commit is contained in:
Wilson Snyder 2024-11-10 19:34:00 -05:00
parent b71d49e55a
commit 15d1751b23
4 changed files with 45 additions and 12 deletions

View File

@ -84,6 +84,12 @@ class LinkNodeMatcherClass final : public VNodeMatcher {
public: public:
bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); } bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); }
}; };
class LinkNodeMatcherClassOrPackage final : public VNodeMatcher {
public:
bool nodeMatch(const AstNode* nodep) const override {
return VN_IS(nodep, Class) || VN_IS(nodep, Package);
}
};
class LinkNodeMatcherFTask final : public VNodeMatcher { class LinkNodeMatcherFTask final : public VNodeMatcher {
public: public:
bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); } bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); }
@ -2300,6 +2306,23 @@ class LinkDotResolveVisitor final : public VNVisitor {
UASSERT_OBJ(ifaceTopVarp, nodep, "Can't find interface var ref: " << findName); UASSERT_OBJ(ifaceTopVarp, nodep, "Can't find interface var ref: " << findName);
return ifaceTopVarp; return ifaceTopVarp;
} }
VSymEnt* findClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool classOnly,
const string& forWhat) {
if (nodep->classOrPackagep()) return m_statep->getNodeSym(nodep->classOrPackagep());
VSymEnt* const foundp = lookSymp->findIdFallback(nodep->name());
if (foundp) {
nodep->classOrPackageNodep(foundp->nodep());
return foundp;
} else {
const string suggest = m_statep->suggestSymFallback(lookSymp, nodep->name(),
LinkNodeMatcherClassOrPackage{});
nodep->v3error((classOnly ? "Class" : "Package/Class")
<< " for '" << forWhat // extends/implements
<< "' not found: " << nodep->prettyNameQ() << '\n'
<< (suggest.empty() ? "" : nodep->warnMore() + suggest));
return nullptr;
}
}
void markAndCheckPinDup(AstPin* nodep, AstNode* refp, const char* whatp) { void markAndCheckPinDup(AstPin* nodep, AstNode* refp, const char* whatp) {
const auto pair = m_usedPins.emplace(refp, nodep); const auto pair = m_usedPins.emplace(refp, nodep);
if (!pair.second) { if (!pair.second) {
@ -3812,6 +3835,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (AstClassOrPackageRef* lookNodep = VN_CAST(dotp->lhsp(), ClassOrPackageRef)) { if (AstClassOrPackageRef* lookNodep = VN_CAST(dotp->lhsp(), ClassOrPackageRef)) {
iterate(lookNodep); iterate(lookNodep);
cprp = dotp->rhsp(); cprp = dotp->rhsp();
VSymEnt* const foundp
= findClassOrPackage(lookSymp, lookNodep, false, nodep->verilogKwd());
if (!foundp) return;
UASSERT_OBJ(lookNodep->classOrPackagep(), nodep, "Bad package link"); UASSERT_OBJ(lookNodep->classOrPackagep(), nodep, "Bad package link");
lookSymp = m_statep->getNodeSym(lookNodep->classOrPackagep()); lookSymp = m_statep->getNodeSym(lookNodep->classOrPackagep());
} else { } else {
@ -3825,7 +3851,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
nodep->v3error("Attempting to extend using non-class"); // LCOV_EXCL_LINE nodep->v3error("Attempting to extend using non-class"); // LCOV_EXCL_LINE
return; return;
} }
VSymEnt* const foundp = lookSymp->findIdFallback(cpackagerefp->name()); VSymEnt* const foundp
= findClassOrPackage(lookSymp, cpackagerefp, true, nodep->verilogKwd());
if (foundp) { if (foundp) {
if (AstClass* const classp = VN_CAST(foundp->nodep(), Class)) { if (AstClass* const classp = VN_CAST(foundp->nodep(), Class)) {
AstPin* paramsp = cpackagerefp->paramsp(); AstPin* paramsp = cpackagerefp->paramsp();
@ -3850,12 +3877,6 @@ class LinkDotResolveVisitor final : public VNVisitor {
return; return;
} }
} else { } else {
const string suggest = m_statep->suggestSymFallback(
m_curSymp, cpackagerefp->name(), LinkNodeMatcherClass{});
cpackagerefp->v3error(
"Class for '" << nodep->verilogKwd() // extends/implements
<< "' not found: " << cpackagerefp->prettyNameQ() << '\n'
<< (suggest.empty() ? "" : cpackagerefp->warnMore() + suggest));
return; return;
} }
if (!nodep->childDTypep()) nodep->v3error("Attempting to extend using non-class"); if (!nodep->childDTypep()) nodep->v3error("Attempting to extend using non-class");

View File

@ -7227,12 +7227,12 @@ class_typeExtImpOne<nodeExprp>: // part of IEEE: class_type, where we either ge
idAny idAny
/*mid*/ { /* no nextId as not refing it above this*/ } /*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentClassE /*cont*/ parameter_value_assignmentClassE
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, $<scp>1, $3}; { $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3};
$<scp>$ = $<scp>1; } $<scp>$ = $<scp>1; }
| idCC | idCC
/*mid*/ { /* no nextId as not refing it above this*/ } /*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentClassE /*cont*/ parameter_value_assignmentClassE
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, $<scp>1, $3}; { $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3};
$<scp>$ = $<scp>1; } $<scp>$ = $<scp>1; }
// //
// // package_sopeIdFollows expanded // // package_sopeIdFollows expanded

View File

@ -1,5 +1,9 @@
%Error: t/t_class_extends_nf_bad.v:10:19: Class for 'extends' not found: 'IsNotFound' %Error: t/t_class_extends_nf_bad.v:15:19: Class for 'extends' not found: 'IsNotFound'
: ... Suggested alternative: 'IsFound' : ... Suggested alternative: 'IsFound'
10 | class Cls extends IsNotFound; 15 | class Cls extends IsNotFound;
| ^~~~~~~~~~ | ^~~~~~~~~~
%Error: t/t_class_extends_nf_bad.v:18:25: Class for 'extends' not found: 'NotFound2'
: ... Suggested alternative: 'otFound2'
18 | class Cls2 extends Pkg::NotFound2;
| ^~~~~~~~~
%Error: Exiting due to %Error: Exiting due to

View File

@ -4,10 +4,18 @@
// any use, without warranty, 2020 by Wilson Snyder. // any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
package Pkg;
class otFound2;
endclass
endpackage
class IsFound; class IsFound;
endclass endclass
class Cls extends IsNotFound; class Cls extends IsNotFound; // BAD: not found
endclass
class Cls2 extends Pkg::NotFound2; // BAD: not found
endclass endclass
module t (/*AUTOARG*/); module t (/*AUTOARG*/);