diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index d6e88835a..84d57b0fc 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1069,11 +1069,11 @@ void CheckUninitVar::checkScope(const Scope* scope) continue; if (Token::Match(i->nameToken(), "%name% =")) { // Variable is initialized, but Rhs might be not - checkRhs(i->nameToken(), *i, NO_ALLOC, ""); + checkRhs(i->nameToken(), *i, NO_ALLOC, 0U, ""); continue; } if (Token::Match(i->nameToken(), "%name% ) (") && Token::simpleMatch(i->nameToken()->linkAt(2), ") =")) { // Function pointer is initialized, but Rhs might be not - checkRhs(i->nameToken()->linkAt(2)->next(), *i, NO_ALLOC, ""); + checkRhs(i->nameToken()->linkAt(2)->next(), *i, NO_ALLOC, 0U, ""); continue; } @@ -1463,12 +1463,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var); const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var); const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0); - if (err) { - if (*alloc != NO_ALLOC) - uninitdataError(tok, var.nameToken()->str()); - else - uninitvarError(tok, var.nameToken()->str()); - } + if (err) + uninitvarError(tok, var.nameToken()->str(), *alloc); // Todo: skip expression if there is no error return true; @@ -1490,10 +1486,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var // Use variable else if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) { - if (*alloc != NO_ALLOC) - uninitdataError(tok, tok->str()); - else - uninitvarError(tok, tok->str()); + uninitvarError(tok, tok->str(), *alloc); + return true; } else @@ -1510,12 +1504,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var); const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var); const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0); - if (err) { - if (*alloc != NO_ALLOC) - uninitdataError(tok, var.nameToken()->str()); - else - uninitvarError(tok, var.nameToken()->str()); - } + if (err) + uninitvarError(tok, var.nameToken()->str(), *alloc); return true; } @@ -1545,7 +1535,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var if (!membervar.empty()) { if (isMemberVariableAssignment(tok, membervar)) { - checkRhs(tok, var, *alloc, membervar); + checkRhs(tok, var, *alloc, number_of_if, membervar); return true; } @@ -1558,15 +1548,13 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var } else { // Use variable if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) { - if (*alloc != NO_ALLOC) - uninitdataError(tok, tok->str()); - else - uninitvarError(tok, tok->str()); + uninitvarError(tok, tok->str(), *alloc); + return true; } else { if (tok->strAt(1) == "=") - checkRhs(tok, var, *alloc, ""); + checkRhs(tok, var, *alloc, number_of_if, ""); // assume that variable is assigned return true; @@ -1599,7 +1587,7 @@ bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Va if (isVariableUsage(tok, var.isPointer(), alloc)) { if (suppressErrors) continue; - uninitvarError(tok, tok->str()); + uninitvarError(tok, tok->str(), alloc); } return true; } @@ -1684,7 +1672,7 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const if (!suppressErrors && usetok) { if (membervar.empty()) - uninitvarError(usetok, usetok->str()); + uninitvarError(usetok, usetok->str(), alloc); else uninitStructMemberError(usetok, usetok->str() + "." + membervar); return true; @@ -1693,7 +1681,7 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const return false; } -void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc, const std::string &membervar) +void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc, unsigned int number_of_if, const std::string &membervar) { bool rhs = false; unsigned int indent = 0; @@ -1702,7 +1690,7 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc rhs = true; else if (rhs && tok->varId() == var.declarationId()) { if (membervar.empty() && isVariableUsage(tok, var.isPointer(), alloc)) - uninitvarError(tok, tok->str()); + uninitvarError(tok, tok->str(), alloc); else if (!membervar.empty() && isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) uninitStructMemberError(tok, tok->str() + "." + membervar); @@ -1714,6 +1702,13 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc if (indent == 0) break; --indent; + } else if (tok->str() == "?" && tok->astOperand2()) { + const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var); + const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var); + const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0); + if (err) + uninitvarError(tok, var.nameToken()->str(), alloc); + break; } else if (Token::simpleMatch(tok, "sizeof (")) tok = tok->next()->link(); } diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index a4b6ef12b..485ff2fca 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -61,7 +61,7 @@ public: bool checkScopeForVariable(const Token *tok, const Variable& var, bool* const possibleInit, bool* const noreturn, Alloc* const alloc, const std::string &membervar); bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, Alloc alloc, const std::string &membervar); bool checkLoopBody(const Token *tok, const Variable& var, const Alloc alloc, const std::string &membervar, const bool suppressErrors); - void checkRhs(const Token *tok, const Variable &var, Alloc alloc, const std::string &membervar); + void checkRhs(const Token *tok, const Variable &var, Alloc alloc, unsigned int number_of_if, const std::string &membervar); bool isVariableUsage(const Token *vartok, bool ispointer, Alloc alloc) const; int isFunctionParUsage(const Token *vartok, bool ispointer, Alloc alloc) const; bool isMemberVariableAssignment(const Token *tok, const std::string &membervar) const; @@ -95,6 +95,12 @@ public: void uninitstringError(const Token *tok, const std::string &varname, bool strncpy_); void uninitdataError(const Token *tok, const std::string &varname); void uninitvarError(const Token *tok, const std::string &varname); + void uninitvarError(const Token *tok, const std::string &varname, Alloc alloc) { + if (alloc == NO_ALLOC) + uninitvarError(tok, varname); + else + uninitdataError(tok, varname); + } void uninitStructMemberError(const Token *tok, const std::string &membername); /** testrunner: (don't abort() when assertion fails, just write error message) */ diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index ae590c9f1..3dbbd7e5e 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -603,11 +603,11 @@ private: "}"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c\n", errout.str()); - checkUninitVar("void f()\n" - "{\n" - " char *s = malloc(100);\n" - " *s += 10;\n" - "}"); + checkUninitVar2("void f()\n" + "{\n" + " char *s = malloc(100);\n" + " *s += 10;\n" + "}"); ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str()); checkUninitVar("void f()\n" @@ -919,12 +919,11 @@ private: ASSERT_EQUALS("", errout.str()); // ? : - checkUninitVar("static void foo(int v)\n" - "{\n" - " int x;\n" - " x = v <= 0 ? -1 : x;\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str()); + checkUninitVar2("static void foo(int v) {\n" + " int x;\n" + " x = v <= 0 ? -1 : x;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str()); checkUninitVarB("void foo()\n" "{\n" @@ -1723,19 +1722,17 @@ private: void uninitvar_return() { - checkUninitVar("static int foo()\n" - "{\n" - " int ret;\n" - " return ret;\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str()); + checkUninitVar2("static int foo() {\n" + " int ret;\n" + " return ret;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str()); - checkUninitVar("static int foo()\n" - "{\n" - " int ret;\n" - " return ret+5;\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str()); + checkUninitVar2("static int foo() {\n" + " int ret;\n" + " return ret+5;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str()); checkUninitVarB("static int foo() {\n" " int ret;\n" @@ -1750,16 +1747,16 @@ private: "}"); ASSERT_EQUALS("", errout.str()); - checkUninitVar("static int foo() {\n" - " int ret;\n" - " return cin >> ret;\n" - "}\n", "test.c"); + checkUninitVar2("static int foo() {\n" + " int ret;\n" + " return cin >> ret;\n" + "}\n", "test.c"); ASSERT_EQUALS("[test.c:3]: (error) Uninitialized variable: ret\n", errout.str()); } // Ticket #6341- False negative { - checkUninitVarB("wchar_t f() { int i; return btowc(i); }"); + checkUninitVar2("wchar_t f() { int i; return btowc(i); }"); ASSERT_EQUALS("[test.cpp:1]: (error) Uninitialized variable: i\n", errout.str()); checkUninitVarB("wchar_t f(int i) { return btowc(i); }"); @@ -1780,8 +1777,7 @@ private: // Ticket #5412 - False negative { - checkUninitVarB("void f(bool b)\n" - "{\n" + checkUninitVar2("void f(bool b) {\n" " double f;\n" " if (b) { }\n" " else {\n" @@ -1789,11 +1785,10 @@ private: " }\n" " printf (\"%f\",f);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:8]: (error) Uninitialized variable: f\n", errout.str()); + ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: f\n", errout.str()); // Check for potential FP - checkUninitVarB("void f(bool b)\n" - "{\n" + checkUninitVarB("void f(bool b) {\n" " double f;\n" " if (b) { f = 1.0 }\n" " else {\n" @@ -1805,10 +1800,10 @@ private: } // Ticket #2146 - False negative - checkUninitVar("int f(int x) {\n" - " int y;\n" - " return x ? 1 : y;\n" - "}"); + checkUninitVar2("int f(int x) {\n" + " int y;\n" + " return x ? 1 : y;\n" + "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: y\n", errout.str()); // Ticket #3106 - False positive @@ -1819,10 +1814,10 @@ private: "}"); ASSERT_EQUALS("", errout.str()); - checkUninitVar("int f() {\n" - " int i;\n" - " return x() ? i : 0;\n" - "}"); + checkUninitVar2("int f() {\n" + " int i;\n" + " return x() ? i : 0;\n" + "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: i\n", errout.str()); }