Add error on mismatching prototypes (#6207).
This commit is contained in:
parent
762c5f573c
commit
60cbbf0ec1
2
Changes
2
Changes
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
| ^~~~~
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue