Fixed #8494 (False positive: serialization class overloads operator)
This commit is contained in:
parent
7d5a1b1248
commit
c84628c28a
|
@ -625,3 +625,26 @@ const Token *findLambdaEndToken(const Token *first)
|
|||
return tok->link();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool isLikelyStreamRead(bool cpp, const Token *op)
|
||||
{
|
||||
if (!cpp)
|
||||
return false;
|
||||
|
||||
if (Token::Match(op, ">> %name% >>|;")) {
|
||||
const Token *parent = op;
|
||||
while (Token::simpleMatch(parent->astParent(), ">>"))
|
||||
parent = parent->astParent();
|
||||
if (parent->astParent())
|
||||
return false;
|
||||
if (!parent->astOperand1() || !parent->astOperand2())
|
||||
return false;
|
||||
return (!parent->astOperand1()->valueType() || !parent->astOperand1()->valueType()->isIntegral());
|
||||
}
|
||||
|
||||
if (Token::Match(op, "& %name% ;") && !op->astParent() && op->astOperand1() && op->astOperand2() && (!op->astOperand1()->valueType() || !op->astOperand1()->valueType()->isIntegral()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,4 +121,11 @@ std::vector<const Token *> getArguments(const Token *ftok);
|
|||
*/
|
||||
const Token *findLambdaEndToken(const Token *first);
|
||||
|
||||
/**
|
||||
* do we see a likely write of rhs through overloaded operator
|
||||
* s >> x;
|
||||
* a & x;
|
||||
*/
|
||||
bool isLikelyStreamRead(bool cpp, const Token *op);
|
||||
|
||||
#endif // astutilsH
|
||||
|
|
|
@ -885,7 +885,7 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc
|
|||
|
||||
bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, Alloc alloc) const
|
||||
{
|
||||
if (alloc == NO_ALLOC && ((Token::Match(vartok->previous(), "return|delete") && vartok->strAt(1) != "=") || (vartok->strAt(-1) == "]" && vartok->linkAt(-1)->strAt(-1) == "delete")))
|
||||
if (alloc == NO_ALLOC && ((Token::Match(vartok->previous(), "return|delete %var% !!=")) || (vartok->strAt(-1) == "]" && vartok->linkAt(-1)->strAt(-1) == "delete")))
|
||||
return true;
|
||||
|
||||
// Passing variable to typeof/__alignof__
|
||||
|
@ -893,7 +893,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, Alloc al
|
|||
return false;
|
||||
|
||||
// Accessing Rvalue member using "." or "->"
|
||||
if (vartok->strAt(1) == "." && vartok->strAt(-1) != "&") {
|
||||
if (Token::Match(vartok->previous(), "!!& %var% .")) {
|
||||
// Is struct member passed to function?
|
||||
if (!pointer && Token::Match(vartok->previous(), "[,(] %name% . %name%")) {
|
||||
// TODO: there are FN currently:
|
||||
|
@ -939,20 +939,21 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, Alloc al
|
|||
if (_tokenizer->isCPP() && alloc == ARRAY && Token::Match(vartok->tokAt(-4), "& %var% =|( *"))
|
||||
return false;
|
||||
|
||||
if (_tokenizer->isCPP() && Token::Match(vartok->previous(), ">>|<<")) {
|
||||
if (isLikelyStreamRead(_tokenizer->isCPP(), vartok->previous()))
|
||||
return false;
|
||||
|
||||
if (_tokenizer->isCPP() && Token::Match(vartok->previous(), "<<")) {
|
||||
const Token* tok2 = vartok->previous();
|
||||
if (Token::simpleMatch(tok2->astOperand1(), ">>"))
|
||||
return false; // Looks like stream operator, initializes the variable
|
||||
if (Token::simpleMatch(tok2, "<<")) {
|
||||
// Looks like stream operator, but could also initialize the variable. Check lhs.
|
||||
do {
|
||||
tok2 = tok2->astOperand1();
|
||||
} while (Token::simpleMatch(tok2, "<<"));
|
||||
if (tok2 && tok2->strAt(-1) == "::")
|
||||
tok2 = tok2->previous();
|
||||
if (tok2 && (Token::simpleMatch(tok2->previous(), "std ::") || (tok2->variable() && tok2->variable()->isStlType()) || tok2->isStandardType() || tok2->isEnumType()))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Looks like stream operator, but could also initialize the variable. Check lhs.
|
||||
do {
|
||||
tok2 = tok2->astOperand1();
|
||||
} while (Token::simpleMatch(tok2, "<<"));
|
||||
if (tok2 && tok2->strAt(-1) == "::")
|
||||
tok2 = tok2->previous();
|
||||
if (tok2 && (Token::simpleMatch(tok2->previous(), "std ::") || (tok2->variable() && tok2->variable()->isStlType()) || tok2->isStandardType() || tok2->isEnumType()))
|
||||
return true;
|
||||
|
||||
const Variable *var = vartok->tokAt(-2)->variable();
|
||||
return (var && (var->typeStartToken()->isStandardType() || var->typeStartToken()->isEnumType()));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
//---------------------------------------------------------------------------
|
||||
#include "checkunusedvar.h"
|
||||
|
||||
#include "astutils.h"
|
||||
#include "errorlogger.h"
|
||||
#include "settings.h"
|
||||
#include "symboldatabase.h"
|
||||
|
@ -1127,6 +1128,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
|||
variables.use(tok->next()->varId(), tok); // use = read + write
|
||||
} else if (Token::Match(tok, "%var% >>|&") && Token::Match(tok->previous(), "[{};:]")) {
|
||||
variables.read(tok->varId(), tok);
|
||||
} else if (isLikelyStreamRead(_tokenizer->isCPP(),tok->previous())) {
|
||||
variables.use(tok->varId(), tok);
|
||||
}
|
||||
|
||||
// function parameter
|
||||
|
|
|
@ -2012,16 +2012,10 @@ static bool valueFlowForward(Token * const startToken,
|
|||
}
|
||||
|
||||
// bailout: possible assignment using >>
|
||||
if (Token::Match(tok2->previous(), ">> %name% >>|;")) {
|
||||
const Token *parent = tok2->previous();
|
||||
do {
|
||||
parent = parent->astParent();
|
||||
} while (Token::simpleMatch(parent, ">>"));
|
||||
if (!parent) {
|
||||
if (settings->debugwarnings)
|
||||
bailout(tokenlist, errorLogger, tok2, "Possible assignment of " + tok2->str() + " using >>");
|
||||
return false;
|
||||
}
|
||||
if (isLikelyStreamRead(tokenlist->isCPP(), tok2->previous())) {
|
||||
if (settings->debugwarnings)
|
||||
bailout(tokenlist, errorLogger, tok2, "Possible assignment of " + tok2->str() + " using " + tok2->strAt(-1));
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip if variable is conditionally used in ?: expression
|
||||
|
|
|
@ -473,6 +473,18 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
|
||||
}
|
||||
|
||||
// #8494 : Overloaded & operator
|
||||
checkUninitVar("void f() {\n"
|
||||
" int x;\n"
|
||||
" a & x;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
checkUninitVar("void f(int a) {\n"
|
||||
" int x;\n"
|
||||
" a & x;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
|
||||
|
||||
checkUninitVar("void a() {\n" // asm
|
||||
" int x;\n"
|
||||
" asm();\n"
|
||||
|
@ -1817,7 +1829,8 @@ private:
|
|||
{
|
||||
checkUninitVar("static int foo() {\n"
|
||||
" int ret;\n"
|
||||
" return cin >> ret;\n"
|
||||
" cin >> ret;\n"
|
||||
" return ret;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
|
@ -2183,9 +2196,8 @@ private:
|
|||
{
|
||||
const char code[] = "void f() {\n"
|
||||
" int x;\n"
|
||||
" if (i >> x) { }\n"
|
||||
" i >> x;\n"
|
||||
"}";
|
||||
|
||||
checkUninitVar(code, "test.cpp");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
|
|
|
@ -1789,6 +1789,19 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'x' is not assigned a value.\n"
|
||||
"[test.cpp:2]: (style) Variable 'y' is not assigned a value.\n", errout.str());
|
||||
|
||||
// ticket #8494
|
||||
functionVariableUsage("void f(C c) {\n"
|
||||
" int x;\n"
|
||||
" c & x;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
functionVariableUsage("void f(int c) {\n"
|
||||
" int x;\n"
|
||||
" c & x;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'x' is not assigned a value.\n", errout.str());
|
||||
}
|
||||
|
||||
void localvar33() { // ticket #2345
|
||||
|
|
|
@ -3067,6 +3067,14 @@ private:
|
|||
"}\n";
|
||||
values = tokenValues(code, "x +");
|
||||
ASSERT_EQUALS(true, values.empty());
|
||||
|
||||
// #8494 - overloaded operator &
|
||||
code = "void f() {\n"
|
||||
" int x;\n"
|
||||
" a & x;\n"
|
||||
"}";
|
||||
values = tokenValues(code, "x ; }");
|
||||
ASSERT_EQUALS(true, values.empty());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue