Fixed more false negatives (and recently introduced false positives) literalWithCharPtrCompare by using ValueType

Merged from LCppC.
This commit is contained in:
PKEuS 2021-02-20 13:29:14 +01:00 committed by Daniel Marjamäki
parent b1ccad5f02
commit 29a6031cea
2 changed files with 23 additions and 36 deletions

View File

@ -181,46 +181,18 @@ void CheckString::checkSuspiciousStringCompare()
else if (!Token::Match(litTok, "%char%|%num%|%str%"))
continue;
if (mTokenizer->isCPP() && (!varTok->valueType() || !varTok->valueType()->isIntegral()))
if (varTok->isLiteral())
continue;
// Pointer addition?
if (varTok->str() == "+" && mTokenizer->isC()) {
const Token * const tokens[2] = { varTok->astOperand1(), varTok->astOperand2() };
for (const Token * t : tokens) {
while (t && (t->str() == "." || t->str() == "::"))
t = t->astOperand2();
if (t && t->variable() && t->variable()->isPointer())
varTok = t;
}
}
const Token* oldVarTok = varTok;
while (varTok->str() == "*") {
if (!mTokenizer->isC() || varTok->astOperand2() != nullptr || litTok->tokType() != Token::eString)
break;
varTok = varTok->astOperand1();
}
if (mTokenizer->isC() && varTok->str() == "&")
varTok = varTok->astOperand1();
if (varTok->str() == "[")
varTok = varTok->astOperand1();
while (varTok && (varTok->str() == "." || varTok->str() == "::"))
varTok = varTok->astOperand2();
if (!varTok || !varTok->isName())
const ValueType* varType = varTok->valueType();
if (mTokenizer->isCPP() && (!varType || !varType->isIntegral()))
continue;
const Variable *var = varTok->variable();
const bool ischar(litTok->tokType() == Token::eChar);
if (litTok->tokType() == Token::eString) {
if (mTokenizer->isC() || (var && var->isArrayOrPointer()))
suspiciousStringCompareError(tok, oldVarTok->expressionString(), litTok->isLong());
} else if (ischar && var && var->isPointer()) {
suspiciousStringCompareError_char(tok, oldVarTok->expressionString());
if (mTokenizer->isC() || (varType && varType->pointer))
suspiciousStringCompareError(tok, varTok->expressionString(), litTok->isLong());
} else if (litTok->tokType() == Token::eChar && varType && varType->pointer) {
suspiciousStringCompareError_char(tok, varTok->expressionString());
}
}
}

View File

@ -317,7 +317,7 @@ private:
check("bool foo(char* c) {\n"
" return \"x\" == c+foo;\n"
"}", "test.c");
ASSERT_EQUALS("[test.c:2]: (warning) String literal compared with variable 'c'. Did you intend to use strcmp() instead?\n", errout.str());
ASSERT_EQUALS("[test.c:2]: (warning) String literal compared with variable 'c+foo'. Did you intend to use strcmp() instead?\n", errout.str());
check("bool foo(Foo c) {\n"
" return \"x\" == c.foo;\n"
@ -424,6 +424,21 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
check("bool foo(char* c) {\n"
" return c[0] == '\\0';\n"
"}");
ASSERT_EQUALS("", errout.str());
check("bool foo(char** c) {\n"
" return c[0] == '\\0';\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Char literal compared with pointer 'c[0]'. Did you intend to dereference it?\n", errout.str());
check("bool foo(char** c) {\n"
" return *c == '\\0';\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Char literal compared with pointer '*c'. Did you intend to dereference it?\n", errout.str());
check("bool foo(char c) {\n"
" return c == 0;\n"
"}");