diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 49d347293..8a194f1d4 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -643,19 +643,15 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var // variable is seen.. if (tok->varId() == var.declarationId()) { if (!membervar.empty()) { - if (Token::Match(tok, "%name% . %name% ;|%cop%") && tok->strAt(2) == membervar) + if (!suppressErrors && Token::Match(tok, "%name% . %name% ;|%cop%") && tok->strAt(2) == membervar) uninitStructMemberError(tok, tok->str() + "." + membervar); - else - return true; } // Use variable else if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) uninitvarError(tok, tok->str(), *alloc); - else - // assume that variable is assigned - return true; + return true; } else if (Token::Match(tok, "sizeof|typeof|offsetof|decltype (")) @@ -723,16 +719,20 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var return true; } - if (isMemberVariableUsage(tok, var.isPointer(), *alloc, membervar)) + if (isMemberVariableUsage(tok, var.isPointer(), *alloc, membervar)) { uninitStructMemberError(tok, tok->str() + "." + membervar); + return true; + } else if (Token::Match(tok->previous(), "[(,] %name% [,)]")) return true; } else { // Use variable - if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) + if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) { uninitvarError(tok, tok->str(), *alloc); + return true; + } else { if (tok->strAt(1) == "=") diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index e9bb95969..95f568c93 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -40,6 +40,7 @@ private: LOAD_LIB_2(settings.library, "std.cfg"); TEST_CASE(uninitvar1); + TEST_CASE(uninitvar_warn_once); // only write 1 warning at a time TEST_CASE(uninitvar_decl); // handling various types in C and C++ files TEST_CASE(uninitvar_bitop); // using uninitialized operand in bit operation TEST_CASE(uninitvar_alloc); // data is allocated but not initialized @@ -669,6 +670,15 @@ private: ASSERT_EQUALS("", errout.str()); } + void uninitvar_warn_once() { + checkUninitVar("void f() {\n" + " int x;\n" + " a = x;\n" + " b = x;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str()); + } + // Handling of unknown types. Assume they are POD in C. void uninitvar_decl() { const char code[] = "void f() {\n" @@ -1503,16 +1513,7 @@ private: " vertices[i][1][3] = 5.0;\n" " }\n" "}\n"); - // kind of regression test - there are more lines which access vertices!? - ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: vertices\n" - "[test.cpp:5]: (error) Uninitialized variable: vertices\n" - "[test.cpp:6]: (error) Uninitialized variable: vertices\n" - "[test.cpp:7]: (error) Uninitialized variable: vertices\n" - "[test.cpp:8]: (error) Uninitialized variable: vertices\n" - "[test.cpp:9]: (error) Uninitialized variable: vertices\n" - "[test.cpp:10]: (error) Uninitialized variable: vertices\n" - "[test.cpp:11]: (error) Uninitialized variable: vertices\n" - "[test.cpp:18]: (error) Uninitialized variable: vertices\n", + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: vertices\n", errout.str()); } @@ -3326,7 +3327,6 @@ private: "}"); ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized struct member: abc.a\n" "[test.cpp:5]: (error) Uninitialized struct member: abc.b\n" - "[test.cpp:6]: (error) Uninitialized struct member: abc.b\n" "[test.cpp:5]: (error) Uninitialized struct member: abc.c\n", errout.str()); // return