Skip to content

Commit 4b9f3c6

Browse files
Fix #12188 FN uninitvar with increment of struct member (#5665)
1 parent 831aec5 commit 4b9f3c6

4 files changed

Lines changed: 57 additions & 12 deletions

File tree

lib/astutils.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3265,6 +3265,18 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
32653265
return ExprUsage::Inconclusive;
32663266
}
32673267

3268+
bool isLeafDot(const Token* tok)
3269+
{
3270+
if (!tok)
3271+
return false;
3272+
const Token * parent = tok->astParent();
3273+
if (!Token::simpleMatch(parent, "."))
3274+
return false;
3275+
if (parent->astOperand2() == tok && !Token::simpleMatch(parent->astParent(), "."))
3276+
return true;
3277+
return isLeafDot(parent);
3278+
}
3279+
32683280
ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings, bool cpp)
32693281
{
32703282
const Token* parent = tok->astParent();
@@ -3285,6 +3297,13 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings,
32853297
!parent->isUnaryOp("&") &&
32863298
!(astIsRHS(tok) && isLikelyStreamRead(cpp, parent)))
32873299
return ExprUsage::Used;
3300+
if (isLeafDot(tok)) {
3301+
const Token* op = parent->astParent();
3302+
while (Token::simpleMatch(op, "."))
3303+
op = op->astParent();
3304+
if (Token::Match(op, "%assign%|++|--") && op->str() != "=")
3305+
return ExprUsage::Used;
3306+
}
32883307
if (Token::simpleMatch(parent, "=") && astIsRHS(tok)) {
32893308
const Token* const lhs = parent->astOperand1();
32903309
if (lhs && lhs->variable() && lhs->variable()->isReference() && lhs == lhs->variable()->nameToken())

lib/astutils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ bool isCPPCast(const Token* tok);
418418

419419
bool isConstVarExpression(const Token* tok, std::function<bool(const Token*)> skipPredicate = nullptr);
420420

421+
bool isLeafDot(const Token* tok);
422+
421423
enum class ExprUsage { None, NotUsed, PassedByReference, Used, Inconclusive };
422424

423425
ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings, bool cpp);

lib/checkuninitvar.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,18 +1596,6 @@ void CheckUninitVar::uninitStructMemberError(const Token *tok, const std::string
15961596
"$symbol:" + membername + "\nUninitialized struct member: $symbol", CWE_USE_OF_UNINITIALIZED_VARIABLE, Certainty::normal);
15971597
}
15981598

1599-
static bool isLeafDot(const Token* tok)
1600-
{
1601-
if (!tok)
1602-
return false;
1603-
const Token * parent = tok->astParent();
1604-
if (!Token::simpleMatch(parent, "."))
1605-
return false;
1606-
if (parent->astOperand2() == tok && !Token::simpleMatch(parent->astParent(), "."))
1607-
return true;
1608-
return isLeafDot(parent);
1609-
}
1610-
16111599
void CheckUninitVar::valueFlowUninit()
16121600
{
16131601
logChecker("CheckUninitVar::valueFlowUninit");

test/testuninitvar.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7215,6 +7215,42 @@ class TestUninitVar : public TestFixture {
72157215
" foo(&my_st);\n"
72167216
"}\n");
72177217
ASSERT_EQUALS("", errout.str());
7218+
7219+
valueFlowUninit("struct S {\n" // #12188
7220+
" int i;\n"
7221+
" struct T { int j; } t;\n"
7222+
"};\n"
7223+
"void f() {\n"
7224+
" S s;\n"
7225+
" ++s.i;\n"
7226+
"}\n"
7227+
"void g() {\n"
7228+
" S s;\n"
7229+
" s.i--;\n"
7230+
"}\n"
7231+
"void h() {\n"
7232+
" S s;\n"
7233+
" s.i &= 3;\n"
7234+
"}\n"
7235+
"void k() {\n"
7236+
" S s;\n"
7237+
" if (++s.i < 3) {}\n"
7238+
"}\n"
7239+
"void m() {\n"
7240+
" S s;\n"
7241+
" ++s.t.j;\n"
7242+
"}\n"
7243+
"void n() {\n"
7244+
" S s;\n"
7245+
" if (s.t.j-- < 3) {}\n"
7246+
"}\n");
7247+
ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: s.i\n"
7248+
"[test.cpp:11]: (error) Uninitialized variable: s.i\n"
7249+
"[test.cpp:15]: (error) Uninitialized variable: s.i\n"
7250+
"[test.cpp:19]: (error) Uninitialized variable: s.i\n"
7251+
"[test.cpp:23]: (error) Uninitialized variable: s.t.j\n"
7252+
"[test.cpp:27]: (error) Uninitialized variable: s.t.j\n",
7253+
errout.str());
72187254
}
72197255

72207256
void uninitvar_memberfunction() {

0 commit comments

Comments
 (0)