mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
@@ -3463,6 +3463,24 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
}
|
||||
defParamPins.emplace(nodep->paramPath(), nodep);
|
||||
}
|
||||
static bool extendsClass(const AstClass* classp, const AstClass* targetp) {
|
||||
// Return true if classp inherits from targetp through already resolved extends
|
||||
// If performance of this becomes a problem, use just a counter to check
|
||||
// exceeds some number of iterations then perform the more expensive analysis
|
||||
std::set<const AstClass*> visited;
|
||||
std::vector<const AstClass*> todo{classp};
|
||||
while (!todo.empty()) {
|
||||
const AstClass* const currp = todo.back();
|
||||
todo.pop_back();
|
||||
if (currp == targetp) return true;
|
||||
if (!visited.insert(currp).second) continue;
|
||||
for (const AstClassExtends* cextp = currp->extendsp(); cextp;
|
||||
cextp = VN_AS(cextp->nextp(), ClassExtends)) {
|
||||
if (const AstClass* const basep = cextp->classOrNullp()) todo.push_back(basep);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static AstClocking* sensClockingp(AstNode* nodep) {
|
||||
// Return the clocking block referenced by nodep, either directly or through a modport
|
||||
if (AstClocking* const clockingp = VN_CAST(nodep, Clocking)) return clockingp;
|
||||
@@ -5989,6 +6007,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
if (baseClassp == nodep) {
|
||||
cextp->v3error("Attempting to extend class " << nodep->prettyNameQ()
|
||||
<< " from itself");
|
||||
} else if (extendsClass(baseClassp, nodep)) {
|
||||
cextp->v3error("Attempting to extend class "
|
||||
<< nodep->prettyNameQ() << " from "
|
||||
<< baseClassp->prettyNameQ()
|
||||
<< ", which circularly inherits from it");
|
||||
} else if (cextp->isImplements() && !baseClassp->isInterfaceClass()) {
|
||||
cextp->v3error("Attempting to implement from non-interface class "
|
||||
<< baseClassp->prettyNameQ() << '\n'
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
%Error: t/t_class_extends_cycle_bad.v:10:21: Attempting to extend class 'Cls2B' from 'Cls2A', which circularly inherits from it
|
||||
10 | class Cls2B extends Cls2A;
|
||||
| ^~~~~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: t/t_class_extends_cycle_bad.v:8:21: Attempting to extend class 'Cls2A' from 'Cls2B', which circularly inherits from it
|
||||
8 | class Cls2A extends Cls2B;
|
||||
| ^~~~~
|
||||
%Error: t/t_class_extends_cycle_bad.v:16:21: Attempting to extend class 'Cls3B' from 'Cls3A', which circularly inherits from it
|
||||
16 | class Cls3B extends Cls3A;
|
||||
| ^~~~~
|
||||
%Error: t/t_class_extends_cycle_bad.v:18:21: Attempting to extend class 'Cls3C' from 'Cls3B', which circularly inherits from it
|
||||
18 | class Cls3C extends Cls3B;
|
||||
| ^~~~~
|
||||
%Error: t/t_class_extends_cycle_bad.v:14:21: Attempting to extend class 'Cls3A' from 'Cls3C', which circularly inherits from it
|
||||
14 | class Cls3A extends Cls3C;
|
||||
| ^~~~~
|
||||
%Error: t/t_class_extends_cycle_bad.v:24:30: Attempting to extend class 'IfcB' from 'IfcA', which circularly inherits from it
|
||||
24 | interface class IfcB extends IfcA;
|
||||
| ^~~~
|
||||
%Error: t/t_class_extends_cycle_bad.v:22:30: Attempting to extend class 'IfcA' from 'IfcB', which circularly inherits from it
|
||||
22 | interface class IfcA extends IfcB;
|
||||
| ^~~~
|
||||
%Error: Exiting due to
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# 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()
|
||||
@@ -0,0 +1,30 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Saqib Khan
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Two-class cycle
|
||||
class Cls2A extends Cls2B;
|
||||
endclass
|
||||
class Cls2B extends Cls2A;
|
||||
endclass
|
||||
|
||||
// Three-class cycle
|
||||
class Cls3A extends Cls3C;
|
||||
endclass
|
||||
class Cls3B extends Cls3A;
|
||||
endclass
|
||||
class Cls3C extends Cls3B;
|
||||
endclass
|
||||
|
||||
// Interface class cycle
|
||||
interface class IfcA extends IfcB;
|
||||
endclass
|
||||
interface class IfcB extends IfcA;
|
||||
endclass
|
||||
|
||||
module t;
|
||||
Cls2A c2 = new;
|
||||
Cls3B c3 = new;
|
||||
endmodule
|
||||
Reference in New Issue
Block a user