diff --git a/src/V3Width.cpp b/src/V3Width.cpp index ba22aa1cd..a9bff2d59 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -7329,21 +7329,26 @@ class WidthVisitor final : public VNVisitor { } return false; } - void checkClassAssign(AstNode* nodep, const char* side, AstNode* rhsp, + void checkClassAssign(const AstNode* nodep, const char* side, AstNode* rhsp, AstNodeDType* const lhsDTypep) { - if (AstClassRefDType* const lhsClassRefp = VN_CAST(lhsDTypep->skipRefp(), ClassRefDType)) { - UASSERT_OBJ(rhsp->dtypep(), rhsp, "Node has no type"); - AstNodeDType* const rhsDtypep = rhsp->dtypep()->skipRefp(); - if (AstClassRefDType* const rhsClassRefp = VN_CAST(rhsDtypep, ClassRefDType)) { + UASSERT_OBJ(rhsp->dtypep(), rhsp, "Node has no type"); + const AstNodeDType* const lhsRawDTypep = lhsDTypep->skipRefp(); + const AstNodeDType* const rhsRawDTypep = rhsp->dtypep()->skipRefp(); + if (const AstClassRefDType* const lhsClassRefp = VN_CAST(lhsRawDTypep, ClassRefDType)) { + if (const AstClassRefDType* const rhsClassRefp + = VN_CAST(rhsRawDTypep, ClassRefDType)) { if (isBaseClassRecurse(lhsClassRefp->classp(), rhsClassRefp->classp())) return; } else if (rhsp->isNull()) { return; } nodep->v3error(side << " expects a " << lhsClassRefp->prettyTypeName() << ", got " - << rhsDtypep->prettyTypeName()); + << rhsRawDTypep->prettyTypeName()); + } else if (VN_IS(rhsRawDTypep, ClassRefDType)) { + nodep->v3error(side << " " << rhsRawDTypep->prettyDTypeNameQ() + << " cannot be assigned to non-class " + << lhsDTypep->prettyDTypeNameQ()); } - if (VN_IS(lhsDTypep->skipRefp(), DynArrayDType) - && VN_IS(rhsp->dtypep()->skipRefp(), UnpackArrayDType)) { + if (VN_IS(lhsRawDTypep, DynArrayDType) && VN_IS(rhsRawDTypep, UnpackArrayDType)) { VNRelinker relinker; rhsp->unlinkFrBack(&relinker); relinker.relink( diff --git a/test_regress/t/t_class_to_basic_assignment_bad.out b/test_regress/t/t_class_to_basic_assignment_bad.out new file mode 100755 index 000000000..a1b195381 --- /dev/null +++ b/test_regress/t/t_class_to_basic_assignment_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_class_to_basic_assignment_bad.v:26:29: Assign RHS 'class{}Foo' cannot be assigned to non-class 'int' + 26 | new_node.phase_done = get(); + | ^ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: Exiting due to diff --git a/test_regress/t/t_class_to_basic_assignment_bad.py b/test_regress/t/t_class_to_basic_assignment_bad.py new file mode 100755 index 000000000..55203b6c9 --- /dev/null +++ b/test_regress/t/t_class_to_basic_assignment_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_class_to_basic_assignment_bad.v b/test_regress/t/t_class_to_basic_assignment_bad.v new file mode 100644 index 000000000..e0f020cce --- /dev/null +++ b/test_regress/t/t_class_to_basic_assignment_bad.v @@ -0,0 +1,32 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +class Foo; + int phase_done; + + static function Foo get(); + Foo ans = new; + return ans; + endfunction + + static function int create (); + return 3; + endfunction + + function string get_name (); + return "bar"; + endfunction + + function void add(Foo phase); + Foo new_node; + if (new_node.get_name() == "run") begin + new_node.phase_done = get(); + end + else begin + new_node.phase_done = create(); + end + endfunction +endclass diff --git a/test_regress/t/t_process_copy_constr.v b/test_regress/t/t_process_copy_constr.v index 13f57775e..3bbadf5c2 100644 --- a/test_regress/t/t_process_copy_constr.v +++ b/test_regress/t/t_process_copy_constr.v @@ -7,7 +7,7 @@ class Cls; int x = 1; function new(); - int p = process::self(); + process p = process::self(); endfunction endclass