Fixed #8999 (False positive uninitvar related to casting)

This commit is contained in:
Daniel Marjamäki 2019-02-27 17:58:25 +01:00
parent fe402498e1
commit 80143725dd
2 changed files with 23 additions and 11 deletions

View File

@ -925,20 +925,24 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, Alloc al
// Accessing Rvalue member using "." or "->" // Accessing Rvalue member using "." or "->"
if (Token::Match(vartok->previous(), "!!& %var% .")) { if (Token::Match(vartok->previous(), "!!& %var% .")) {
// Is struct member passed to function? // Is struct member passed to function?
if (!pointer && Token::Match(vartok->previous(), "[,(] %name% . %name%")) { if (!pointer) {
// TODO: there are FN currently: // TODO: there are FN currently:
// - should only return false if struct member is (or might be) array. // - 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 // - should only return false if function argument is (or might be) non-const pointer or reference
const Token *tok2 = vartok->next(); bool unknown = false;
do { const Token *possibleParent = getAstParentSkipPossibleCastAndAddressOf(vartok, &unknown);
tok2 = tok2->tokAt(2); if (Token::Match(possibleParent, "[(,]")) {
} while (Token::Match(tok2, ". %name%")); if (unknown)
if (Token::Match(tok2, "[,)]")) return false; // TODO: output some info message?
return false; const int use = isFunctionParUsage(vartok, pointer, alloc);
} else if (pointer && alloc != CTOR_CALL && Token::Match(vartok, "%name% . %name% (")) { if (use >= 0)
return true; return (use>0);
}
} }
if (pointer && alloc != CTOR_CALL && Token::Match(vartok, "%name% . %name% ("))
return true;
bool assignment = false; bool assignment = false;
const Token* parent = vartok->astParent(); const Token* parent = vartok->astParent();
while (parent) { while (parent) {

View File

@ -3053,7 +3053,8 @@ private:
" struct AB ab;\n" " struct AB ab;\n"
" do_something(ab.a);\n" " do_something(ab.a);\n"
"}\n", "test.c"); "}\n", "test.c");
ASSERT_EQUALS("[test.c:5]: (error) Uninitialized struct member: ab.a\n", errout.str()); ASSERT_EQUALS("[test.c:5]: (error) Uninitialized variable: ab\n"
"[test.c:5]: (error) Uninitialized struct member: ab.a\n", errout.str());
checkUninitVar("struct AB { int a; int b; };\n" checkUninitVar("struct AB { int a; int b; };\n"
"void do_something(const struct AB &ab) { a = ab.a; }\n" "void do_something(const struct AB &ab) { a = ab.a; }\n"
@ -3183,12 +3184,19 @@ private:
"}\n", "test.c"); "}\n", "test.c");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("struct AB { unsigned char a[10]; };\n" // #8999 - cast
"void f(void) {\n"
" struct AB ab;\n"
" strcpy((char *)ab.a, STR);\n"
"}\n", "test.c");
ASSERT_EQUALS("", errout.str());
checkUninitVar("struct AB { char a[10]; };\n" checkUninitVar("struct AB { char a[10]; };\n"
"void f(void) {\n" "void f(void) {\n"
" struct AB ab;\n" " struct AB ab;\n"
" strcpy(x, ab.a);\n" " strcpy(x, ab.a);\n"
"}\n", "test.c"); "}\n", "test.c");
TODO_ASSERT_EQUALS("error", "", errout.str()); ASSERT_EQUALS("[test.c:4]: (error) Uninitialized variable: ab\n", errout.str());
checkUninitVar("struct AB { int a; };\n" checkUninitVar("struct AB { int a; };\n"
"void f(void) {\n" "void f(void) {\n"