Fix error when calling non-static method (#6916)

This commit is contained in:
Artur Bieniek 2026-01-14 14:40:57 +01:00 committed by GitHub
parent 09ca7ea8d1
commit 4563501192
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 13 deletions

View File

@ -237,6 +237,8 @@ class WidthVisitor final : public VNVisitor {
TableMap m_tableMap; // Created tables so can remove duplicates
std::map<const AstNodeDType*, AstQueueDType*>
m_queueDTypeIndexed; // Queues with given index type
std::map<const AstNode*, const AstClass*>
m_containingClassp; // Containing class cache for containingClass() function
std::unordered_set<AstVar*> m_aliasedVars; // Variables referenced in alias
static constexpr int ENUM_LOOKUP_BITS = 16; // Maximum # bits to make enum lookup table
@ -6582,6 +6584,22 @@ class WidthVisitor final : public VNVisitor {
}
return VN_CAST(pkgItemp->backp(), Package);
}
const AstClass* containingClass(AstNode* nodep) {
// backp is still needed, m_containingClassp is just a cache
if (const AstClass* const classp = VN_CAST(nodep, Class))
return m_containingClassp[nodep] = classp;
if (const AstClassPackage* const packagep = VN_CAST(nodep, ClassPackage)) {
return m_containingClassp[nodep] = packagep->classp();
}
if (m_containingClassp.find(nodep) != m_containingClassp.end()) {
return m_containingClassp[nodep];
}
if (nodep->backp()) {
return m_containingClassp[nodep] = containingClass(nodep->backp());
} else {
return m_containingClassp[nodep] = nullptr;
}
}
void visit(AstFuncRef* nodep) override {
visit(static_cast<AstNodeFTaskRef*>(nodep));
if (nodep->taskp() && VN_IS(nodep->taskp(), Task)) {
@ -6889,10 +6907,26 @@ class WidthVisitor final : public VNVisitor {
return;
}
if ((nodep->taskp()->classMethod() && !nodep->taskp()->isStatic())
&& !VN_IS(m_procedurep, InitialAutomatic)
&& (!m_ftaskp || !m_ftaskp->classMethod() || m_ftaskp->isStatic()) && !m_constraintp) {
nodep->v3error("Cannot call non-static member function "
<< nodep->prettyNameQ() << " without object (IEEE 1800-2023 8.10)");
&& !VN_IS(m_procedurep, InitialAutomatic) && !m_constraintp) {
bool allow = false;
if (m_ftaskp && m_ftaskp->classMethod() && !m_ftaskp->isStatic()) {
if (const AstFuncRef* const funcRefp = VN_CAST(nodep, FuncRef)) {
allow = funcRefp->superReference();
} else if (const AstTaskRef* const taskRefp = VN_CAST(nodep, TaskRef)) {
allow = taskRefp->superReference();
}
if (!allow) {
const AstClass* callerClassp = containingClass(m_ftaskp);
if (!callerClassp) callerClassp = containingClass(m_ftaskp->classOrPackagep());
const AstClass* calleeClassp = VN_CAST(nodep->classOrPackagep(), Class);
if (!calleeClassp) calleeClassp = containingClass(nodep->taskp());
allow = AstClass::isClassExtendedFrom(callerClassp, calleeClassp);
}
}
if (!allow) {
nodep->v3error("Cannot call non-static member function "
<< nodep->prettyNameQ() << " without object (IEEE 1800-2023 8.10)");
}
}
if (nodep->taskp() && !nodep->scopeNamep()
&& (nodep->taskp()->dpiContext() || nodep->taskp()->dpiExport())) {

View File

@ -1,14 +1,22 @@
%Error: t/t_class_misstatic_bad.v:31:5: Cannot call non-static member function 'nonstatic' without object (IEEE 1800-2023 8.10)
: ... note: In instance 't'
31 | nonstatic();
| ^~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_class_misstatic_bad.v:38:10: Cannot call non-static member function 'nonstatic' without object (IEEE 1800-2023 8.10)
%Error: t/t_class_misstatic_bad.v:23:10: Cannot call non-static member function 'nonstatic' without object (IEEE 1800-2023 8.10)
: ... note: In instance 't'
38 | Cls::nonstatic();
23 | Cls::nonstatic();
| ^~~~~~~~~
%Error: t/t_class_misstatic_bad.v:44:10: Cannot call non-static member function 'nonstatic' without object (IEEE 1800-2023 8.10)
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_class_misstatic_bad.v:24:10: Cannot call non-static member function 'nonstatic_retcls' without object (IEEE 1800-2023 8.10)
: ... note: In instance 't'
44 | Cls::nonstatic();
24 | Cls::nonstatic_retcls();
| ^~~~~~~~~~~~~~~~
%Error: t/t_class_misstatic_bad.v:35:5: Cannot call non-static member function 'nonstatic' without object (IEEE 1800-2023 8.10)
: ... note: In instance 't'
35 | nonstatic();
| ^~~~~~~~~
%Error: t/t_class_misstatic_bad.v:45:10: Cannot call non-static member function 'nonstatic' without object (IEEE 1800-2023 8.10)
: ... note: In instance 't'
45 | Cls::nonstatic();
| ^~~~~~~~~
%Error: t/t_class_misstatic_bad.v:51:10: Cannot call non-static member function 'nonstatic' without object (IEEE 1800-2023 8.10)
: ... note: In instance 't'
51 | Cls::nonstatic();
| ^~~~~~~~~
%Error: Exiting due to

View File

@ -11,6 +11,9 @@ class Cls;
endfunction
function void nonstatic();
endfunction
function Cls nonstatic_retcls();
return null;
endfunction
static function void isst();
endfunction
endclass
@ -18,6 +21,7 @@ endclass
class Bar;
function void bar();
Cls::nonstatic(); // <--- bad static ref
Cls::nonstatic_retcls(); // <--- bad static ref
Cls::isst();
endfunction
endclass
@ -31,6 +35,9 @@ class Extends extends Cls;
nonstatic(); // <--- bad static ref
isst();
endfunction
function new();
Cls c = super.nonstatic_retcls();
endfunction
endclass
module t;