CheckInternal: Improved checking of multiCompare patterns
This commit is contained in:
parent
0877adb542
commit
62c608141d
|
@ -22,6 +22,7 @@
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
// Register this check class (by creating a static instance of it).
|
// Register this check class (by creating a static instance of it).
|
||||||
// Disabled in release builds
|
// Disabled in release builds
|
||||||
|
@ -48,6 +49,32 @@ void CheckInternal::checkTokenMatchPatterns()
|
||||||
continue;
|
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
|
// Check for signs of complex patterns
|
||||||
if (pattern.find_first_of("[|%") != std::string::npos)
|
if (pattern.find_first_of("[|%") != std::string::npos)
|
||||||
continue;
|
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)
|
void CheckInternal::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning, "simplePatternError",
|
reportError(tok, Severity::warning, "simplePatternError",
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
void checkRedundantNextPrevious();
|
void checkRedundantNextPrevious();
|
||||||
|
|
||||||
private:
|
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 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 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 {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||||
CheckInternal c(0, settings, errorLogger);
|
CheckInternal c(0, settings, errorLogger);
|
||||||
|
c.multiComparePatternError(0, ";|%type%", "Match");
|
||||||
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");
|
c.missingPercentCharacterError(0, "%num", "Match");
|
||||||
|
|
|
@ -40,6 +40,7 @@ private:
|
||||||
TEST_CASE(unknownPattern)
|
TEST_CASE(unknownPattern)
|
||||||
TEST_CASE(redundantNextPrevious)
|
TEST_CASE(redundantNextPrevious)
|
||||||
TEST_CASE(internalError)
|
TEST_CASE(internalError)
|
||||||
|
TEST_CASE(invalidMultiCompare);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(const char code[]) {
|
void check(const char code[]) {
|
||||||
|
@ -222,7 +223,9 @@ private:
|
||||||
" const Token *tok;\n"
|
" const Token *tok;\n"
|
||||||
" Token::Match(tok, \"foo|%type|bar\");\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%
|
// Make sure we don't take %or% for a broken %oror%
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
|
@ -312,6 +315,21 @@ private:
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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)
|
REGISTER_TEST(TestInternal)
|
||||||
|
|
Loading…
Reference in New Issue