diff --git a/lib/checkio.cpp b/lib/checkio.cpp index b9866a717..de5ae6039 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -44,19 +44,15 @@ void CheckIO::checkCoutCerrMisusage() std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; - bool firstCout = false; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { - if (tok->str() == "(") - tok = tok->link(); - - if (Token::Match(tok, "std :: cout|cerr")) { - if (firstCout && tok->strAt(-1) == "<<" && tok->strAt(3) != ".") { - coutCerrMisusageError(tok, tok->strAt(2)); - firstCout = false; - } else if (tok->strAt(3) == "<<") - firstCout = true; - } else if (firstCout && tok->str() == ";") - firstCout = false; + if (Token::Match(tok, "std :: cout|cerr !!.") && tok->next()->astParent() && tok->next()->astParent()->astOperand1() == tok->next()) { + const Token* tok2 = tok->next(); + while (tok2->astParent() && tok2->astParent()->str() == "<<") { + tok2 = tok2->astParent(); + if (tok2->astOperand2() && Token::Match(tok2->astOperand2()->previous(), "std :: cout|cerr")) + coutCerrMisusageError(tok, tok2->astOperand2()->strAt(1)); + } + } } } } diff --git a/test/testio.cpp b/test/testio.cpp index 8459e31f5..53b6cc935 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -96,6 +96,12 @@ private: "}"); ASSERT_EQUALS("[test.cpp:2]: (error) Invalid usage of output stream: '<< std::cout'.\n", errout.str()); + check( + "void foo() {\n" + " std::cout << (std::cout);\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Invalid usage of output stream: '<< std::cout'.\n", errout.str()); + check( "void foo() {\n" " std::cout << \"xyz\" << std::cout;\n" @@ -121,6 +127,12 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + check( + "void foo() {\n" + " unknownObject << std::cout;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + check( "void foo() {\n" " MACRO(std::cout <<, << std::cout)\n"