diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 726b209a4..f805c2b2a 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6249,12 +6249,23 @@ private: } return false; // No change } - + bool isBaseClassRecurse(const AstClass* const cls1p, const AstClass* const cls2p) { + // Returns true if cls1p and cls2p are equal or if cls1p is a base class of cls2p + if (cls1p == cls2p) return true; + for (const AstClassExtends* cextp = cls2p->extendsp(); cextp; + cextp = VN_CAST(cextp->nextp(), ClassExtends)) { + if (isBaseClassRecurse(cls1p, cextp->classp())) return true; + } + return false; + } void checkClassAssign(AstNode* nodep, const char* side, AstNode* rhsp, AstNodeDType* lhsDTypep) { - if (VN_IS(lhsDTypep, ClassRefDType) - && !(rhsp->dtypep() && VN_IS(rhsp->dtypep()->skipRefp(), ClassRefDType))) { - if (auto* const constp = VN_CAST(rhsp, Const)) { + if (AstClassRefDType* const lhsClassRefp = VN_CAST(lhsDTypep, ClassRefDType)) { + UASSERT_OBJ(rhsp->dtypep(), rhsp, "Node has no type"); + if (AstClassRefDType* const rhsClassRefp + = VN_CAST(rhsp->dtypep()->skipRefp(), ClassRefDType)) { + if (isBaseClassRecurse(lhsClassRefp->classp(), rhsClassRefp->classp())) return; + } else if (auto* const constp = VN_CAST(rhsp, Const)) { if (constp->num().isNull()) return; } nodep->v3error(side << " expects a " << lhsDTypep->prettyTypeName()); diff --git a/test_regress/t/t_class_assign_bad.out b/test_regress/t/t_class_assign_bad.out index f93dffe76..6c909e986 100644 --- a/test_regress/t/t_class_assign_bad.out +++ b/test_regress/t/t_class_assign_bad.out @@ -1,17 +1,33 @@ -%Error: t/t_class_assign_bad.v:16:9: Assign RHS expects a CLASSREFDTYPE 'Cls' +%Error: t/t_class_assign_bad.v:25:9: Assign RHS expects a CLASSREFDTYPE 'Cls' : ... In instance t - 16 | c = 0; + 25 | c = 0; | ^ -%Error: t/t_class_assign_bad.v:17:9: Assign RHS expects a CLASSREFDTYPE 'Cls' +%Error: t/t_class_assign_bad.v:26:9: Assign RHS expects a CLASSREFDTYPE 'Cls' : ... In instance t - 17 | c = 1; + 26 | c = 1; | ^ -%Error: t/t_class_assign_bad.v:18:7: Function Argument expects a CLASSREFDTYPE 'Cls' +%Error: t/t_class_assign_bad.v:27:9: Assign RHS expects a CLASSREFDTYPE 'Cls' : ... In instance t - 18 | t(0); + 27 | c = c2; + | ^ +%Error: t/t_class_assign_bad.v:28:13: Assign RHS expects a CLASSREFDTYPE 'ClsExt' + : ... In instance t + 28 | c_ext = c; + | ^ +%Error: t/t_class_assign_bad.v:30:7: Function Argument expects a CLASSREFDTYPE 'Cls' + : ... In instance t + 30 | t(0); | ^ -%Error: t/t_class_assign_bad.v:19:7: Function Argument expects a CLASSREFDTYPE 'Cls' +%Error: t/t_class_assign_bad.v:31:7: Function Argument expects a CLASSREFDTYPE 'Cls' : ... In instance t - 19 | t(1); + 31 | t(1); + | ^ +%Error: t/t_class_assign_bad.v:32:7: Function Argument expects a CLASSREFDTYPE 'Cls' + : ... In instance t + 32 | t(c2); + | ^ +%Error: t/t_class_assign_bad.v:33:7: Function Argument expects a CLASSREFDTYPE 'ClsExt' + : ... In instance t + 33 | f(c); | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_assign_bad.v b/test_regress/t/t_class_assign_bad.v index 97b7b9f46..46045ee5c 100644 --- a/test_regress/t/t_class_assign_bad.v +++ b/test_regress/t/t_class_assign_bad.v @@ -7,15 +7,29 @@ class Cls; endclass : Cls +class Cls2; +endclass + +class ClsExt extends Cls; +endclass + module t (/*AUTOARG*/); Cls c; + Cls2 c2; + ClsExt c_ext; task t(Cls c); endtask + function f(ClsExt c); endfunction initial begin c = 0; c = 1; + c = c2; + c_ext = c; + t(0); t(1); + t(c2); + f(c); end endmodule diff --git a/test_regress/t/t_class_new_bad.out b/test_regress/t/t_class_new_bad.out index 425a7898e..454eae5d6 100644 --- a/test_regress/t/t_class_new_bad.out +++ b/test_regress/t/t_class_new_bad.out @@ -14,11 +14,7 @@ : ... In instance t 34 | c1 = new[2]; | ^~~ -%Error: t/t_class_new_bad.v:34:10: Assign RHS expects a CLASSREFDTYPE 'ClsNoArg' - : ... In instance t - 34 | c1 = new[2]; - | ^ -%Error: Internal Error: t/t_class_new_bad.v:34:10: ../V3Width.cpp:#: Node has no type +%Error: Internal Error: t/t_class_new_bad.v:34:12: ../V3Width.cpp:#: Node has no type : ... In instance t 34 | c1 = new[2]; - | ^ + | ^~~