diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index d64c103ee..2b00279cd 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -778,10 +778,24 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const if (isMemberVariableAssignment(tok, membervar)) { bool assign = true; bool rhs = false; + // Used for tracking if an ")" is inner or outer + const Token *rpar = nullptr; for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { if (tok2->str() == "=") rhs = true; - if (tok2->str() == ";") + + // Look at inner expressions but not outer expressions + if (!rpar && tok2->str() == "(") + rpar = tok2->link(); + else if (tok2->str() == ")") { + // No rpar => this is an outer right parenthesis + if (!rpar) + break; + if (rpar == tok2) + rpar = nullptr; + } + + if (tok2->str() == ";" || (!rpar && tok2->str() == ",")) break; if (rhs && tok2->varId() == var.declarationId() && isMemberVariableUsage(tok2, var.isPointer(), alloc, membervar)) { assign = false; @@ -792,9 +806,6 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const return true; } - if (Token::Match(tok, "%name% =")) - return true; - if (isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) usetok = tok; else if (Token::Match(tok->previous(), "[(,] %name% [,)]")) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 3ed0c5d93..c06d812c8 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -3346,6 +3346,13 @@ private: "}"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized struct member: ab.a\n", errout.str()); + checkUninitVar("struct AB { int a; };\n" + "void f() {\n" + " struct AB ab;\n" + " while (x) { init(&ab); z = ab.a; }\n" + "}"); + ASSERT_EQUALS("", errout.str()); + // address of member checkUninitVar("struct AB { int a[10]; int b; };\n" "void f() {\n"