parent
831aec5c03
commit
4b9f3c68fb
|
@ -3265,6 +3265,18 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
|
|||
return ExprUsage::Inconclusive;
|
||||
}
|
||||
|
||||
bool isLeafDot(const Token* tok)
|
||||
{
|
||||
if (!tok)
|
||||
return false;
|
||||
const Token * parent = tok->astParent();
|
||||
if (!Token::simpleMatch(parent, "."))
|
||||
return false;
|
||||
if (parent->astOperand2() == tok && !Token::simpleMatch(parent->astParent(), "."))
|
||||
return true;
|
||||
return isLeafDot(parent);
|
||||
}
|
||||
|
||||
ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings, bool cpp)
|
||||
{
|
||||
const Token* parent = tok->astParent();
|
||||
|
@ -3285,6 +3297,13 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings,
|
|||
!parent->isUnaryOp("&") &&
|
||||
!(astIsRHS(tok) && isLikelyStreamRead(cpp, parent)))
|
||||
return ExprUsage::Used;
|
||||
if (isLeafDot(tok)) {
|
||||
const Token* op = parent->astParent();
|
||||
while (Token::simpleMatch(op, "."))
|
||||
op = op->astParent();
|
||||
if (Token::Match(op, "%assign%|++|--") && op->str() != "=")
|
||||
return ExprUsage::Used;
|
||||
}
|
||||
if (Token::simpleMatch(parent, "=") && astIsRHS(tok)) {
|
||||
const Token* const lhs = parent->astOperand1();
|
||||
if (lhs && lhs->variable() && lhs->variable()->isReference() && lhs == lhs->variable()->nameToken())
|
||||
|
|
|
@ -418,6 +418,8 @@ bool isCPPCast(const Token* tok);
|
|||
|
||||
bool isConstVarExpression(const Token* tok, std::function<bool(const Token*)> skipPredicate = nullptr);
|
||||
|
||||
bool isLeafDot(const Token* tok);
|
||||
|
||||
enum class ExprUsage { None, NotUsed, PassedByReference, Used, Inconclusive };
|
||||
|
||||
ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings, bool cpp);
|
||||
|
|
|
@ -1596,18 +1596,6 @@ void CheckUninitVar::uninitStructMemberError(const Token *tok, const std::string
|
|||
"$symbol:" + membername + "\nUninitialized struct member: $symbol", CWE_USE_OF_UNINITIALIZED_VARIABLE, Certainty::normal);
|
||||
}
|
||||
|
||||
static bool isLeafDot(const Token* tok)
|
||||
{
|
||||
if (!tok)
|
||||
return false;
|
||||
const Token * parent = tok->astParent();
|
||||
if (!Token::simpleMatch(parent, "."))
|
||||
return false;
|
||||
if (parent->astOperand2() == tok && !Token::simpleMatch(parent->astParent(), "."))
|
||||
return true;
|
||||
return isLeafDot(parent);
|
||||
}
|
||||
|
||||
void CheckUninitVar::valueFlowUninit()
|
||||
{
|
||||
logChecker("CheckUninitVar::valueFlowUninit");
|
||||
|
|
|
@ -7215,6 +7215,42 @@ private:
|
|||
" foo(&my_st);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
valueFlowUninit("struct S {\n" // #12188
|
||||
" int i;\n"
|
||||
" struct T { int j; } t;\n"
|
||||
"};\n"
|
||||
"void f() {\n"
|
||||
" S s;\n"
|
||||
" ++s.i;\n"
|
||||
"}\n"
|
||||
"void g() {\n"
|
||||
" S s;\n"
|
||||
" s.i--;\n"
|
||||
"}\n"
|
||||
"void h() {\n"
|
||||
" S s;\n"
|
||||
" s.i &= 3;\n"
|
||||
"}\n"
|
||||
"void k() {\n"
|
||||
" S s;\n"
|
||||
" if (++s.i < 3) {}\n"
|
||||
"}\n"
|
||||
"void m() {\n"
|
||||
" S s;\n"
|
||||
" ++s.t.j;\n"
|
||||
"}\n"
|
||||
"void n() {\n"
|
||||
" S s;\n"
|
||||
" if (s.t.j-- < 3) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: s.i\n"
|
||||
"[test.cpp:11]: (error) Uninitialized variable: s.i\n"
|
||||
"[test.cpp:15]: (error) Uninitialized variable: s.i\n"
|
||||
"[test.cpp:19]: (error) Uninitialized variable: s.i\n"
|
||||
"[test.cpp:23]: (error) Uninitialized variable: s.t.j\n"
|
||||
"[test.cpp:27]: (error) Uninitialized variable: s.t.j\n",
|
||||
errout.str());
|
||||
}
|
||||
|
||||
void uninitvar_memberfunction() {
|
||||
|
|
Loading…
Reference in New Issue