Add error on illegal --prefix etc. values (#5507).

This commit is contained in:
Wilson Snyder
2024-11-26 21:06:43 -05:00
parent 713dab278c
commit bee344d1ae
12 changed files with 97 additions and 9 deletions
+20 -4
View File
@@ -561,6 +561,12 @@ int V3Options::stripOptionsForChildRun(const string& opt, bool forTop) {
return 0;
}
void V3Options::validateIdentifier(FileLine* fl, const string& arg, const string& opt) {
if (!VString::isIdentifier(arg)) {
fl->v3error(opt << " argument must be a legal C++ identifier: '" << arg << "'");
}
}
string V3Options::filePath(FileLine* fl, const string& modname, const string& lastpath,
const string& errmsg) { // Error prefix or "" to suppress error
// Find a filename to read the specified module name,
@@ -1386,7 +1392,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
};
DECL_OPTION("-default-language", CbVal, setLang);
DECL_OPTION("-language", CbVal, setLang);
DECL_OPTION("-lib-create", Set, &m_libCreate);
DECL_OPTION("-lib-create", CbVal, [this, fl](const char* valp) {
validateIdentifier(fl, valp, "--lib-create");
m_libCreate = valp;
});
DECL_OPTION("-lint-only", OnOff, &m_lintOnly);
DECL_OPTION("-localize-max-size", Set, &m_localizeMaxSize);
DECL_OPTION("-main-top-name", Set, &m_mainTopName);
@@ -1409,7 +1418,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
}
});
DECL_OPTION("-max-num-width", Set, &m_maxNumWidth);
DECL_OPTION("-mod-prefix", Set, &m_modPrefix);
DECL_OPTION("-mod-prefix", CbVal, [this, fl](const char* valp) {
validateIdentifier(fl, valp, "--mod-prefix");
m_modPrefix = valp;
});
DECL_OPTION("-O0", CbCall, [this]() { optimize(0); });
DECL_OPTION("-O1", CbCall, [this]() { optimize(1); });
@@ -1460,7 +1472,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-pins-uint8", OnOff, &m_pinsUint8);
DECL_OPTION("-pipe-filter", Set, &m_pipeFilter);
DECL_OPTION("-pp-comments", OnOff, &m_ppComments);
DECL_OPTION("-prefix", Set, &m_prefix);
DECL_OPTION("-prefix", CbVal, [this, fl](const char* valp) {
validateIdentifier(fl, valp, "--prefix");
m_prefix = valp;
});
DECL_OPTION("-private", CbCall, [this]() { m_public = false; });
DECL_OPTION("-prof-c", OnOff, &m_profC);
DECL_OPTION("-prof-cfuncs", CbCall, [this]() { m_profC = m_profCFuncs = true; });
@@ -1470,7 +1485,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-prof-pgo", OnOff, &m_profPgo);
DECL_OPTION("-protect-ids", OnOff, &m_protectIds);
DECL_OPTION("-protect-key", Set, &m_protectKey);
DECL_OPTION("-protect-lib", CbVal, [this](const char* valp) {
DECL_OPTION("-protect-lib", CbVal, [this, fl](const char* valp) {
validateIdentifier(fl, valp, "--protect-lib");
m_libCreate = valp;
m_protectIds = true;
});
+1
View File
@@ -428,6 +428,7 @@ private:
static string parseFileArg(const string& optdir, const string& relfilename);
string filePathCheckOneDir(const string& modname, const string& dirname);
static int stripOptionsForChildRun(const string& opt, bool forTop);
void validateIdentifier(FileLine* fl, const string& arg, const string& opt);
// CONSTRUCTORS
VL_UNCOPYABLE(V3Options);
+1 -1
View File
@@ -490,7 +490,7 @@ void V3PreProcImp::comment(const string& text) {
if (VString::startsWith(cmd, "public_flat_rw")) {
// "/*verilator public_flat_rw @(foo) */" -> "/*verilator public_flat_rw*/ @(foo)"
string::size_type endOfCmd = std::strlen("public_flat_rw");
while (VString::isWordChar(cmd[endOfCmd])) ++endOfCmd;
while (VString::isIdentifierChar(cmd[endOfCmd])) ++endOfCmd;
string baseCmd = cmd.substr(0, endOfCmd);
string arg = cmd.substr(endOfCmd);
while (std::isspace(arg[0])) arg = arg.substr(1);
+9 -2
View File
@@ -216,6 +216,13 @@ string VString::removeWhitespace(const string& str) {
return result;
}
bool VString::isIdentifier(const string& str) {
for (const char c : str) {
if (!isIdentifierChar(c)) return false;
}
return true;
}
bool VString::isWhitespace(const string& str) {
for (const char c : str) {
if (!std::isspace(c)) return false;
@@ -256,8 +263,8 @@ string VString::replaceWord(const string& str, const string& from, const string&
UASSERT_STATIC(len > 0, "Cannot replace empty string");
for (size_t pos = 0; (pos = result.find(from, pos)) != string::npos; pos += len) {
// Only replace whole words
if (((pos > 0) && VString::isWordChar(result[pos - 1])) || //
((pos + len < result.size()) && VString::isWordChar(result[pos + len]))) {
if (((pos > 0) && VString::isIdentifierChar(result[pos - 1])) || //
((pos + len < result.size()) && VString::isIdentifierChar(result[pos + len]))) {
continue;
}
result.replace(pos, len, to);
+4 -2
View File
@@ -114,6 +114,10 @@ public:
static string spaceUnprintable(const string& str) VL_PURE;
// Remove any whitespace
static string removeWhitespace(const string& str);
// Return true if only identifer or ""
static bool isIdentifier(const string& str);
// Return true if char is valid character in C identifiers
static bool isIdentifierChar(char c) { return isalnum(c) || c == '_'; }
// Return true if only whitespace or ""
static bool isWhitespace(const string& str);
// Return number of spaces/tabs leading in string
@@ -128,8 +132,6 @@ public:
static bool startsWith(const string& str, const string& prefix);
// Predicate to check if 'str' ends with 'suffix'
static bool endsWith(const string& str, const string& suffix);
// Return true if char is valid character in word
static bool isWordChar(char c) { return isalnum(c) || c == '_'; }
// Return proper article (a/an) for a word. May be inaccurate for some special words
static string aOrAn(const char* word);
static string aOrAn(const string& word) { return aOrAn(word.c_str()); }