CheckInternal: Improved checking of multiCompare patterns

This commit is contained in:
Daniel Marjamäki 2014-01-05 21:15:41 +01:00
parent 0877adb542
commit 62c608141d
3 changed files with 55 additions and 1 deletions

View File

@ -22,6 +22,7 @@
#include "symboldatabase.h"
#include <string>
#include <set>
#include <cstring>
// Register this check class (by creating a static instance of it).
// Disabled in release builds
@ -48,6 +49,32 @@ void CheckInternal::checkTokenMatchPatterns()
continue;
}
const char *p = pattern.c_str();
while (*p) {
while (*p && std::isspace(*p))
p++;
const char *start = p;
while (*p && !std::isspace(*p))
p++;
const char *end = p - 1;
if (start < end && !(*start == '[' && *end == ']')) {
// check multicompare pattern..
for (const char *s = start; s != end; s++) {
if (*s == '|') {
if (*(s+1) == '%' &&
std::isalpha(*(s+2)) &&
std::strncmp(s+1,"%op%",4)!=0 &&
std::strncmp(s+1,"%or%",4)!=0 &&
std::strncmp(s+1,"%cop%",5)!=0 &&
std::strncmp(s+1,"%var%",5)!=0 &&
std::strncmp(s+1,"%oror%",6)!=0) {
multiComparePatternError(tok, pattern, funcname);
}
}
}
}
}
// Check for signs of complex patterns
if (pattern.find_first_of("[|%") != std::string::npos)
continue;
@ -245,6 +272,13 @@ void CheckInternal::checkRedundantNextPrevious()
}
}
void CheckInternal::multiComparePatternError(const Token* tok, const std::string& pattern, const std::string &funcname)
{
reportError(tok, Severity::error, "multiComparePatternError",
"Bad multicompare pattern (a %cmd% must be first unless it is %or%,%op%,%cop%,%var%,%oror%) inside Token::" + funcname + "() call: \"" + pattern + "\""
);
}
void CheckInternal::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname)
{
reportError(tok, Severity::warning, "simplePatternError",

View File

@ -73,6 +73,7 @@ public:
void checkRedundantNextPrevious();
private:
void multiComparePatternError(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 missingPercentCharacterError(const Token *tok, const std::string &pattern, const std::string &funcname);
@ -81,6 +82,7 @@ private:
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckInternal c(0, settings, errorLogger);
c.multiComparePatternError(0, ";|%type%", "Match");
c.simplePatternError(0, "class {", "Match");
c.complexPatternError(0, "%type% ( )", "Match");
c.missingPercentCharacterError(0, "%num", "Match");

View File

@ -40,6 +40,7 @@ private:
TEST_CASE(unknownPattern)
TEST_CASE(redundantNextPrevious)
TEST_CASE(internalError)
TEST_CASE(invalidMultiCompare);
}
void check(const char code[]) {
@ -222,7 +223,9 @@ private:
" 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());
ASSERT_EQUALS("[test.cpp:3]: (error) Bad multicompare pattern (a %cmd% must be first unless it is %or%,%op%,%cop%,%var%,%oror%) inside Token::Match() call: \"foo|%type|bar\"\n"
"[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"
@ -312,6 +315,21 @@ private:
"};");
ASSERT_EQUALS("", errout.str());
}
void invalidMultiCompare() {
// #5310
check("void f() {\n"
" const Token *tok;\n"
" Token::Match(tok, \";|%type%\");\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Bad multicompare pattern (a %cmd% must be first unless it is %or%,%op%,%cop%,%var%,%oror%) inside Token::Match() call: \";|%type%\"\n", errout.str());
check("void f() {\n"
" const Token *tok;\n"
" Token::Match(tok, \";|%oror%\");\n"
"}");
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestInternal)