From 5c488b951926df6c95b069f5120b71befc14b422 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Sat, 24 Aug 2019 04:27:47 -0500 Subject: [PATCH] Fix issue 9190: FP uninitvar for struct member (#2112) * Fix issue 9190: FP uninitvar for struct member * Add more test cases * Fix false negative --- lib/checkuninitvar.cpp | 6 ++++-- lib/token.cpp | 3 +++ lib/valueflow.cpp | 5 +++++ test/testuninitvar.cpp | 35 ++++++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 8e3bd4b16..224d6313c 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1334,9 +1334,11 @@ void CheckUninitVar::valueFlowUninit() const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings); if (v->indirect == 1 && !deref) continue; - if (Token::Match(tok->astParent(), ". %var%") && !(isLeafDot(tok) || deref)) + const bool uninitderef = deref && v->indirect == 0; + const bool isleaf = isLeafDot(tok) || uninitderef; + if (Token::Match(tok->astParent(), ". %var%") && !isleaf) continue; - if (!Token::Match(tok->astParent(), ". %name% (") && isVariableChanged(tok, mSettings, mTokenizer->isCPP())) + if (!Token::Match(tok->astParent(), ". %name% (") && !uninitderef && isVariableChanged(tok, mSettings, mTokenizer->isCPP())) continue; uninitvarError(tok, tok->str(), v->errorPath); const Token * nextTok = tok; diff --git a/lib/token.cpp b/lib/token.cpp index e27fe5637..3be98a52a 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1626,6 +1626,9 @@ void Token::printValueFlow(bool xml, std::ostream &out) const out << "lifetime=" << value.tokvalue->str(); break; } + if (value.indirect > 0) + for(int i=0;iisCPP())) { + values.remove_if(std::mem_fn(&ValueFlow::Value::isUninitValue)); + } } // Lambda function @@ -2716,6 +2720,7 @@ static bool valueFlowForward(Token * const startToken, return false; } } + } return true; } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 99e9a9e44..71793b033 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -4064,7 +4064,6 @@ private: " return ostr.str();\n" "}\n"); ASSERT_EQUALS("", errout.str()); - // #9281 valueFlowUninit("struct s {\n" " char a[20];\n" @@ -4080,6 +4079,40 @@ private: " b(&s1);\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // # 9290 + valueFlowUninit("struct A {\n" + " double x;\n" + "};\n" + "double b() {\n" + " A * c;\n" + " c->x = 42;\n" + " return c->x;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: c\n", errout.str()); + + valueFlowUninit("struct A {\n" + " double x;\n" + "};\n" + "double b() {\n" + " A c;\n" + " c.x = 42;\n" + " return c->x;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("struct A {\n" + " double x;\n" + "};\n" + "double d(A * e) {\n" + " e->x = 42;\n" + " return e->x;\n" + "}\n" + "double b() {\n" + " A c;\n" + " return d(&c);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void uninitvar_memberfunction() {