diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 463f09d8e..58a419fb7 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1437,6 +1437,11 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, return true; } + // bailout on ternary operator. TODO: This can be solved much better. For example, if the variable is not accessed in the branches of the ternary operator, we could just continue. + if (Token::Match(tok, "?")) { + return true; + } + if (Token::Match(tok, "return|break|continue|throw|goto")) { if (noreturn) *noreturn = true; @@ -1729,16 +1734,16 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all if (arg) { const bool address(vartok->previous()->str() == "&"); const Token *argStart = arg->typeStartToken(); - while (argStart->previous() && argStart->previous()->isName()) - argStart = argStart->previous(); - if (!address && Token::Match(argStart, "const| struct| %type% [,)]")) + if (!address && Token::Match(argStart, "struct| %type% [,)]")) return true; - if (!address && Token::Match(argStart, "const| struct| %type% %var% [,)]")) - return true; - if (Token::Match(argStart, "const %type% & %var% [,)]")) + if (!address && Token::Match(argStart, "struct| %type% %var% [,)]")) return true; if (pointer && !address && !alloc && Token::Match(argStart, "struct| %type% * %var% [,)]")) return true; + while (argStart->previous() && argStart->previous()->isName()) + argStart = argStart->previous(); + if (Token::Match(argStart, "const %type% & %var% [,)]")) + return true; if ((pointer || address) && !alloc && Token::Match(argStart, "const struct| %type% * %var% [,)]")) return true; if ((pointer || address) && Token::Match(argStart, "const %type% %var% [") && Token::Match(argStart->linkAt(3), "] [,)]")) @@ -1748,6 +1753,12 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all } else if (Token::Match(start->previous(), "if|while|for")) { // control-flow statement reading the variable "by value" return !alloc; + } else { + bool isnullbad = _settings->library.isnullargbad(start->previous(), argumentNumber + 1); + bool isuninitbad = _settings->library.isuninitargbad(start->previous(), argumentNumber + 1); + if (alloc) + return isnullbad && isuninitbad; + return isuninitbad; } } } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 73e8d974e..c5542076b 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -3832,7 +3832,7 @@ private: " FILE *f;\n" " fgets (s, n, f);\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: f\n","", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: f\n",errout.str()); checkUninitVarB("void f(char * s, int n, FILE *f) {\n" " fgets (s, n, f);\n" @@ -3993,7 +3993,7 @@ private: " int nbytes;\n" " write(STDOUT_FILENO, buf, nbytes);\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: nbytes\n", "", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: nbytes\n", errout.str()); checkUninitVarB("void no_uninitvar(char *buf, int nbytes)\n" "{\n"