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:
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 {
public:
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);
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) {
const auto pair = m_usedPins.emplace(refp, nodep);
if (!pair.second) {
@ -3812,6 +3835,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
if (AstClassOrPackageRef* lookNodep = VN_CAST(dotp->lhsp(), ClassOrPackageRef)) {
iterate(lookNodep);
cprp = dotp->rhsp();
VSymEnt* const foundp
= findClassOrPackage(lookSymp, lookNodep, false, nodep->verilogKwd());
if (!foundp) return;
UASSERT_OBJ(lookNodep->classOrPackagep(), nodep, "Bad package link");
lookSymp = m_statep->getNodeSym(lookNodep->classOrPackagep());
} else {
@ -3825,7 +3851,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
nodep->v3error("Attempting to extend using non-class"); // LCOV_EXCL_LINE
return;
}
VSymEnt* const foundp = lookSymp->findIdFallback(cpackagerefp->name());
VSymEnt* const foundp
= findClassOrPackage(lookSymp, cpackagerefp, true, nodep->verilogKwd());
if (foundp) {
if (AstClass* const classp = VN_CAST(foundp->nodep(), Class)) {
AstPin* paramsp = cpackagerefp->paramsp();
@ -3850,12 +3877,6 @@ class LinkDotResolveVisitor final : public VNVisitor {
return;
}
} 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;
}
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
/*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentClassE
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, $<scp>1, $3};
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3};
$<scp>$ = $<scp>1; }
| idCC
/*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentClassE
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, $<scp>1, $3};
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3};
$<scp>$ = $<scp>1; }
//
// // 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'
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

View File

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