diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index c2a215b66..9aa85776d 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1841,8 +1841,34 @@ bool CheckUninitVar::isMemberVariableAssignment(const Token *tok, const std::str return true; } else if (tok->strAt(1) == "=") return true; - else if (tok->strAt(-1) == "&") + else if (tok->strAt(-1) == "&") { + if (Token::Match(tok->tokAt(-2), "[(,] & %var%")) { + // locate start parentheses in function call.. + unsigned int argumentNumber = 0; + const Token *ftok = tok; + while (ftok && !Token::Match(ftok, "[;{}(]")) { + if (ftok->str() == ")") + ftok = ftok->link(); + else if (ftok->str() == ",") + ++argumentNumber; + ftok = ftok->previous(); + } + + // is this a function call? + ftok = ftok ? ftok->previous() : NULL; + if (Token::Match(ftok, "%var% (")) { + // check how function handle uninitialized data arguments.. + const Function *function = ftok->function(); + const Variable *arg = function ? function->getArgumentVar(argumentNumber) : NULL; + const Token *argStart = arg ? arg->typeStartToken() : NULL; + while (argStart && argStart->previous() && argStart->previous()->isName()) + argStart = argStart->previous(); + if (Token::Match(argStart, "const struct| %type% * const| %var% [,)]")) + return false; + } + } return true; + } return false; } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index f99897364..726e1119d 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -3000,6 +3000,15 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + checkUninitVar2("struct ABC { int a; int b; int c; };\n" + "void foo(int x, const struct ABC *abc);\n" + "void bar(void) {\n" + " struct ABC abc;\n" + " foo(123, &abc);\n" + " return abc.b;\n" + "}"); + ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized struct member: abc.b\n", errout.str()); + // return checkUninitVar2("struct AB { int a; int b; };\n" "void f(void) {\n"