Detect wrong number of args on method calls.
This commit is contained in:
parent
ce5a70fbca
commit
3eb0ff8aa0
|
|
@ -1646,6 +1646,28 @@ private:
|
|||
<<"' which is a '"<<nodep->fromp()->dtypep()->prettyTypeName()<<"'");
|
||||
}
|
||||
}
|
||||
void methodOkArguments(AstMethodSel* nodep, int minArg, int maxArg) {
|
||||
int narg = 0;
|
||||
for (AstNode* argp = nodep->pinsp(); argp; argp = argp->nextp()) ++narg;
|
||||
bool ok = (narg >= minArg) && (narg <= maxArg);
|
||||
if (!ok) {
|
||||
nodep->v3error("The "<<narg<<" arguments passed to ."<<nodep->prettyName()
|
||||
<<" method does not match its requiring "<<cvtToStr(minArg)
|
||||
<<(minArg == maxArg ? "" : " to " + cvtToStr(maxArg))
|
||||
<<" arguments");
|
||||
// Adjust to required argument counts, very bogus, but avoids core dump
|
||||
for (; narg < minArg; ++narg) {
|
||||
nodep->addPinsp(new AstArg(nodep->fileline(), "",
|
||||
new AstConst(nodep->fileline(), 0)));
|
||||
}
|
||||
for (; narg > maxArg; --narg) {
|
||||
AstNode* argp = nodep->pinsp();
|
||||
while (argp->nextp()) argp = argp->nextp();
|
||||
argp->unlinkFrBack(); argp->deleteTree(); VL_DANGLING(argp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void methodCallEnum(AstMethodSel* nodep, AstEnumDType* adtypep) {
|
||||
// Method call on enum without following parenthesis, e.g. "ENUM.next"
|
||||
// Convert this into a method call, and let that visitor figure out what to do next
|
||||
|
|
@ -1655,7 +1677,7 @@ private:
|
|||
|| nodep->name() == "last") {
|
||||
// Constant value
|
||||
AstConst* newp = NULL;
|
||||
if (nodep->pinsp()) nodep->v3error("Arguments passed to enum.num method, but it does not take arguments");
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
if (nodep->name() == "num") {
|
||||
int items = 0;
|
||||
for (AstNode* itemp = adtypep->itemsp(); itemp; itemp = itemp->nextp()) ++items;
|
||||
|
|
@ -1685,8 +1707,8 @@ private:
|
|||
else if (nodep->name() == "prev") attrType = AstAttrType::ENUM_PREV;
|
||||
else nodep->v3fatalSrc("Bad case");
|
||||
|
||||
if (nodep->pinsp() && nodep->name() == "name") {
|
||||
nodep->v3error("Arguments passed to enum.name method, but it does not take arguments");
|
||||
if (nodep->name() == "name") {
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
} else if (nodep->pinsp()
|
||||
&& !(VN_IS(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)
|
||||
&& VN_CAST(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)->toUInt() == 1
|
||||
|
|
@ -1735,7 +1757,7 @@ private:
|
|||
else if (nodep->name() == "xor") methodId = ARRAY_XOR;
|
||||
|
||||
if (methodId) {
|
||||
if (nodep->pinsp()) nodep->v3error("Arguments passed to array method, but it does not take arguments");
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
FileLine* fl = nodep->fileline();
|
||||
AstNode* newp = NULL;
|
||||
for (int i = 0; i < adtypep->elementsConst(); ++i) {
|
||||
|
|
@ -1762,19 +1784,24 @@ private:
|
|||
// Method call on string
|
||||
if (nodep->name() == "len") {
|
||||
// Constant value
|
||||
if (nodep->pinsp()) nodep->v3error("Arguments passed to string.len method, but it does not take arguments");
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
AstNode* newp = new AstLenN(nodep->fileline(), nodep->fromp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
} else if (nodep->name() == "itoa") {
|
||||
methodOkArguments(nodep, 1, 1);
|
||||
replaceWithSFormat(nodep, "%0d"); VL_DANGLING(nodep);
|
||||
} else if (nodep->name() == "hextoa") {
|
||||
methodOkArguments(nodep, 1, 1);
|
||||
replaceWithSFormat(nodep, "%0x"); VL_DANGLING(nodep);
|
||||
} else if (nodep->name() == "octtoa") {
|
||||
methodOkArguments(nodep, 1, 1);
|
||||
replaceWithSFormat(nodep, "%0o"); VL_DANGLING(nodep);
|
||||
} else if (nodep->name() == "bintoa") {
|
||||
methodOkArguments(nodep, 1, 1);
|
||||
replaceWithSFormat(nodep, "%0b"); VL_DANGLING(nodep);
|
||||
} else if (nodep->name() == "realtoa") {
|
||||
methodOkArguments(nodep, 1, 1);
|
||||
replaceWithSFormat(nodep, "%g"); VL_DANGLING(nodep);
|
||||
} else {
|
||||
nodep->v3error("Unsupported: built-in string method "<<nodep->prettyNameQ());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
%Error: t/t_string_type_methods_bad.v:14: The 1 arguments passed to .len method does not match its requiring 0 arguments
|
||||
: ... In instance t
|
||||
i = s.len(0);
|
||||
^~~
|
||||
%Error: t/t_string_type_methods_bad.v:15: The 0 arguments passed to .itoa method does not match its requiring 1 arguments
|
||||
: ... In instance t
|
||||
s.itoa;
|
||||
^~~~
|
||||
%Error: t/t_string_type_methods_bad.v:16: The 3 arguments passed to .itoa method does not match its requiring 1 arguments
|
||||
: ... In instance t
|
||||
s.itoa(1,2,3);
|
||||
^~~~
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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.
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
string s;
|
||||
integer i;
|
||||
|
||||
// Check constification
|
||||
initial begin
|
||||
s="1234";
|
||||
i = s.len(0); // BAD
|
||||
s.itoa; // BAD
|
||||
s.itoa(1,2,3); // BAD
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in New Issue