diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 0fb48ed37..a4a7e8126 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1263,8 +1263,13 @@ const Token* CheckUninitVar::isVariableUsage(bool cpp, const Token *vartok, cons if (isLikelyStreamRead(cpp, vartok->previous())) return nullptr; - if (valueExpr->valueType() && valueExpr->valueType()->type == ValueType::Type::VOID) - return nullptr; + if (const auto* vt = valueExpr->valueType()) { + if (vt->type == ValueType::Type::VOID) + return nullptr; + // passing a char* to a stream will dereference it + if ((alloc == CTOR_CALL || alloc == ARRAY) && vt->pointer && vt->type != ValueType::Type::CHAR && vt->type != ValueType::Type::WCHAR_T) + return nullptr; + } } if (astIsRhs(derefValue) && isLikelyStreamRead(cpp, derefValue->astParent())) return nullptr; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index ac8787125..d3236b2c3 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -525,6 +525,24 @@ private: "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p\n", errout.str()); + checkUninitVar("void f() {\n" // #9696 + " int *p = new int[10];\n" + " std::cout << p << 1;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + checkUninitVar("void f() {\n" + " int i[10];\n" + " std::cout << i;\n" + " char c[10];\n" + " std::cout << c;\n" + " wchar_t w[10];\n" + " std::cout << w;\n" + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: c\n" + "[test.cpp:7]: (error) Uninitialized variable: w\n", + errout.str()); + checkUninitVar("void f() {\n" " char p[10];\n" " std::cout << p << 1;\n"