Uninitialized variables; Improved checking of loops

This commit is contained in:
Daniel Marjamäki 2021-05-20 22:56:14 +02:00
parent 8e650e4243
commit 4746d4b819
2 changed files with 45 additions and 7 deletions

View File

@ -891,6 +891,14 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va
if (tok->varId() != var.declarationId()) if (tok->varId() != var.declarationId())
continue; continue;
bool conditionalUsage = false;
for (const Token* parent = tok; parent; parent = parent->astParent()) {
if (Token::Match(parent->astParent(), "%oror%|&&|?") && astIsRHS(parent)) {
conditionalUsage = true;
break;
}
}
if (!membervar.empty()) { if (!membervar.empty()) {
if (isMemberVariableAssignment(tok, membervar)) { if (isMemberVariableAssignment(tok, membervar)) {
bool assign = true; bool assign = true;
@ -924,17 +932,22 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va
return nullptr; return nullptr;
} }
} }
if (isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) {
if (isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) if (!conditionalUsage)
return tok; return tok;
else if (Token::Match(tok->previous(), "[(,] %name% [,)]")) { if (!errorToken)
errorToken = tok;
} else if (Token::Match(tok->previous(), "[(,] %name% [,)]")) {
bailout = true; bailout = true;
return nullptr; return nullptr;
} }
} else { } else {
if (const Token *errtok = isVariableUsage(tok, var.isPointer(), alloc)) if (const Token *errtok = isVariableUsage(tok, var.isPointer(), alloc)) {
return errtok; if (!conditionalUsage)
else if (tok->strAt(1) == "=") { return errtok;
if (!errorToken)
errorToken = errtok;
} else if (tok->strAt(1) == "=") {
bool varIsUsedInRhs = false; bool varIsUsedInRhs = false;
visitAstNodes(tok->next()->astOperand2(), [&](const Token * t) { visitAstNodes(tok->next()->astOperand2(), [&](const Token * t) {
if (!t) if (!t)

View File

@ -1233,6 +1233,31 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("void foo(void) {\n"
" int a = 0;\n"
" int x;\n"
"\n"
" for (;;) {\n"
" if (!a || 12 < x) {\n" // <- x is not uninitialized
" a = 1;\n"
" x = 2;\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("void foo(void) {\n"
" int a = 0;\n"
" int x;\n"
"\n"
" for (;;) {\n"
" if (!a || 12 < x) {\n" // <- x is uninitialized
" a = 1;\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: x\n", errout.str());
// Ticket #2226: C++0x loop // Ticket #2226: C++0x loop
checkUninitVar("void f() {\n" checkUninitVar("void f() {\n"
" container c;\n" " container c;\n"