diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 3d7e88795..06d2d4a5c 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -218,6 +218,17 @@ static bool isVariableUsed(const Token *tok, const Variable& var) return false; if (tok->isConstOp()) return isVariableUsed(tok->astOperand1(),var) || isVariableUsed(tok->astOperand2(),var); + if (var.isArray()) { + const Token *parent = tok->astParent(); + while (Token::Match(parent, "[?:]")) + parent = parent->astParent(); + // no dereference, then array is not "used" + if (!Token::Match(parent, "*|[")) + return false; + const Token *parent2 = parent->astParent(); + // TODO: handle function calls. There is a TODO assertion in TestUninitVar::uninitvar_arrays + return !parent2 || parent2->isConstOp() || (parent2->str() == "=" && parent2->astOperand2() == parent); + } return (tok->varId() == var.declarationId()); } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index c61f97435..ce7482d14 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -1254,6 +1254,26 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + // array usage in ?: (tests that the isVariableUsed() works) + checkUninitVar("void f() {\n" + " char a[10], *p;\n" + " p = c?a:0;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + checkUninitVar("void f() {\n" + " char a[10], c;\n" + " c = *(x?a:0);\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); + + checkUninitVar("void f() {\n" + " char a[10], c;\n" + " strcpy(dest, x?a:\"\");\n" + "}"); + TODO_ASSERT_EQUALS("error", "", errout.str()); + + // passing array to library functions checkUninitVar("void f()\n" "{\n" " char c[50] = \"\";\n"