Add internal check that searches Token::Match() patterns for missing % end charaters
Example: "%type" or "foo %var bar"
This commit is contained in:
parent
b67cb077a3
commit
3d438003ff
|
@ -116,6 +116,56 @@ void CheckInternal::checkTokenSimpleMatchPatterns()
|
|||
}
|
||||
}
|
||||
|
||||
void CheckInternal::checkMissingPercentCharacter()
|
||||
{
|
||||
set<string> magics;
|
||||
magics.insert("%any%");
|
||||
magics.insert("%var%");
|
||||
magics.insert("%type%");
|
||||
magics.insert("%num%");
|
||||
magics.insert("%bool%");
|
||||
magics.insert("%str%");
|
||||
magics.insert("%varid%");
|
||||
magics.insert("%or%");
|
||||
magics.insert("%oror%");
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (!Token::simpleMatch(tok, "Token :: Match (") && !Token::simpleMatch(tok, "Token :: findmatch ("))
|
||||
continue;
|
||||
|
||||
const std::string funcname = tok->strAt(2);
|
||||
|
||||
// Get pattern string
|
||||
const Token *pattern_tok = tok->tokAt(4)->nextArgument();
|
||||
if (!pattern_tok || !Token::Match(pattern_tok, "%str%"))
|
||||
continue;
|
||||
|
||||
const string pattern = pattern_tok->strValue();
|
||||
|
||||
set<string>::const_iterator magic, magics_end = magics.end();
|
||||
for (magic = magics.begin(); magic != magics_end; ++magic) {
|
||||
const string broken_magic = (*magic).substr(0, (*magic).size()-1);
|
||||
|
||||
string::size_type pos = 0;
|
||||
while((pos = pattern.find(broken_magic, pos)) != string::npos) {
|
||||
// Check if it's the full pattern
|
||||
if (pattern.find(*magic, pos) != pos) {
|
||||
// Known whitelist of substrings
|
||||
if ((broken_magic == "%var" && pattern.find("%varid%", pos) == pos) ||
|
||||
(broken_magic == "%or" && pattern.find("%oror%", pos) == pos)) {
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
missingPercentCharacterError(tok, pattern, funcname);
|
||||
}
|
||||
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckInternal::simplePatternError(const Token* tok, const string& pattern, const std::string &funcname)
|
||||
{
|
||||
reportError(tok, Severity::warning, "simplePatternError",
|
||||
|
@ -129,3 +179,10 @@ void CheckInternal::complexPatternError(const Token* tok, const string& pattern,
|
|||
"Found complex pattern inside Token::" + funcname + "() call: \"" + pattern + "\""
|
||||
);
|
||||
}
|
||||
|
||||
void CheckInternal::missingPercentCharacterError(const Token* tok, const std::string& pattern, const std::string& funcname)
|
||||
{
|
||||
reportError(tok, Severity::error, "missingPercentCharacter",
|
||||
"Missing percent end character in Token::" + funcname + "() pattern: \"" + pattern + "\""
|
||||
);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
|
||||
checkInternal.checkTokenMatchPatterns();
|
||||
checkInternal.checkTokenSimpleMatchPatterns();
|
||||
checkInternal.checkMissingPercentCharacter();
|
||||
}
|
||||
|
||||
/** @brief %Check if a simple pattern is used inside Token::Match or Token::findmatch */
|
||||
|
@ -59,14 +60,19 @@ public:
|
|||
/** @brief %Check if a complex pattern is used inside Token::simpleMatch or Token::findsimplematch */
|
||||
void checkTokenSimpleMatchPatterns();
|
||||
|
||||
/** @brief %Check for missing % end character in Token::Match pattern */
|
||||
void checkMissingPercentCharacter();
|
||||
|
||||
private:
|
||||
void simplePatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
||||
void complexPatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
||||
void missingPercentCharacterError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) {
|
||||
CheckInternal c(0, settings, errorLogger);
|
||||
c.simplePatternError(0, "class {", "Match");
|
||||
c.complexPatternError(0, "%type% ( )", "Match");
|
||||
c.missingPercentCharacterError(0, "%num", "Match");
|
||||
}
|
||||
|
||||
std::string myName() const {
|
||||
|
@ -76,7 +82,8 @@ private:
|
|||
std::string classInfo() const {
|
||||
return "Check for wrong or unsuitable internal API usage:\n"
|
||||
"* Found simple pattern inside Token::Match() call: \"class {\"\n"
|
||||
"* Found complex pattern inside Token::simpleMatch() call: \"%type\"\n";
|
||||
"* Found complex pattern inside Token::simpleMatch() call: \"%type%\"\n"
|
||||
"* Missing percent end character in Token::Match pattern: \"%num\"\n";
|
||||
}
|
||||
};
|
||||
/// @}
|
||||
|
|
|
@ -36,6 +36,7 @@ private:
|
|||
TEST_CASE(complexPatternInTokenSimpleMatch)
|
||||
TEST_CASE(simplePatternSquareBrackets)
|
||||
TEST_CASE(simplePatternAlternatives)
|
||||
TEST_CASE(missingPercentCharacter);
|
||||
}
|
||||
|
||||
void check(const std::string &code) {
|
||||
|
@ -171,6 +172,61 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void missingPercentCharacter() {
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"%type%\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"foo %type% bar\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// Missing % at the end of string
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"%type\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"%type\"\n", errout.str());
|
||||
|
||||
// Missing % in the middle of a pattern
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"foo %type bar\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"foo %type bar\"\n", errout.str());
|
||||
|
||||
// Bei quiet on single %
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"foo % %type% bar\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"foo % %type % bar\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"foo % %type % bar\"\n", errout.str());
|
||||
|
||||
// Find missing % also in 'alternatives' pattern
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"foo|%type|bar\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"foo|%type|bar\"\n", errout.str());
|
||||
|
||||
// Make sure we don't take %or% for a broken %oror%
|
||||
check("void f() {\n"
|
||||
" const Token *tok;\n"
|
||||
" Token::Match(tok, \"foo|%oror%|bar\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestInternal)
|
||||
|
|
Loading…
Reference in New Issue