diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 388ed4964..11daa14dd 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -891,6 +891,14 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va if (tok->varId() != var.declarationId()) 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 (isMemberVariableAssignment(tok, membervar)) { bool assign = true; @@ -924,17 +932,22 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va return nullptr; } } - - if (isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) - return tok; - else if (Token::Match(tok->previous(), "[(,] %name% [,)]")) { + if (isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) { + if (!conditionalUsage) + return tok; + if (!errorToken) + errorToken = tok; + } else if (Token::Match(tok->previous(), "[(,] %name% [,)]")) { bailout = true; return nullptr; } } else { - if (const Token *errtok = isVariableUsage(tok, var.isPointer(), alloc)) - return errtok; - else if (tok->strAt(1) == "=") { + if (const Token *errtok = isVariableUsage(tok, var.isPointer(), alloc)) { + if (!conditionalUsage) + return errtok; + if (!errorToken) + errorToken = errtok; + } else if (tok->strAt(1) == "=") { bool varIsUsedInRhs = false; visitAstNodes(tok->next()->astOperand2(), [&](const Token * t) { if (!t) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 0ec8e16c6..80afd7b30 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -1233,6 +1233,31 @@ private: "}"); 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 checkUninitVar("void f() {\n" " container c;\n"