diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index cfcf86e8c..83ab37508 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1671,7 +1671,7 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, bool alloc, bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool alloc) const { - if (!alloc && vartok->previous()->str() == "return") + if (!alloc && vartok->previous()->str() == "return" && vartok->strAt(1) != "=") return true; // Passing variable to typeof/__alignof__ @@ -1690,7 +1690,10 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all tok2 = tok2->tokAt(2); if (Token::Match(tok2, "[,)]")) return false; + } else if (pointer && Token::Match(vartok, "%var% . %var% (")) { + return true; } + bool assignment = false; const Token* parent = vartok->astParent(); while (parent) { @@ -1750,9 +1753,11 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all } if (Token::Match(vartok->previous(), "++|--|%cop%")) { - if (_tokenizer->isCPP() && vartok->previous()->str() == ">>") { - // assume that variable is initialized - return false; + if (_tokenizer->isCPP() && Token::Match(vartok->previous(), ">>|<<")) { + if (Token::Match(vartok->previous()->astOperand1(), ">>|<<")) + return false; // Looks like stream operator + const Variable *var = vartok->tokAt(-2)->variable(); + return (var && var->typeStartToken()->isStandardType()); } // is there something like: ; "*((&var ..expr.. =" => the variable is assigned @@ -1810,11 +1815,6 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all return true; } - if (pointer && Token::Match(vartok, "%var% . %var% (")) { - const Function *function = vartok->tokAt(2)->function(); - return (!function || !function->isStatic()); - } - if (_tokenizer->isCPP() && Token::Match(vartok->next(), "<<|>>")) { // Is this calculation done in rhs? const Token *tok = vartok; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index c06a8a044..555f71ebd 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -340,20 +340,20 @@ private: // Unknown types { - checkUninitVar("void a()\n" - "{\n" - " A ret;\n" - " return ret;\n" - "}"); + checkUninitVar2("void a()\n" + "{\n" + " A ret;\n" + " return ret;\n" + "}"); ASSERT_EQUALS("", errout.str()); - checkUninitVar("void a()\n" - "{\n" - " A ret;\n" - " return ret;\n" - "}\n", - "test.c"); - TODO_ASSERT_EQUALS("[test.c:4]: (error) Uninitialized variable: ret\n", "", errout.str()); + checkUninitVar2("void a()\n" + "{\n" + " A ret;\n" + " return ret;\n" + "}\n", + "test.c"); + ASSERT_EQUALS("[test.c:4]: (error) Uninitialized variable: ret\n", errout.str()); // #3916 - avoid false positive checkUninitVar("void f(float x) {\n" @@ -389,16 +389,6 @@ private: "}"); ASSERT_EQUALS("", errout.str()); - // #5255 - checkUninitVar("struct Element {\n" - " static void abcd() {}\n" - "};\n" - "void a() {\n" - " Element *e;\n" - " e->abcd();\n" - "}"); - ASSERT_EQUALS("", errout.str()); - // Handling >> and << { checkUninitVar("int a() {\n" @@ -1046,16 +1036,15 @@ private: " }\n" "}"); ASSERT_EQUALS("", errout.str()); - checkUninitVar("void f(int x) {\n" - " const PoolItem* pItem;\n" - " while (x > 0) {\n" - " if (*pItem != rPool)\n" - " { }\n" - " x--;\n" - " }\n" - "}"); - TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: pItem\n", - "", errout.str()); + checkUninitVar2("void f(int x) {\n" + " const PoolItem* pItem;\n" + " while (x > 0) {\n" + " if (*pItem != rPool)\n" + " { }\n" + " x--;\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: pItem\n", errout.str()); // #2231 - conditional initialization in loop.. checkUninitVar("int foo(char *a) {\n" @@ -1830,13 +1819,6 @@ private: "}"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: f\n", errout.str()); - checkUninitVar("void f()\n" - "{\n" - " int i;\n" - " x(i+2);\n" - "}"); - ASSERT_EQUALS("", errout.str()); - checkUninitVar2("void f()\n" "{\n" " int i;\n" @@ -1873,14 +1855,6 @@ private: "}"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); - checkUninitVar("int foo(int x) { return x; }\n" - "void f2()\n" - "{\n" - " int x;\n" - " foo(x);\n" - "}"); - ASSERT_EQUALS("", errout.str()); - checkUninitVar2("int foo(int x) { return x; }\n" "void f2()\n" "{\n" @@ -1997,53 +1971,45 @@ private: ASSERT_EQUALS("", errout.str()); // #2775 - uninitialized struct pointer in subfunction - checkUninitVar("void a(struct Fred *fred) {\n" - " fred->x = 0;\n" - "}\n" - "\n" - "void b() {\n" - " struct Fred *p;\n" - " a(p);\n" - "}"); - // TODO: See #2946 - TODO_ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: p\n", "", errout.str()); + checkUninitVar2("void a(struct Fred *fred) {\n" + " fred->x = 0;\n" + "}\n" + "\n" + "void b() {\n" + " struct Fred *p;\n" + " a(p);\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: p\n", errout.str()); // #2946 - FP array is initialized in subfunction - checkUninitVar("void a(char *buf) {\n" - " buf[0] = 0;\n" - "}\n" - "void b() {\n" - " char buf[10];\n" - " a(buf);\n" - " buf[1] = buf[0];\n" - "}"); + checkUninitVar2("void a(char *buf) {\n" + " buf[0] = 0;\n" + "}\n" + "void b() {\n" + " char buf[10];\n" + " a(buf);\n" + " buf[1] = buf[0];\n" + "}"); ASSERT_EQUALS("", errout.str()); // #3159 - initialization by function - checkUninitVar("static int isnumber(const char *arg) {\n" - " char *p;\n" - " return strtod(arg, &p) != 0 || p != arg;\n" - "}"); + checkUninitVar2("static int isnumber(const char *arg) {\n" + " char *p;\n" + " return strtod(arg, &p) != 0 || p != arg;\n" + "}"); ASSERT_EQUALS("", errout.str()); - checkUninitVar("static int isnumber(const char *arg) {\n" - " char *p;\n" - " return strtod(&arg) != 0 || p != arg;\n" - "}"); - TODO_ASSERT_EQUALS("error", "", errout.str()); + checkUninitVar2("static int isnumber(const char *arg) {\n" + " char *p;\n" + " return strtod(&arg) != 0 || p != arg;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: p\n", errout.str()); } // valid and invalid use of 'int a(int x) { return x + x; }' void func_uninit_var() { const std::string funca("int a(int x) { return x + x; }"); - checkUninitVar((funca + - "void b() {\n" - " int x;\n" - " a(x);\n" - "}").c_str()); - ASSERT_EQUALS("", errout.str()); - checkUninitVar2((funca + "void b() {\n" " int x;\n" @@ -2065,20 +2031,14 @@ private: const std::string funca("void a(int *p) { *p = 0; }"); // ok - initialized pointer - checkUninitVar((funca + - "void b() {\n" - " int buf[10];\n" - " a(buf);\n" - "}").c_str()); + checkUninitVar2((funca + + "void b() {\n" + " int buf[10];\n" + " a(buf);\n" + "}").c_str()); ASSERT_EQUALS("", errout.str()); // not ok - uninitialized pointer - checkUninitVar((funca + - "void b() {\n" - " int *p;\n" - " a(p);\n" - "}").c_str()); - ASSERT_EQUALS("", errout.str()); checkUninitVar2((funca + "void b() {\n" " int *p;\n"