diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index ea7ed6391..309d146ae 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1783,8 +1783,19 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all if (Token::Match(vartok->previous(), "++|--|%cop%")) { if (_tokenizer->isCPP() && Token::Match(vartok->previous(), ">>|<<")) { - if (Token::Match(vartok->previous()->astOperand1(), ">>|<<")) - return false; // Looks like stream operator + const Token* tok2 = vartok->previous(); + if (Token::simpleMatch(tok2->astOperand1(), ">>")) + return false; // Looks like stream operator, initializes the variable + if (Token::simpleMatch(tok2, "<<")) { + // Looks like stream operator, but could also initialize the variable. Check lhs. + do { + tok2 = tok2->astOperand1(); + } while (Token::simpleMatch(tok2, "<<")); + if (tok2->strAt(-1) == "::") + tok2 = tok2->previous(); + if (tok2 && (Token::simpleMatch(tok2->previous(), "std ::") || (tok2->variable() && tok2->variable()->isStlType()) || tok2->isStandardType())) + return true; + } const Variable *var = vartok->tokAt(-2)->variable(); return (var && var->typeStartToken()->isStandardType()); } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 500c8d6b6..663178a62 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -443,6 +443,19 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + checkUninitVarB("void f(int b) {\n" + " int a;\n" + " std::cin >> b >> a;\n" + " return a;" + "}"); + ASSERT_EQUALS("", errout.str()); + + checkUninitVar2("void f(int i) {\n" + " int a;\n" + " i >> a;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); + checkUninitVar("int a() {\n" " int ret;\n" " int a = value >> ret;\n" @@ -480,6 +493,31 @@ private: " return a;\n" "}"); ASSERT_EQUALS("", errout.str()); + + // #4673 + checkUninitVar2("void f() {\n" + " int a;\n" + " std::cout << a;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); + + checkUninitVar2("void f(std::ostringstream& os) {\n" + " int a;\n" + " os << a;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); + + checkUninitVar2("void f() {\n" + " int a;\n" + " std::cout << 1 << a;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); + + checkUninitVar2("void f(std::ostringstream& os) {\n" + " int a;\n" + " os << 1 << a;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); } checkUninitVarB("void a() {\n" // asm