Added check to CheckInternal: detect invalid patterns like "%typ%"
Replaced some Token::Match by Token::simpleMatch (suggestions of internal checks)
This commit is contained in:
parent
524df179af
commit
e8f4dce25f
|
@ -1511,7 +1511,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func)
|
|||
else if (tok2->isName() && isMemberVar(scope, tok2))
|
||||
return(false); // TODO: Only bailout if function takes argument as non-const reference
|
||||
}
|
||||
} else if (Token::Match(tok1, "> (") && (!tok1->link() || !Token::Match(tok1->link()->previous(), "static_cast|const_cast|dynamic_cast|reinterpret_cast"))) {
|
||||
} else if (Token::simpleMatch(tok1, "> (") && (!tok1->link() || !Token::Match(tok1->link()->previous(), "static_cast|const_cast|dynamic_cast|reinterpret_cast"))) {
|
||||
return(false);
|
||||
} else if (Token::Match(tok1, "%var% . %var% (")) {
|
||||
if (!isMemberVar(scope, tok1))
|
||||
|
|
|
@ -169,6 +169,51 @@ void CheckInternal::checkMissingPercentCharacter()
|
|||
}
|
||||
}
|
||||
|
||||
void CheckInternal::checkUnknownPattern()
|
||||
{
|
||||
static std::set<std::string> knownPatterns;
|
||||
if (knownPatterns.empty()) {
|
||||
knownPatterns.insert("%any%");
|
||||
knownPatterns.insert("%var%");
|
||||
knownPatterns.insert("%type%");
|
||||
knownPatterns.insert("%num%");
|
||||
knownPatterns.insert("%bool%");
|
||||
knownPatterns.insert("%str%");
|
||||
knownPatterns.insert("%varid%");
|
||||
knownPatterns.insert("%or%");
|
||||
knownPatterns.insert("%oror%");
|
||||
knownPatterns.insert("%op%");
|
||||
}
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (!Token::simpleMatch(tok, "Token :: Match (") && !Token::simpleMatch(tok, "Token :: findmatch ("))
|
||||
continue;
|
||||
|
||||
// Get pattern string
|
||||
const Token *pattern_tok = tok->tokAt(4)->nextArgument();
|
||||
if (!pattern_tok || pattern_tok->type() != Token::eString)
|
||||
continue;
|
||||
|
||||
const std::string pattern = pattern_tok->strValue();
|
||||
bool inBrackets = false;
|
||||
|
||||
for (std::string::size_type i = 0; i < pattern.length()-1; i++) {
|
||||
if (pattern[i] == '[' && (i == 0 || pattern[i-1] == ' '))
|
||||
inBrackets = true;
|
||||
else if (pattern[i] == ']')
|
||||
inBrackets = false;
|
||||
else if (pattern[i] == '%' && pattern[i+1] != ' ' && pattern[i+1] != '|' && !inBrackets) {
|
||||
std::string::size_type end = pattern.find('%', i+1);
|
||||
if (end != std::string::npos) {
|
||||
std::string s = pattern.substr(i, end-i+1);
|
||||
if (knownPatterns.find(s) == knownPatterns.end())
|
||||
unknownPatternError(tok, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckInternal::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname)
|
||||
{
|
||||
reportError(tok, Severity::warning, "simplePatternError",
|
||||
|
@ -190,4 +235,10 @@ void CheckInternal::missingPercentCharacterError(const Token* tok, const std::st
|
|||
);
|
||||
}
|
||||
|
||||
void CheckInternal::unknownPatternError(const Token* tok, const std::string& pattern)
|
||||
{
|
||||
reportError(tok, Severity::error, "unkownPattern",
|
||||
"Unkown pattern used: \"" + pattern + "\"");
|
||||
}
|
||||
|
||||
#endif // #ifndef NDEBUG
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
checkInternal.checkTokenMatchPatterns();
|
||||
checkInternal.checkTokenSimpleMatchPatterns();
|
||||
checkInternal.checkMissingPercentCharacter();
|
||||
checkInternal.checkUnknownPattern();
|
||||
}
|
||||
|
||||
/** @brief %Check if a simple pattern is used inside Token::Match or Token::findmatch */
|
||||
|
@ -64,16 +65,21 @@ public:
|
|||
/** @brief %Check for missing % end character in Token::Match pattern */
|
||||
void checkMissingPercentCharacter();
|
||||
|
||||
/** @brief %Check for for unkown (invalid) complex patterns like "%typ%" */
|
||||
void checkUnknownPattern();
|
||||
|
||||
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 unknownPatternError(const Token* tok, const std::string& pattern);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||
CheckInternal c(0, settings, errorLogger);
|
||||
c.simplePatternError(0, "class {", "Match");
|
||||
c.complexPatternError(0, "%type% ( )", "Match");
|
||||
c.missingPercentCharacterError(0, "%num", "Match");
|
||||
c.unknownPatternError(0, "%typ");
|
||||
}
|
||||
|
||||
std::string myName() const {
|
||||
|
|
|
@ -102,7 +102,7 @@ void CheckIO::checkFileUsage()
|
|||
std::size_t varListSize = symbolDatabase->getVariableListSize();
|
||||
for (std::size_t i = 1; i < varListSize; ++i) {
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(i);
|
||||
if (!var || !var->varId() || !Token::Match(var->typeStartToken(), "FILE *"))
|
||||
if (!var || !var->varId() || !Token::simpleMatch(var->typeStartToken(), "FILE *"))
|
||||
continue;
|
||||
|
||||
if (var->isLocal()) {
|
||||
|
@ -153,7 +153,7 @@ void CheckIO::checkFileUsage()
|
|||
fileTok = tok->tokAt(-2);
|
||||
operation = Filepointer::OPEN;
|
||||
} else if (tok->str() == "rewind" || tok->str() == "fseek" || tok->str() == "fsetpos" || tok->str() == "fflush") {
|
||||
if (Token::Match(tok, "fflush ( stdin )"))
|
||||
if (Token::simpleMatch(tok, "fflush ( stdin )"))
|
||||
fflushOnInputStreamError(tok, tok->strAt(2));
|
||||
else {
|
||||
fileTok = tok->tokAt(2);
|
||||
|
|
|
@ -508,7 +508,7 @@ void CheckOther::checkSizeofForPointerSize()
|
|||
variable = tok->next();
|
||||
tokVar = tok->tokAt(5)->nextArgument();
|
||||
|
||||
} else if (Token::Match(tok, "memset (")) {
|
||||
} else if (Token::simpleMatch(tok, "memset (")) {
|
||||
variable = tok->tokAt(2);
|
||||
tokVar = variable->tokAt(2)->nextArgument();
|
||||
|
||||
|
|
|
@ -1334,12 +1334,12 @@ void CheckStl::uselessCalls()
|
|||
} else if (tok->varId() && Token::Match(tok, "%var% . swap ( %var% )") &&
|
||||
tok->varId() == tok->tokAt(4)->varId()) {
|
||||
uselessCallsSwapError(tok, tok->str());
|
||||
} else if (Token::Match(tok, ". substr (")) {
|
||||
} else if (Token::simpleMatch(tok, ". substr (")) {
|
||||
if (Token::Match(tok->tokAt(3), "0| )"))
|
||||
uselessCallsSubstrError(tok, false);
|
||||
else if (tok->strAt(3) == "0" && tok->linkAt(2)->strAt(-1) == "npos")
|
||||
uselessCallsSubstrError(tok, false);
|
||||
else if (Token::Match(tok->linkAt(2)->tokAt(-2), ", 0 )"))
|
||||
else if (Token::simpleMatch(tok->linkAt(2)->tokAt(-2), ", 0 )"))
|
||||
uselessCallsSubstrError(tok, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ private:
|
|||
TEST_CASE(simplePatternSquareBrackets)
|
||||
TEST_CASE(simplePatternAlternatives)
|
||||
TEST_CASE(missingPercentCharacter)
|
||||
TEST_CASE(unknownPattern)
|
||||
TEST_CASE(internalError)
|
||||
}
|
||||
|
||||
|
@ -212,7 +213,8 @@ 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) Missing percent end character in Token::Match() pattern: \"foo % %type % bar\"\n"
|
||||
"[test.cpp:3]: (error) Unkown pattern used: \"%type %\"\n", errout.str());
|
||||
|
||||
// Find missing % also in 'alternatives' pattern
|
||||
check("void f() {\n"
|
||||
|
@ -229,6 +231,19 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void unknownPattern() {
|
||||
check("void f() {\n"
|
||||
" Token::Match(tok, \"%typ%\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (error) Unkown pattern used: \"%typ%\"\n", errout.str());
|
||||
|
||||
// Make sure we don't take %or% for a broken %oror%
|
||||
check("void f() {\n"
|
||||
" Token::Match(tok, \"%type%\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void internalError() {
|
||||
// Make sure cppcheck does not raise an internal error of Token::Match ( Ticket #3727 )
|
||||
check("class DELPHICLASS X;\n"
|
||||
|
|
Loading…
Reference in New Issue