Change type definition error to show type chain with source context (#7151)
This commit is contained in:
parent
8d34bc786a
commit
d658517715
|
|
@ -941,12 +941,21 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
|||
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
||||
bool assertOn) const VL_MT_STABLE {
|
||||
static constexpr int MAX_TYPEDEF_DEPTH = 1000;
|
||||
static constexpr int MAX_CHAIN_DISPLAY = 10;
|
||||
const AstNodeDType* nodep = this;
|
||||
std::unordered_set<const AstNodeDType*> visited;
|
||||
std::vector<const AstNodeDType*> chain;
|
||||
bool isCycle = false;
|
||||
for (int depth = 0; depth < MAX_TYPEDEF_DEPTH; ++depth) {
|
||||
if (VN_IS(nodep, MemberDType) || VN_IS(nodep, ParamTypeDType) || VN_IS(nodep, RefDType) //
|
||||
|| VN_IS(nodep, RequireDType) //
|
||||
|| (VN_IS(nodep, ConstDType) && skipConst) //
|
||||
|| (VN_IS(nodep, EnumDType) && skipEnum)) {
|
||||
if (!visited.emplace(nodep).second) {
|
||||
isCycle = true;
|
||||
break;
|
||||
}
|
||||
if (chain.size() < static_cast<size_t>(MAX_CHAIN_DISPLAY)) chain.push_back(nodep);
|
||||
if (const AstNodeDType* subp = nodep->subDTypep()) {
|
||||
nodep = subp;
|
||||
continue;
|
||||
|
|
@ -957,7 +966,33 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
|||
}
|
||||
return nodep;
|
||||
}
|
||||
nodep->v3error("Recursive type definition, or over " << MAX_TYPEDEF_DEPTH << " types deep");
|
||||
// Build user-facing error with type chain
|
||||
V3Error::v3errorPrep(V3ErrorCode::EC_ERROR);
|
||||
{
|
||||
std::ostringstream& os = V3Error::v3errorStr();
|
||||
if (isCycle) {
|
||||
os << "Recursive type definition";
|
||||
} else {
|
||||
os << "Type definition over " << MAX_TYPEDEF_DEPTH << " types deep";
|
||||
}
|
||||
bool first = true;
|
||||
for (const AstNodeDType* chainp : chain) {
|
||||
// Skip internal scaffolding nodes (e.g. REQUIREDTYPE) with no user-visible name
|
||||
if (chainp->name().empty()) continue;
|
||||
os << '\n'
|
||||
<< chainp->fileline()->warnOther() << "... Type chain: " << chainp->prettyTypeName()
|
||||
<< '\n'
|
||||
<< (first ? chainp->fileline()->warnContextPrimary()
|
||||
: chainp->fileline()->warnContextSecondary());
|
||||
first = false;
|
||||
}
|
||||
if (visited.size() > static_cast<size_t>(MAX_CHAIN_DISPLAY)) {
|
||||
os << '\n'
|
||||
<< this->fileline()->warnMore() << "... and "
|
||||
<< (visited.size() - MAX_CHAIN_DISPLAY) << " more";
|
||||
}
|
||||
}
|
||||
this->v3errorEnd(V3Error::v3errorStr());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
%Error: t/t_recursive_typedef_bad.v:11:30: Recursive type definition
|
||||
: ... note: In instance 't.u_circ'
|
||||
t/t_recursive_typedef_bad.v:11:30: ... Type chain: PARAMTYPEDTYPE 'A'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
t/t_recursive_typedef_bad.v:11:34: ... Type chain: REFDTYPE 'B'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
t/t_recursive_typedef_bad.v:11:52: ... Type chain: PARAMTYPEDTYPE 'B'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
t/t_recursive_typedef_bad.v:11:56: ... Type chain: REFDTYPE 'A'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: t/t_recursive_typedef_bad.v:11:52: Recursive type definition
|
||||
: ... note: In instance 't.u_circ'
|
||||
t/t_recursive_typedef_bad.v:11:52: ... Type chain: PARAMTYPEDTYPE 'B'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
t/t_recursive_typedef_bad.v:11:56: ... Type chain: REFDTYPE 'A'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
t/t_recursive_typedef_bad.v:11:30: ... Type chain: PARAMTYPEDTYPE 'A'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
t/t_recursive_typedef_bad.v:11:34: ... Type chain: REFDTYPE 'B'
|
||||
11 | module circ #(parameter type A = B, parameter type B = A)
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
|
|
@ -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: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('linter')
|
||||
|
||||
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2025 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
//
|
||||
// Recursive type definition via circular parameter type defaults
|
||||
// should produce a clear error with type chain display.
|
||||
|
||||
// Circular: A defaults to B, B defaults to A
|
||||
module circ #(parameter type A = B, parameter type B = A)
|
||||
(input A ai, output B bo);
|
||||
assign bo = ai;
|
||||
endmodule
|
||||
|
||||
module t();
|
||||
logic [7:0] x, y;
|
||||
circ u_circ(.ai(x), .bo(y));
|
||||
initial begin
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
%Error: t/t_type_param_circ_bad.v:14:22: Recursive type definition, or over 1000 types deep
|
||||
%Error: t/t_type_param_circ_bad.v:14:22: Recursive type definition
|
||||
: ... note: In instance 't'
|
||||
t/t_type_param_circ_bad.v:14:22: ... Type chain: PARAMTYPEDTYPE 'SZ'
|
||||
14 | # (parameter type SZ = SZ)
|
||||
| ^~
|
||||
t/t_type_param_circ_bad.v:14:27: ... Type chain: REFDTYPE 'SZ'
|
||||
14 | # (parameter type SZ = SZ)
|
||||
| ^~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
Loading…
Reference in New Issue