mirror of
https://github.com/verilator/verilator.git
synced 2024-12-29 10:47:34 +00:00
Internals: Defer class extends
resolution until link
This commit is contained in:
parent
b71d49e55a
commit
15d1751b23
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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*/);
|
||||
|
Loading…
Reference in New Issue
Block a user