Add error on mismatching prototypes (#6207).

This commit is contained in:
Wilson Snyder 2025-08-11 19:50:47 -04:00
parent 762c5f573c
commit 60cbbf0ec1
18 changed files with 340 additions and 42 deletions

View File

@ -18,7 +18,7 @@ Verilator 5.039 devel
* Add SPECIFYIGN warning for specify constructs that were previously silently ignored.
* Add PARAMNODEFAULT error, for parameters without defaults.
* Add enum base data type, wire data type, and I/O versus data declaration checking per IEEE.
* Add error on missing forward declarations (#6206). [Alex Solomatnikov]
* Add error on missing and mismatching prototypes (#6206) (#6207). [Alex Solomatnikov]
* Add error when trying to assign class object to variable of non-class types (#6237). [Igor Zaworski, Antmicro Ltd.]
* Add error on class 'function static'.
* Add `-DVERILATOR=1` definition to compiler flags when using verilated.mk.

View File

@ -1612,6 +1612,19 @@ List Of Warnings
accepts the protected code.
.. option:: PROTOTYPEMIS
Error that a function prototype does not match in some respects the
out-of-block declaration of that function. IEEE requires this error.
The typical solution is to fix the prototype to match the declaration
exactly, including in number of arguments, name of arguments, argument
data types, and return data type (for functions).
Disabling this error will cause Verilator to ignore the prototype and
may make the code illegal in other tools.
.. option:: RANDC
Historical, never issued since version 5.018, when :code:`randc` became

View File

@ -508,6 +508,9 @@ public:
ENUM_NAME, // V3Width processes
ENUM_VALID, // V3Width processes
//
FUNC_ARG_PROTO, // V3WidthCommit processes
FUNC_RETURN_PROTO, // V3WidthCommit processes
//
TYPEID, // V3Width processes
TYPENAME, // V3Width processes
//
@ -538,6 +541,7 @@ public:
"DT_PUBLIC",
"ENUM_FIRST", "ENUM_LAST", "ENUM_NUM",
"ENUM_NEXT", "ENUM_PREV", "ENUM_NAME", "ENUM_VALID",
"FUNC_ARG_PROTO", "FUNC_RETURN_PROTO",
"TYPEID", "TYPENAME",
"VAR_BASE", "VAR_CLOCK_ENABLE", "VAR_FORCEABLE", "VAR_PORT_DTYPE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD", "VAR_PUBLIC_FLAT_RW",

View File

@ -1336,7 +1336,7 @@ public:
AstNodeDType* subDTypep() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* virtRefDTypep() const override { return nullptr; }
void virtRefDTypep(AstNodeDType* nodep) override {}
bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; }
bool similarDTypeNode(const AstNodeDType* samep) const override { return true; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 1; }

View File

@ -594,6 +594,7 @@ class AstAttrOf final : public AstNodeExpr {
// @astgen op1 := fromp : Optional[AstNode<AstNodeExpr|AstNodeDType>]
// @astgen op2 := dimp : Optional[AstNodeExpr]
VAttrType m_attrType; // What sort of extraction
string m_name; // Name for some attributes
public:
AstAttrOf(FileLine* fl, VAttrType attrtype, AstNode* fromp = nullptr,
AstNodeExpr* dimp = nullptr)
@ -603,10 +604,11 @@ public:
m_attrType = attrtype;
}
ASTGEN_MEMBERS_AstAttrOf;
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
void name(const string& name) override { m_name = name; }
VAttrType attrType() const { return m_attrType; }
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { V3ERROR_NA_RETURN(true); }

View File

@ -69,6 +69,7 @@ class AstNodeFTask VL_NOT_FINAL : public AstNode {
bool m_taskPublic : 1; // Public task
bool m_attrIsolateAssign : 1; // User isolate_assignments attribute
bool m_classMethod : 1; // Class method
bool m_didProto : 1; // Did prototype processing
bool m_prototype : 1; // Just a prototype
bool m_dpiExport : 1; // DPI exported
bool m_dpiImport : 1; // DPI imported
@ -98,6 +99,7 @@ protected:
, m_taskPublic{false}
, m_attrIsolateAssign{false}
, m_classMethod{false}
, m_didProto{false}
, m_prototype{false}
, m_dpiExport{false}
, m_dpiImport{false}
@ -145,6 +147,8 @@ public:
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool classMethod() const { return m_classMethod; }
void classMethod(bool flag) { m_classMethod = flag; }
bool didProto() const { return m_didProto; }
void didProto(bool flag) { m_didProto = flag; }
bool isExternProto() const { return m_isExternProto; }
void isExternProto(bool flag) { m_isExternProto = flag; }
bool isExternDef() const { return m_isExternDef; }

View File

@ -300,8 +300,8 @@ void V3Error::init() {
describedEachWarn(static_cast<V3ErrorCode>(i), false);
pretendError(static_cast<V3ErrorCode>(i), V3ErrorCode{i}.pretendError());
}
UASSERT(std::string{V3ErrorCode{V3ErrorCode::_ENUM_MAX}.ascii()} == " MAX",
"Enum table in V3ErrorCode::EC_ascii() is munged");
// Not an UASSERT as failure would call V3Error and it's broken due to this
assert(std::string{V3ErrorCode{V3ErrorCode::_ENUM_MAX}.ascii()} == " MAX");
}
string V3Error::lineStr(const char* filename, int lineno) VL_PURE {

View File

@ -139,7 +139,8 @@ public:
PROCASSINIT, // Procedural assignment versus initialization
PROCASSWIRE, // Procedural assignment on wire
PROFOUTOFDATE, // Profile data out of date
PROTECTED, // detected `pragma protected
PROTECTED, // Detected `pragma protected
PROTOTYPEMIS, // Prototype mismatch or related
RANDC, // Unsupported: 'randc' converted to 'rand'
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro
@ -213,14 +214,14 @@ public:
"MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING", "MULTIDRIVEN", "MULTITOP",
"NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT", "PARAMNODEFAULT",
"PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL",
"PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED", "RANDC",
"REALCVT", "REDEFMACRO", "RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT",
"SPECIFYIGN", "SPLITVAR", "STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL",
"USERERROR", "USERFATAL", "USERINFO", "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH",
"WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL",
" MAX"};
"PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
"PROTOTYPEMIS", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY", "SELRANGE",
"SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR", "STATICVAR", "STMTDLY",
"SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", "UNOPT",
"UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDLOOP",
"UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL", "USERINFO", "USERWARN",
"VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC",
"WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"};
return names[m_e];
}
// Warnings that default to off
@ -249,7 +250,8 @@ public:
|| m_e == BLKLOOPINIT || m_e == CONTASSREG || m_e == ENCAPSULATED
|| m_e == ENDLABEL || m_e == ENUMITEMWIDTH || m_e == ENUMVALUE || m_e == IMPURE
|| m_e == MODMISSING || m_e == PARAMNODEFAULT || m_e == PINNOTFOUND
|| m_e == PKGNODECL || m_e == PROCASSWIRE || m_e == ZEROREPL // Says IEEE
|| m_e == PKGNODECL || m_e == PROCASSWIRE || m_e == PROTOTYPEMIS
|| m_e == ZEROREPL // Says IEEE
);
}
// Warnings to mention manual

View File

@ -3717,8 +3717,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
}
if (nodep->isExternProto()) {
if (!m_curSymp->findIdFallback(nodep->name()) && nodep->isExternExplicit()) {
nodep->v3error("Definition not found for extern prototype "
+ nodep->prettyNameQ());
nodep->v3warn(PROTOTYPEMIS, "Definition not found for extern prototype "
<< nodep->prettyNameQ());
}
}
VL_RESTORER(m_curSymp);
@ -4270,7 +4270,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
LINKDOT_VISIT_START();
UINFO(5, indent() << "visit " << nodep);
checkNoDot(nodep);
if (nodep->isExternDef()) {
if (nodep->isExternDef() && !nodep->didProto()) {
nodep->didProto(true);
if (const VSymEnt* const foundp
= m_curSymp->findIdFallback("extern " + nodep->name())) {
const AstNodeFTask* const protop = VN_AS(foundp->nodep(), NodeFTask);
@ -4281,14 +4282,28 @@ class LinkDotResolveVisitor final : public VNVisitor {
nodep->isStatic(protop->isStatic());
nodep->isVirtual(protop->isVirtual());
nodep->lifetime(protop->lifetime());
// Always add an FUNC_RETURN_PROTO even if task, so we can locate the prototype
nodep->addStmtsp(new AstAttrOf{protop->fileline(), VAttrType::FUNC_RETURN_PROTO,
protop->fvarp()
? protop->fvarp()->cloneTree(false)
: new AstVoidDType{protop->fileline()}});
for (AstNode* stmtp = protop->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (AstVar* const portp = VN_CAST(stmtp, Var)) {
AstAttrOf* const attrp
= new AstAttrOf{protop->fileline(), VAttrType::FUNC_ARG_PROTO,
portp->subDTypep()->cloneTree(false)};
attrp->name(portp->name());
nodep->addStmtsp(attrp);
}
}
} else {
nodep->v3error("extern not found that declares " + nodep->prettyNameQ());
}
}
if (nodep->isExternProto()) {
if (!m_curSymp->findIdFallback(nodep->name())) {
nodep->v3error("Definition not found for extern prototype "
+ nodep->prettyNameQ());
nodep->v3warn(PROTOTYPEMIS,
"Definition not found for extern prototype " + nodep->prettyNameQ());
}
}
VL_RESTORER(m_curSymp);

View File

@ -911,7 +911,7 @@ class WidthVisitor final : public VNVisitor {
}
void visit(AstNodeStream* nodep) override {
VL_RESTORER(m_streamConcat);
UINFOTREE(1, nodep, "stream-in vup" << m_vup, "stream-in ");
// UINFOTREE(1, nodep, "stream-in vup" << m_vup, "stream-in ");
if (m_vup->prelim()) {
m_streamConcat = true;
iterateCheckSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
@ -1669,9 +1669,6 @@ class WidthVisitor final : public VNVisitor {
if (nodep->dimp()) userIterateAndNext(nodep->dimp(), WidthVP{SELF, BOTH}.p());
// Don't iterate children, don't want to lose VarRef.
switch (nodep->attrType()) {
case VAttrType::VAR_BASE:
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
break;
case VAttrType::DIM_DIMENSIONS:
case VAttrType::DIM_UNPK_DIMENSIONS: {
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, "Unsized expression");
@ -1795,6 +1792,36 @@ class WidthVisitor final : public VNVisitor {
}
break;
}
case VAttrType::FUNC_ARG_PROTO:
// Created by V3LinkDot only to check that the prototype was correct when we got here
// Checked at bottom of visit(AstNodeFTask)
// V3WidthCommit::visit(AstAttrOf) will delete nodep
break;
case VAttrType::FUNC_RETURN_PROTO: {
// Created by V3LinkDot only to check that the prototype was correct when we got here
UASSERT_OBJ(m_ftaskp, nodep, "FUNC attr not under function");
AstNodeDType* const protoDtp = nodep->fromp()->dtypep();
AstNodeDType* const declDtp = m_ftaskp->fvarp()
? m_ftaskp->fvarp()->dtypep()
: new AstVoidDType{m_ftaskp->fileline()};
if (!similarDTypeRecurse(protoDtp, declDtp)) {
protoDtp->v3warn(
PROTOTYPEMIS,
"In prototype for "
<< m_ftaskp->prettyNameQ()
<< ", return data type does not match out-of-block"
" declaration data-type (IEEE 1800-2023 8.24)\n"
<< protoDtp->warnMore()
<< "... Prototype data type: " << protoDtp->prettyDTypeNameQ() << '\n'
<< protoDtp->warnMore()
<< "... Declaration data type: " << declDtp->prettyDTypeNameQ() << '\n'
<< protoDtp->warnContextPrimary() << '\n'
<< declDtp->warnOther() << "... Location of out-of-block declaration\n"
<< declDtp->warnContextSecondary());
}
// V3WidthCommit::visit(AstAttrOf) will delete nodep
break;
}
case VAttrType::TYPENAME: {
UASSERT_OBJ(nodep->fromp(), nodep, "Unprovided expression");
const string result = nodep->fromp()->dtypep()->prettyDTypeName(true);
@ -1808,6 +1835,9 @@ class WidthVisitor final : public VNVisitor {
// Soon to be handled in AstEqT
nodep->dtypeSetSigned32();
break;
case VAttrType::VAR_BASE:
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
break;
default: {
// Everything else resolved earlier
nodep->dtypeSetLogicUnsized(32, 1, VSigning::UNSIGNED); // Approximation, unsized 32
@ -6076,6 +6106,67 @@ class WidthVisitor final : public VNVisitor {
nodep->dpiOpenParentInc(); // Mark so V3Task will wait for a child to build calling
// func
}
std::vector<AstVar*> ports;
std::vector<AstAttrOf*> protos;
AstAttrOf* protop = nullptr; // Base prototype
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (AstVar* const portp = VN_CAST(stmtp, Var)) {
if (portp->isIO() && !portp->isFuncReturn()) { ports.emplace_back(portp); }
} else if (AstAttrOf* const attrp = VN_CAST(stmtp, AttrOf)) {
if (attrp->attrType() == VAttrType::FUNC_ARG_PROTO) { protos.emplace_back(attrp); }
if (attrp->attrType() == VAttrType::FUNC_RETURN_PROTO) { protop = attrp; }
}
}
if (protop) {
for (size_t i = 0; i < std::max(ports.size(), protos.size()); ++i) {
if (i >= ports.size() || i >= protos.size()) {
protop->v3warn(
PROTOTYPEMIS,
"In prototype for "
<< nodep->prettyNameQ()
<< ", the argumement counts do not match the out-of-block declaration"
<< " (IEEE 1800-2023 8.24)\n"
<< protop->warnContextPrimary() << '\n'
<< nodep->warnOther() << "... Location of out-of-block declaration\n"
<< nodep->warnContextSecondary());
break;
} else {
AstVar* const portp = ports[i];
AstAttrOf* const protop = protos[i];
AstNodeDType* const declDtp = portp->dtypep();
AstNodeDType* const protoDtp = protop->fromp()->dtypep();
if (portp->name() != protop->name()) {
protoDtp->v3warn(PROTOTYPEMIS,
"In prototype for "
<< nodep->prettyNameQ() << ", argument " << (i + 1)
<< " named " << protop->prettyNameQ()
<< " mismatches out-of-block argument name "
<< portp->prettyNameQ() << " (IEEE 1800-2023 8.24)\n"
<< protoDtp->warnContextPrimary() << '\n'
<< declDtp->warnOther()
<< "... Location of out-of-block declaration\n"
<< declDtp->warnContextSecondary());
} else if (!similarDTypeRecurse(protoDtp, declDtp)) {
protoDtp->v3warn(
PROTOTYPEMIS,
"In prototype for "
<< nodep->prettyNameQ() << ", argument " << portp->prettyNameQ()
<< " data-type does not match out-of-block"
" declaration's data-type (IEEE 1800-2023 8.24)\n"
<< protoDtp->warnMore() << "... Prototype data type: "
<< protoDtp->prettyDTypeNameQ() << '\n'
<< protoDtp->warnMore() << "... Declaration data type: "
<< declDtp->prettyDTypeNameQ() << '\n'
<< protoDtp->warnContextPrimary() << '\n'
<< declDtp->warnOther()
<< "... Location of out-of-block declaration\n"
<< declDtp->warnContextSecondary());
}
}
}
// V3WidthCommit::visit(AstAttrOf) will delete nodep
}
}
void visit(AstConstraint* nodep) override {
if (nodep->didWidth()) return;

View File

@ -168,6 +168,17 @@ private:
}
}
}
void visit(AstAttrOf* nodep) override {
switch (nodep->attrType()) {
case VAttrType::FUNC_ARG_PROTO: // FALLTHRU
case VAttrType::FUNC_RETURN_PROTO:
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
default:;
}
iterateChildren(nodep);
editDType(nodep);
}
void visit(AstClassExtends* nodep) override {
if (nodep->user1SetOnce()) return; // Process once
// Extend arguments were converted to super.new arguments in V3LinkDot

View File

@ -0,0 +1,17 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 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('vlt')
test.top_filename = 't/t_class_extern_args_bad.v'
test.lint(verilator_flags2=['-Wno-PROTOTYPEMIS'])
test.passes()

View File

@ -0,0 +1,75 @@
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:8:15: In prototype for 'func_bad', return data type does not match out-of-block declaration data-type (IEEE 1800-2023 8.24)
: ... note: In instance 't'
: ... Prototype data type: 'VOIDDTYPE'
: ... Declaration data type: 'bit'
8 | extern task func_bad();
| ^~~~~~~~
t/t_class_extern_args_bad.v:19:10: ... Location of out-of-block declaration
19 | function bit Cls::func_bad();
| ^~~
... For error description see https://verilator.org/warn/PROTOTYPEMIS?v=latest
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:9:19: In prototype for 'f1_bad', return data type does not match out-of-block declaration data-type (IEEE 1800-2023 8.24)
: ... note: In instance 't'
: ... Prototype data type: 'int'
: ... Declaration data type: 'bit'
9 | extern function int f1_bad();
| ^~~
t/t_class_extern_args_bad.v:22:10: ... Location of out-of-block declaration
22 | function bit Cls::f1_bad();
| ^~~
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:10:19: In prototype for 'f2_bad', return data type does not match out-of-block declaration data-type (IEEE 1800-2023 8.24)
: ... note: In instance 't'
: ... Prototype data type: 'int'
: ... Declaration data type: 'VOIDDTYPE'
10 | extern function int f2_bad();
| ^~~
t/t_class_extern_args_bad.v:24:15: ... Location of out-of-block declaration
24 | function void Cls::f2_bad();
| ^~~
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:11:24: In prototype for 'f3_bad', return data type does not match out-of-block declaration data-type (IEEE 1800-2023 8.24)
: ... note: In instance 't'
: ... Prototype data type: 'VOIDDTYPE'
: ... Declaration data type: 'bit'
11 | extern function void f3_bad();
| ^~~~~~
t/t_class_extern_args_bad.v:26:10: ... Location of out-of-block declaration
26 | function bit Cls::f3_bad();
| ^~~
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:12:34: In prototype for 'f1bit_bad', argument 'a' data-type does not match out-of-block declaration's data-type (IEEE 1800-2023 8.24)
: ... note: In instance 't'
: ... Prototype data type: 'int'
: ... Declaration data type: 'bit'
12 | extern function void f1bit_bad(int a);
| ^~~
t/t_class_extern_args_bad.v:29:30: ... Location of out-of-block declaration
29 | function void Cls::f1bit_bad(bit a);
| ^~~
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:13:24: In prototype for 'f2args1_bad', the argumement counts do not match the out-of-block declaration (IEEE 1800-2023 8.24)
: ... note: In instance 't'
13 | extern function void f2args1_bad(bit a);
| ^~~~~~~~~~~
t/t_class_extern_args_bad.v:32:15: ... Location of out-of-block declaration
32 | function void Cls::f2args1_bad(bit a, bit b);
| ^~~
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:14:24: In prototype for 'f2args2', the argumement counts do not match the out-of-block declaration (IEEE 1800-2023 8.24)
: ... note: In instance 't'
14 | extern function void f2args2(bit a);
| ^~~~~~~
t/t_class_extern_args_bad.v:35:15: ... Location of out-of-block declaration
35 | function void Cls::f2args2(bit a, bit b);
| ^~~
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:15:24: In prototype for 'f2args3_bad', the argumement counts do not match the out-of-block declaration (IEEE 1800-2023 8.24)
: ... note: In instance 't'
15 | extern function void f2args3_bad(bit a, bit b, bit c);
| ^~~~~~~~~~~
t/t_class_extern_args_bad.v:38:15: ... Location of out-of-block declaration
38 | function void Cls::f2args3_bad(bit a, bit b);
| ^~~
%Error-PROTOTYPEMIS: t/t_class_extern_args_bad.v:16:38: In prototype for 'farg_name_bad', argument 1 named 'declnamebad' mismatches out-of-block argument name 'declname' (IEEE 1800-2023 8.24)
: ... note: In instance 't'
16 | extern function void farg_name_bad(bit declnamebad);
| ^~~
t/t_class_extern_args_bad.v:41:34: ... Location of out-of-block declaration
41 | function void Cls::farg_name_bad(bit declname);
| ^~~
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 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()

View File

@ -0,0 +1,46 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
class Cls;
extern task func_bad(); //<--- Error (mismatch func)
extern function int f1_bad(); //<--- Error (mismatch func type)
extern function int f2_bad(); //<--- Error (mismatch func type)
extern function void f3_bad(); //<--- Error (mismatch func type)
extern function void f1bit_bad(int a); //<--- Error (mismatch arg type)
extern function void f2args1_bad(bit a); //<--- Error (missing arg)
extern function void f2args2(bit a); // ok
extern function void f2args3_bad(bit a, bit b, bit c); //<--- Error (missing arg)
extern function void farg_name_bad(bit declnamebad); //<--- Error (declname arg)
endclass
function bit Cls::func_bad();
endfunction
function bit Cls::f1_bad();
endfunction
function void Cls::f2_bad();
endfunction
function bit Cls::f3_bad();
endfunction
function void Cls::f1bit_bad(bit a);
endfunction
function void Cls::f2args1_bad(bit a, bit b);
endfunction
function void Cls::f2args2(bit a, bit b);
endfunction
function void Cls::f2args3_bad(bit a, bit b);
endfunction
function void Cls::farg_name_bad(bit declname);
endfunction
module t;
initial $stop;
endmodule

View File

@ -1,16 +1,17 @@
%Error: t/t_class_extern_bad.v:9:16: Duplicate declaration of task: 'extern nodef'
9 | extern task nodef();
| ^~~~~
t/t_class_extern_bad.v:8:16: ... Location of original declaration
8 | extern task nodef();
| ^~~~~
%Error: t/t_class_extern_bad.v:9:15: Duplicate declaration of task: 'extern nodef'
9 | extern task nodef();
| ^~~~~
t/t_class_extern_bad.v:8:15: ... Location of original declaration
8 | extern task nodef();
| ^~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_class_extern_bad.v:8:16: Definition not found for extern prototype 'nodef'
8 | extern task nodef();
| ^~~~~
%Error: t/t_class_extern_bad.v:9:16: Definition not found for extern prototype 'nodef'
9 | extern task nodef();
| ^~~~~
%Error-PROTOTYPEMIS: t/t_class_extern_bad.v:8:15: Definition not found for extern prototype 'nodef'
8 | extern task nodef();
| ^~~~~
... For error description see https://verilator.org/warn/PROTOTYPEMIS?v=latest
%Error-PROTOTYPEMIS: t/t_class_extern_bad.v:9:15: Definition not found for extern prototype 'nodef'
9 | extern task nodef();
| ^~~~~
%Error: t/t_class_extern_bad.v:12:6: extern not found that declares 'noproto'
12 | task Base1::noproto();
| ^~~~~

View File

@ -5,12 +5,12 @@
// SPDX-License-Identifier: CC0-1.0
class Base1;
extern task nodef();
extern task nodef(); // duplicate
extern task nodef();
extern task nodef(); // <--- Error: duplicate
endclass
task Base1::noproto(); // no such prototype
task Base1::noproto(); // <--- Error: Missing prototype
endtask
module t (/*AUTOARG*/);
module t;
endmodule

View File

@ -1,8 +1,9 @@
%Error: t/t_constraint_extern_bad.v:8:22: Definition not found for extern prototype 'missing_bad'
%Error-PROTOTYPEMIS: t/t_constraint_extern_bad.v:8:22: Definition not found for extern prototype 'missing_bad'
8 | extern constraint missing_bad;
| ^~~~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
... For error description see https://verilator.org/warn/PROTOTYPEMIS?v=latest
%Error: t/t_constraint_extern_bad.v:11:20: extern not found that declares 'missing_extern'
11 | constraint Packet::missing_extern { }
| ^~~~~~~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to