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)
|
void CheckInternal::simplePatternError(const Token* tok, const string& pattern, const std::string &funcname)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning, "simplePatternError",
|
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 + "\""
|
"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.checkTokenMatchPatterns();
|
||||||
checkInternal.checkTokenSimpleMatchPatterns();
|
checkInternal.checkTokenSimpleMatchPatterns();
|
||||||
|
checkInternal.checkMissingPercentCharacter();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief %Check if a simple pattern is used inside Token::Match or Token::findmatch */
|
/** @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 */
|
/** @brief %Check if a complex pattern is used inside Token::simpleMatch or Token::findsimplematch */
|
||||||
void checkTokenSimpleMatchPatterns();
|
void checkTokenSimpleMatchPatterns();
|
||||||
|
|
||||||
|
/** @brief %Check for missing % end character in Token::Match pattern */
|
||||||
|
void checkMissingPercentCharacter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void simplePatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
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 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) {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) {
|
||||||
CheckInternal c(0, settings, errorLogger);
|
CheckInternal c(0, settings, errorLogger);
|
||||||
c.simplePatternError(0, "class {", "Match");
|
c.simplePatternError(0, "class {", "Match");
|
||||||
c.complexPatternError(0, "%type% ( )", "Match");
|
c.complexPatternError(0, "%type% ( )", "Match");
|
||||||
|
c.missingPercentCharacterError(0, "%num", "Match");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string myName() const {
|
std::string myName() const {
|
||||||
|
@ -76,7 +82,8 @@ private:
|
||||||
std::string classInfo() const {
|
std::string classInfo() const {
|
||||||
return "Check for wrong or unsuitable internal API usage:\n"
|
return "Check for wrong or unsuitable internal API usage:\n"
|
||||||
"* Found simple pattern inside Token::Match() call: \"class {\"\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(complexPatternInTokenSimpleMatch)
|
||||||
TEST_CASE(simplePatternSquareBrackets)
|
TEST_CASE(simplePatternSquareBrackets)
|
||||||
TEST_CASE(simplePatternAlternatives)
|
TEST_CASE(simplePatternAlternatives)
|
||||||
|
TEST_CASE(missingPercentCharacter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(const std::string &code) {
|
void check(const std::string &code) {
|
||||||
|
@ -171,6 +172,61 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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)
|
REGISTER_TEST(TestInternal)
|
||||||
|
|
Loading…
Reference in New Issue