Support 1800-2023 class and function :initial, :extends, :final virtual overrides (#5025). (#5025)

This commit is contained in:
Wilson Snyder
2024-03-27 23:57:58 -04:00
committed by GitHub
parent 28b9216f8a
commit 1ed5557d2d
12 changed files with 566 additions and 16 deletions
+60 -5
View File
@@ -27,6 +27,8 @@
#include "V3WidthCommit.h"
#include "V3MemberMap.h"
VL_DEFINE_DEBUG_FUNCTIONS;
//######################################################################
@@ -40,6 +42,7 @@ class WidthCommitVisitor final : public VNVisitor {
// STATE
AstNodeModule* m_modp = nullptr;
VMemberMap m_memberMap; // Member names cached for fast lookup
public:
// METHODS
@@ -73,7 +76,7 @@ private:
return nodep;
}
void classEncapCheck(AstNode* nodep, AstNode* defp, AstClass* defClassp) {
// Call on non-local class to check local/protected status and complain
// Check local/protected status and complain
bool local = false;
bool prot = false;
if (const auto varp = VN_CAST(defp, Var)) {
@@ -110,10 +113,23 @@ private:
// VISITORS
void visit(AstNodeModule* nodep) override {
VL_RESTORER(m_modp);
{
m_modp = nodep;
iterateChildren(nodep);
editDType(nodep);
m_modp = nodep;
iterateChildren(nodep);
editDType(nodep);
if (AstClass* const classp = VN_CAST(nodep, Class)) {
for (AstClassExtends* extendsp = classp->extendsp(); extendsp;
extendsp = extendsp->classp()->extendsp()) {
const AstClass* const ebasep = extendsp->classp();
if (ebasep->baseOverride().isFinal()) {
extendsp->v3error("Class " << nodep->prettyNameQ()
<< " is being extended from class marked ':final'"
" (IEEE 1800-2023 8.20)\n"
<< extendsp->warnContextPrimary() << "\n"
<< ebasep->warnOther()
<< "... Location of ':final' class being extended\n"
<< ebasep->warnContextSecondary());
}
}
}
}
void visit(AstConst* nodep) override {
@@ -177,6 +193,45 @@ private:
nodep->v3error(
"Illegal to have 'pure virtual' in non-virtual class (IEEE 1800-2023 8.21)");
}
bool extended = false;
if (const AstClass* const classp = VN_CAST(m_modp, Class)) {
for (AstClassExtends* extendsp = classp->extendsp(); extendsp;
extendsp = extendsp->classp()->extendsp()) {
const AstClass* const eclassp = extendsp->classp();
if (AstNodeFTask* const fbasep
= VN_CAST(m_memberMap.findMember(eclassp, nodep->name()), NodeFTask)) {
if (fbasep != nodep) {
extended = true;
if (nodep->baseOverride().isInitial()) {
nodep->v3error("Member "
<< nodep->prettyNameQ()
<< " is marked ':initial' but is being extended"
" (IEEE 1800-2023 8.20)\n"
<< nodep->warnContextPrimary() << "\n"
<< fbasep->warnOther()
<< "... Location of declaration being extended\n"
<< fbasep->warnContextSecondary());
}
if (fbasep->baseOverride().isFinal()) {
nodep->v3error(
"Member "
<< nodep->prettyNameQ()
<< " is being extended from member marked ':final'"
" (IEEE 1800-2023 8.20)\n"
<< nodep->warnContextPrimary() << "\n"
<< fbasep->warnOther()
<< "... Location of ':final' declaration being extended\n"
<< fbasep->warnContextSecondary());
}
}
}
}
}
if (!extended && nodep->baseOverride().isExtends()) {
nodep->v3error("Member " << nodep->prettyNameQ()
<< " marked ':extends' but no base class function is"
" being extend (IEEE 1800-2023 8.20)");
}
}
void visit(AstNodeVarRef* nodep) override {
iterateChildren(nodep);