diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index a8d529ab4..cc259e7e3 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1673,6 +1673,17 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all // Accessing Rvalue member using "." or "->" if (vartok->strAt(1) == "." && vartok->strAt(-1) != "&") { + // Is struct member passed to function? + if (!pointer && Token::Match(vartok->previous(), "[,(] %var% . %var%")) { + // TODO: there are FN currently: + // - should only return false if struct member is (or might be) array. + // - should only return false if function argument is (or might be) non-const pointer or reference + const Token *tok2 = vartok->next(); + while (Token::Match(tok2,". %var%")) + tok2 = tok2->tokAt(2); + if (Token::Match(tok2, "[,)]")) + return false; + } bool assignment = false; const Token* parent = vartok->astParent(); while (parent) { diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 8d777524f..666a3a4a5 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -2947,6 +2947,70 @@ private: "}\n", "test.c"); ASSERT_EQUALS("[test.c:5]: (error) Uninitialized struct member: ab.b\n", errout.str()); + checkUninitVar2("class Element {\n" + " static void f() { }\n" + "};\n" + "void test() {\n" + " Element *element; element->f();\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + + checkUninitVar2("class Element {\n" + " static void f() { }\n" + "};\n" + "void test() {\n" + " Element *element; (*element).f();\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + + checkUninitVar2("class Element {\n" + " static int v;\n" + "};\n" + "void test() {\n" + " Element *element; element->v;\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + + checkUninitVar2("class Element {\n" + " static int v;\n" + "};\n" + "void test() {\n" + " Element *element; (*element).v;\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + + checkUninitVar2("class Element {\n" + " void f() { }\n" + "};\n" + "void test() {\n" + " Element *element; element->f();\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + + checkUninitVar2("class Element {\n" + " void f() { }\n" + "};\n" + "void test() {\n" + " Element *element; (*element).f();\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + + checkUninitVar2("class Element {\n" + " int v;\n" + "};\n" + "void test() {\n" + " Element *element; element->v;\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + + checkUninitVar2("class Element {\n" + " int v;\n" + "};\n" + "void test() {\n" + " Element *element; (*element).v;\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); + checkUninitVar2("struct AB { int a; int b; };\n" // pass struct member by address "void f(void) {\n" " struct AB ab;\n" @@ -2964,6 +3028,27 @@ private: "}\n", "test.c"); ASSERT_EQUALS("", errout.str()); + { + checkUninitVar2("void f(void) {\n" + " struct AB ab;\n" + " strcpy(ab.a, STR);\n" + "}\n", "test.c"); + ASSERT_EQUALS("", errout.str()); + + checkUninitVar2("void f(void) {\n" + " struct AB ab;\n" + " strcpy(x, ab.a);\n" + "}\n", "test.c"); + TODO_ASSERT_EQUALS("error", "", errout.str()); + + checkUninitVar2("struct AB { int a; };\n" + "void f(void) {\n" + " struct AB ab;\n" + " dosomething(ab.a);\n" + "}\n", "test.c"); + TODO_ASSERT_EQUALS("error","", errout.str()); + } + checkUninitVar2("struct AB { int a; int b; };\n" "void do_something(const struct AB ab);\n" "void f(void) {\n" @@ -3163,70 +3248,6 @@ private: "}"); ASSERT_EQUALS("[test.cpp:2]: (error) Uninitialized variable: ptr3\n", errout.str()); - checkUninitVar2("class Element {\n" - " static void f() { }\n" - "};\n" - "void test() {\n" - " Element *element; element->f();\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - - checkUninitVar2("class Element {\n" - " static void f() { }\n" - "};\n" - "void test() {\n" - " Element *element; (*element).f();\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - - checkUninitVar2("class Element {\n" - " static int v;\n" - "};\n" - "void test() {\n" - " Element *element; element->v;\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - - checkUninitVar2("class Element {\n" - " static int v;\n" - "};\n" - "void test() {\n" - " Element *element; (*element).v;\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - - checkUninitVar2("class Element {\n" - " void f() { }\n" - "};\n" - "void test() {\n" - " Element *element; element->f();\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - - checkUninitVar2("class Element {\n" - " void f() { }\n" - "};\n" - "void test() {\n" - " Element *element; (*element).f();\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - - checkUninitVar2("class Element {\n" - " int v;\n" - "};\n" - "void test() {\n" - " Element *element; element->v;\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - - checkUninitVar2("class Element {\n" - " int v;\n" - "};\n" - "void test() {\n" - " Element *element; (*element).v;\n" - "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str()); - checkUninitVar2("void f() {\n" // #4911 - bad simplification => don't crash " int a;\n" " do { a=do_something() } while (a);\n"