Fixed #3765 (false negative: unitialized variable)
This commit is contained in:
parent
75c8dcc664
commit
cfd960d794
|
@ -1318,13 +1318,15 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
tok = tok->next()->link();
|
tok = tok->next()->link();
|
||||||
|
|
||||||
// for/while..
|
// for/while..
|
||||||
if (Token::Match(tok, "for|while (")) {
|
if (Token::Match(tok, "for|while (") || Token::simpleMatch(tok, "do {")) {
|
||||||
|
const bool forwhile = Token::Match(tok, "for|while (");
|
||||||
|
|
||||||
// is variable initialized in for-head (don't report errors yet)?
|
// is variable initialized in for-head (don't report errors yet)?
|
||||||
if (checkIfForWhileHead(tok->next(), var, true, false, membervar))
|
if (forwhile && checkIfForWhileHead(tok->next(), var, true, false, membervar))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// goto the {
|
// goto the {
|
||||||
const Token *tok2 = tok->next()->link()->next();
|
const Token *tok2 = forwhile ? tok->next()->link()->next() : tok->next();
|
||||||
|
|
||||||
if (tok2 && tok2->str() == "{") {
|
if (tok2 && tok2->str() == "{") {
|
||||||
bool init = checkLoopBody(tok2, var, membervar, (number_of_if > 0) | suppressErrors);
|
bool init = checkLoopBody(tok2, var, membervar, (number_of_if > 0) | suppressErrors);
|
||||||
|
@ -1335,11 +1337,16 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
|
|
||||||
// is variable used in for-head?
|
// is variable used in for-head?
|
||||||
if (!suppressErrors) {
|
if (!suppressErrors) {
|
||||||
checkIfForWhileHead(tok->next(), var, false, bool(number_of_if == 0), membervar);
|
const Token *startCond = forwhile ? tok->next() : tok->next()->link()->tokAt(2);
|
||||||
|
checkIfForWhileHead(startCond, var, false, bool(number_of_if == 0), membervar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// goto "}"
|
// goto "}"
|
||||||
tok = tok2->link();
|
tok = tok2->link();
|
||||||
|
|
||||||
|
// do-while => goto ")"
|
||||||
|
if (!forwhile)
|
||||||
|
tok = tok->linkAt(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1453,8 +1460,22 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const
|
||||||
for (const Token * const end = tok->link(); tok != end; tok = tok->next()) {
|
for (const Token * const end = tok->link(); tok != end; tok = tok->next()) {
|
||||||
if (tok->varId() == var.varId()) {
|
if (tok->varId() == var.varId()) {
|
||||||
if (!membervar.empty()) {
|
if (!membervar.empty()) {
|
||||||
if (isMemberVariableAssignment(tok, membervar))
|
if (isMemberVariableAssignment(tok, membervar)) {
|
||||||
return true;
|
bool assign = true;
|
||||||
|
bool rhs = false;
|
||||||
|
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
||||||
|
if (tok2->str() == "=")
|
||||||
|
rhs = true;
|
||||||
|
if (tok2->str() == ";")
|
||||||
|
break;
|
||||||
|
if (rhs && tok2->varId() == var.varId() && isMemberVariableUsage(tok2, var.isPointer(), membervar)) {
|
||||||
|
assign = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (assign)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (isMemberVariableUsage(tok, var.isPointer(), membervar))
|
if (isMemberVariableUsage(tok, var.isPointer(), membervar))
|
||||||
usetok = tok;
|
usetok = tok;
|
||||||
|
@ -1463,8 +1484,17 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const
|
||||||
} else {
|
} else {
|
||||||
if (isVariableUsage(tok, var.isPointer(), _tokenizer->isCPP()))
|
if (isVariableUsage(tok, var.isPointer(), _tokenizer->isCPP()))
|
||||||
usetok = tok;
|
usetok = tok;
|
||||||
else
|
else if (Token::Match(tok->previous(), "[;{}] %var% =")) {
|
||||||
return true;
|
bool assign = true;
|
||||||
|
for (const Token *tok2 = tok->next(); tok2 && tok2->str() != ";"; tok2 = tok2->next()) {
|
||||||
|
if (tok2->varId() == var.varId()) {
|
||||||
|
assign = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (assign)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2795,6 +2795,13 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
checkUninitVar2("struct AB { int a; };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" struct AB ab;\n"
|
||||||
|
" while (x) { ab.a = ab.a + 1; }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized struct member: ab.a\n", errout.str());
|
||||||
|
|
||||||
// address of member
|
// address of member
|
||||||
checkUninitVar2("struct AB { int a[10]; int b; };\n"
|
checkUninitVar2("struct AB { int a[10]; int b; };\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
|
@ -2812,7 +2819,15 @@ private:
|
||||||
" x = x + 1;\n"
|
" x = x + 1;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
TODO_ASSERT_EQUALS("error", "", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
|
||||||
|
|
||||||
|
checkUninitVar2("void f() {\n"
|
||||||
|
" int x;\n"
|
||||||
|
" do {\n"
|
||||||
|
" x = x + 1;\n"
|
||||||
|
" } while (a);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
|
||||||
|
|
||||||
checkUninitVar2("void f() {\n"
|
checkUninitVar2("void f() {\n"
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
|
|
Loading…
Reference in New Issue