Add warning on missing class reference #()
This commit is contained in:
parent
ab502c5196
commit
e21198cb2d
|
|
@ -210,6 +210,7 @@ private:
|
||||||
bool m_modTrace : 1; // Tracing this module
|
bool m_modTrace : 1; // Tracing this module
|
||||||
bool m_inLibrary : 1; // From a library, no error if not used, never top level
|
bool m_inLibrary : 1; // From a library, no error if not used, never top level
|
||||||
bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors
|
bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors
|
||||||
|
bool m_hasGParam : 1; // Has global parameter (for link)
|
||||||
bool m_hierBlock : 1; // Hierarchical Block marked by HIER_BLOCK pragma
|
bool m_hierBlock : 1; // Hierarchical Block marked by HIER_BLOCK pragma
|
||||||
bool m_internal : 1; // Internally created
|
bool m_internal : 1; // Internally created
|
||||||
bool m_recursive : 1; // Recursive module
|
bool m_recursive : 1; // Recursive module
|
||||||
|
|
@ -223,6 +224,7 @@ protected:
|
||||||
, m_modTrace{false}
|
, m_modTrace{false}
|
||||||
, m_inLibrary{false}
|
, m_inLibrary{false}
|
||||||
, m_dead{false}
|
, m_dead{false}
|
||||||
|
, m_hasGParam{false}
|
||||||
, m_hierBlock{false}
|
, m_hierBlock{false}
|
||||||
, m_internal{false}
|
, m_internal{false}
|
||||||
, m_recursive{false}
|
, m_recursive{false}
|
||||||
|
|
@ -250,6 +252,8 @@ public:
|
||||||
bool modTrace() const { return m_modTrace; }
|
bool modTrace() const { return m_modTrace; }
|
||||||
void dead(bool flag) { m_dead = flag; }
|
void dead(bool flag) { m_dead = flag; }
|
||||||
bool dead() const { return m_dead; }
|
bool dead() const { return m_dead; }
|
||||||
|
void hasGParam(bool flag) { m_hasGParam = flag; }
|
||||||
|
bool hasGParam() const { return m_hasGParam; }
|
||||||
void hierBlock(bool flag) { m_hierBlock = flag; }
|
void hierBlock(bool flag) { m_hierBlock = flag; }
|
||||||
bool hierBlock() const { return m_hierBlock; }
|
bool hierBlock() const { return m_hierBlock; }
|
||||||
void internal(bool flag) { m_internal = flag; }
|
void internal(bool flag) { m_internal = flag; }
|
||||||
|
|
|
||||||
|
|
@ -2227,6 +2227,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITs
|
||||||
void visit(AstNetlist* nodep) override {
|
void visit(AstNetlist* nodep) override {
|
||||||
// Recurse..., backward as must do packages before using packages
|
// Recurse..., backward as must do packages before using packages
|
||||||
|
|
@ -2822,8 +2823,15 @@ private:
|
||||||
UINFO(4, "(Backto) Link ClassOrPackageRef: " << nodep << endl);
|
UINFO(4, "(Backto) Link ClassOrPackageRef: " << nodep << endl);
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
if (m_statep->forPrimary() && VN_IS(nodep->classOrPackagep(), Class) && !nodep->paramsp()
|
||||||
|
&& nodep->classOrPackagep()->hasGParam()
|
||||||
|
// Don't warn on typedefs, which are hard to know if there's a param somewhere buried
|
||||||
|
&& VN_IS(nodep->classOrPackageNodep(), Class)) {
|
||||||
|
nodep->v3error("Reference to parameterized class without #() (IEEE 1800-2017 8.25.1)\n"
|
||||||
|
<< nodep->warnMore() << "... Suggest use '"
|
||||||
|
<< nodep->classOrPackageNodep()->prettyName() << "#()'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(AstVarRef* nodep) override {
|
void visit(AstVarRef* nodep) override {
|
||||||
// VarRef: Resolve its reference
|
// VarRef: Resolve its reference
|
||||||
// ParseRefs are used the first pass (forPrimary) so we shouldn't get can't find
|
// ParseRefs are used the first pass (forPrimary) so we shouldn't get can't find
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,7 @@ private:
|
||||||
if (nodep->lifetime().isNone() && nodep->varType() != VVarType::PORT) {
|
if (nodep->lifetime().isNone() && nodep->varType() != VVarType::PORT) {
|
||||||
nodep->lifetime(m_lifetime);
|
nodep->lifetime(m_lifetime);
|
||||||
}
|
}
|
||||||
|
if (nodep->isGParam() && m_modp) m_modp->hasGParam(true);
|
||||||
if (nodep->isParam() && !nodep->valuep()
|
if (nodep->isParam() && !nodep->valuep()
|
||||||
&& nodep->fileline()->language() < V3LangCode::L1800_2009) {
|
&& nodep->fileline()->language() < V3LangCode::L1800_2009) {
|
||||||
nodep->v3error("Parameter requires default value, or use IEEE 1800-2009 or later.");
|
nodep->v3error("Parameter requires default value, or use IEEE 1800-2009 or later.");
|
||||||
|
|
|
||||||
|
|
@ -1394,7 +1394,7 @@ parameter_value_assignmentE<pinp>: // IEEE: [ parameter_value_assignment ]
|
||||||
;
|
;
|
||||||
|
|
||||||
parameter_value_assignment<pinp>: // IEEE: parameter_value_assignment
|
parameter_value_assignment<pinp>: // IEEE: parameter_value_assignment
|
||||||
'#' '(' cellparamList ')' { $$ = $3; }
|
'#' '(' cellparamListE ')' { $$ = $3; }
|
||||||
// // Parentheses are optional around a single parameter
|
// // Parentheses are optional around a single parameter
|
||||||
| '#' yaINTNUM { $$ = new AstPin{$<fl>2, 1, "", new AstConst{$<fl>2, *$2}}; }
|
| '#' yaINTNUM { $$ = new AstPin{$<fl>2, 1, "", new AstConst{$<fl>2, *$2}}; }
|
||||||
| '#' yaFLOATNUM { $$ = new AstPin{$<fl>2, 1, "",
|
| '#' yaFLOATNUM { $$ = new AstPin{$<fl>2, 1, "",
|
||||||
|
|
@ -1408,7 +1408,7 @@ parameter_value_assignment<pinp>: // IEEE: parameter_value_assignment
|
||||||
|
|
||||||
parameter_value_assignmentClass<pinp>: // IEEE: [ parameter_value_assignment ] (for classes)
|
parameter_value_assignmentClass<pinp>: // IEEE: [ parameter_value_assignment ] (for classes)
|
||||||
// // Like parameter_value_assignment, but for classes only, which always have #()
|
// // Like parameter_value_assignment, but for classes only, which always have #()
|
||||||
'#' '(' cellparamList ')' { $$ = $3; }
|
'#' '(' cellparamListE ')' { $$ = $3; }
|
||||||
;
|
;
|
||||||
|
|
||||||
parameter_port_listE<nodep>: // IEEE: parameter_port_list + empty == parameter_value_assignment
|
parameter_port_listE<nodep>: // IEEE: parameter_port_list + empty == parameter_value_assignment
|
||||||
|
|
@ -3160,11 +3160,11 @@ instnameList<nodep>:
|
||||||
;
|
;
|
||||||
|
|
||||||
instnameParen<nodep>:
|
instnameParen<nodep>:
|
||||||
id instRangeListE '(' cellpinList ')'
|
id instRangeListE '(' cellpinListE ')'
|
||||||
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, $4, $2); }
|
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, $4, $2); }
|
||||||
| id instRangeListE
|
| id instRangeListE
|
||||||
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, nullptr, $2); }
|
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, nullptr, $2); }
|
||||||
//UNSUP instRangeListE '(' cellpinList ')' { UNSUP } // UDP
|
//UNSUP instRangeListE '(' cellpinListE ')' { UNSUP } // UDP
|
||||||
// // Adding above and switching to the Verilog-Perl syntax
|
// // Adding above and switching to the Verilog-Perl syntax
|
||||||
// // causes a shift conflict due to use of idClassSel inside exprScope.
|
// // causes a shift conflict due to use of idClassSel inside exprScope.
|
||||||
// // It also breaks allowing "id foo;" instantiation syntax.
|
// // It also breaks allowing "id foo;" instantiation syntax.
|
||||||
|
|
@ -3187,22 +3187,22 @@ instRange<nodeRangep>:
|
||||||
{ $$ = new AstRange{$1, $2, $4}; }
|
{ $$ = new AstRange{$1, $2, $4}; }
|
||||||
;
|
;
|
||||||
|
|
||||||
cellparamList<pinp>:
|
cellparamListE<pinp>:
|
||||||
{ GRAMMARP->pinPush(); } cellparamItList { $$ = $2; GRAMMARP->pinPop(CRELINE()); }
|
{ GRAMMARP->pinPush(); } cellparamItListE { $$ = $2; GRAMMARP->pinPop(CRELINE()); }
|
||||||
;
|
;
|
||||||
|
|
||||||
cellpinList<pinp>:
|
cellpinListE<pinp>:
|
||||||
{VARRESET_LIST(UNKNOWN);} cellpinItList { $$ = $2; VARRESET_NONLIST(UNKNOWN); }
|
{ VARRESET_LIST(UNKNOWN); } cellpinItListE { $$ = $2; VARRESET_NONLIST(UNKNOWN); }
|
||||||
;
|
;
|
||||||
|
|
||||||
cellparamItList<pinp>: // IEEE: list_of_parameter_assignmente
|
cellparamItListE<pinp>: // IEEE: list_of_parameter_assignmente
|
||||||
cellparamItemE { $$ = $1; }
|
cellparamItemE { $$ = $1; }
|
||||||
| cellparamItList ',' cellparamItemE { $$ = addNextNull($1, $3); }
|
| cellparamItListE ',' cellparamItemE { $$ = addNextNull($1, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
cellpinItList<pinp>: // IEEE: list_of_port_connections
|
cellpinItListE<pinp>: // IEEE: list_of_port_connections
|
||||||
cellpinItemE { $$ = $1; }
|
cellpinItemE { $$ = $1; }
|
||||||
| cellpinItList ',' cellpinItemE { $$ = addNextNull($1, $3); }
|
| cellpinItListE ',' cellpinItemE { $$ = addNextNull($1, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
cellparamItemE<pinp>: // IEEE: named_parameter_assignment + empty
|
cellparamItemE<pinp>: // IEEE: named_parameter_assignment + empty
|
||||||
|
|
@ -6602,8 +6602,8 @@ checker_generate_item<nodep>: // ==IEEE: checker_generate_item
|
||||||
//UNSUPchecker_instantiation<nodep>:
|
//UNSUPchecker_instantiation<nodep>:
|
||||||
//UNSUP // // Only used for procedural_assertion_item's
|
//UNSUP // // Only used for procedural_assertion_item's
|
||||||
//UNSUP // // Version in concurrent_assertion_item looks like etcInst
|
//UNSUP // // Version in concurrent_assertion_item looks like etcInst
|
||||||
//UNSUP // // Thus instead of *_checker_port_connection we can use etcInst's cellpinList
|
//UNSUP // // Thus instead of *_checker_port_connection we can use etcInst's cellpinListE
|
||||||
//UNSUP id/*checker_identifier*/ id '(' cellpinList ')' ';' { }
|
//UNSUP id/*checker_identifier*/ id '(' cellpinListE ')' ';' { }
|
||||||
//UNSUP ;
|
//UNSUP ;
|
||||||
|
|
||||||
//**********************************************************************
|
//**********************************************************************
|
||||||
|
|
|
||||||
|
|
@ -210,11 +210,11 @@ module t (/*AUTOARG*/);
|
||||||
if(dict_op.get("abcd") != 1) $stop;
|
if(dict_op.get("abcd") != 1) $stop;
|
||||||
|
|
||||||
if (getter1.get_1() != 1) $stop;
|
if (getter1.get_1() != 1) $stop;
|
||||||
if (Getter1::get_1() != 1) $stop;
|
if (Getter1#()::get_1() != 1) $stop;
|
||||||
if (getter1_param_1.get_1() != 1) $stop;
|
if (getter1_param_1.get_1() != 1) $stop;
|
||||||
|
|
||||||
if (getter2.get_2() != 2) $stop;
|
if (getter2.get_2() != 2) $stop;
|
||||||
if (Getter2::get_2() != 2) $stop;
|
if (Getter2#()::get_2() != 2) $stop;
|
||||||
if (Getter2#(2)::get_2() != 2) $stop;
|
if (Getter2#(2)::get_2() != 2) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
%Error: t/t_class_param_bad_paren.v:28:11: Reference to parameterized class without #() (IEEE 1800-2017 8.25.1)
|
||||||
|
: ... Suggest use 'Cls#()'
|
||||||
|
28 | if (Cls::OTHER != 12) $stop;
|
||||||
|
| ^~~
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2022 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
|
||||||
|
|
||||||
|
scenarios(linter => 1);
|
||||||
|
|
||||||
|
lint(
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2023 by Antmicro Ltd.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class Cls #(int PARAM = 1);
|
||||||
|
parameter OTHER = 12;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class Other extends Cls#(); // Ok
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class OtherMaybe extends Cls; // Questionable but others do not warn
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
typedef Cls#(2) Cls2_t; // Ok
|
||||||
|
typedef Cls ClsNone_t; // Ok
|
||||||
|
|
||||||
|
Cls c; // Ok
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (Cls#()::OTHER != 12) $stop; // Ok
|
||||||
|
if (Cls2_t::OTHER != 12) $stop; // ok
|
||||||
|
|
||||||
|
if (Cls::OTHER != 12) $stop; // Bad #() required
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue