From 8bb4b1ac0d1f88dd9f6e2e7ed3b880456827bb40 Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 18 Oct 2023 10:47:11 +0200 Subject: [PATCH 1/3] Fix #12082 FP uninitvar for assignment to array member in conditional --- lib/astutils.cpp | 2 ++ test/testuninitvar.cpp | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index f417ad704ff..df34edcac9c 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3232,6 +3232,8 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings if (!args.empty() && indirect == 0 && !addressOf) return ExprUsage::Used; } else if (ftok->isControlFlowKeyword()) { + if (Token::simpleMatch(ftok->astParent(), "(") && Token::simpleMatch(ftok->astParent()->astOperand2(), "=")) + return ExprUsage::Inconclusive; return ExprUsage::Used; } else if (ftok->str() == "{") { return indirect == 0 ? ExprUsage::Used : ExprUsage::Inconclusive; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 6e4abe8d876..924a1e3c76c 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -6288,7 +6288,14 @@ class TestUninitVar : public TestFixture { " int &q = s;\n" " foo(q);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: q\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: q\n", errout.str()); + + valueFlowUninit("int g();\n" // #12082 + "void f() {\n" + " int a[1];\n" + " while (a[0] = g()) {}\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void valueFlowUninitBreak() { // Do not show duplicate warnings about the same uninitialized value From a26266f2a09a0ae4d385953d467cf3fbc360db0c Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 18 Oct 2023 10:54:14 +0200 Subject: [PATCH 2/3] Format --- test/testuninitvar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 924a1e3c76c..1eb5c97fed9 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -6288,7 +6288,7 @@ class TestUninitVar : public TestFixture { " int &q = s;\n" " foo(q);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: q\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: q\n", errout.str()); valueFlowUninit("int g();\n" // #12082 "void f() {\n" From bb0ec922fb76ebf431865e8cac9dbcec78c65d39 Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 18 Oct 2023 13:06:30 +0200 Subject: [PATCH 3/3] Improve fix --- lib/astutils.cpp | 8 ++++---- test/testuninitvar.cpp | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index df34edcac9c..2d662062914 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3232,8 +3232,6 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings if (!args.empty() && indirect == 0 && !addressOf) return ExprUsage::Used; } else if (ftok->isControlFlowKeyword()) { - if (Token::simpleMatch(ftok->astParent(), "(") && Token::simpleMatch(ftok->astParent()->astOperand2(), "=")) - return ExprUsage::Inconclusive; return ExprUsage::Used; } else if (ftok->str() == "{") { return indirect == 0 ? ExprUsage::Used : ExprUsage::Inconclusive; @@ -3251,9 +3249,11 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings, bool cpp) { - const Token* const parent = tok->astParent(); + const Token* parent = tok->astParent(); if (indirect > 0 && parent) { - if (Token::Match(parent, "%assign%") && astIsRHS(tok)) + while (Token::simpleMatch(parent, "[") && parent->astParent()) + parent = parent->astParent(); + if (Token::Match(parent, "%assign%") && (astIsRHS(tok) || astIsLHS(parent->astOperand1()))) return ExprUsage::NotUsed; if (parent->isConstOp()) return ExprUsage::NotUsed; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 1eb5c97fed9..1045f709abc 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -6292,8 +6292,9 @@ class TestUninitVar : public TestFixture { valueFlowUninit("int g();\n" // #12082 "void f() {\n" - " int a[1];\n" + " int a[1], b[1];\n" " while (a[0] = g()) {}\n" + " if ((b[0] = g()) == 0) {}\n" "}"); ASSERT_EQUALS("", errout.str()); }