From 3c02291c75f6d169197fa25045e664f27bf9905c Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 11 Aug 2023 20:53:20 -0500 Subject: [PATCH 01/14] Update matching for lifetime --- lib/valueflow.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index b1e7e52a202..abe4ed67802 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2429,6 +2429,14 @@ struct ValueFlowAnalyzer : Analyzer { return settings; } + bool matchEqual(const Token* tok) const { + if (match(tok)) + return true; + if(astIsRHS(tok) && Token::simpleMatch(tok->astParent(), ".")) + return match(tok->astParent()); + return false; + } + struct ConditionState { bool dependent = true; bool unknown = true; @@ -2802,7 +2810,7 @@ struct ValueFlowAnalyzer : Analyzer { return Action::None; lifeTok = v.tokvalue; } - if (lifeTok && match(lifeTok)) { + if (lifeTok && matchEqual(lifeTok)) { Action a = Action::Read; if (isModified(tok).isModified()) a = Action::Invalid; @@ -3295,12 +3303,6 @@ struct MemberExpressionAnalyzer : SubExpressionAnalyzer { : SubExpressionAnalyzer(e, std::move(val), t, s), varname(std::move(varname)) {} - bool match(const Token* tok) const override - { - return SubExpressionAnalyzer::match(tok) || - (Token::simpleMatch(tok->astParent(), ".") && SubExpressionAnalyzer::match(tok->astParent())); - } - bool submatch(const Token* tok, bool exact) const override { if (!Token::Match(tok, ". %var%")) From 6152ef83cd2280791de818263c67bec25446be86 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 11:37:45 -0500 Subject: [PATCH 02/14] Remove modified changes --- lib/valueflow.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index abe4ed67802..45ebfb6dc42 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -7973,7 +7973,6 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings* settings) Token* start = findStartToken(var, tok->next(), &settings->library); std::map partialReads; - Analyzer::Result result; if (const Scope* scope = var->typeScope()) { if (Token::findsimplematch(scope->bodyStart, "union", scope->bodyEnd)) continue; @@ -7988,7 +7987,7 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings* settings) continue; } MemberExpressionAnalyzer analyzer(memVar.nameToken()->str(), tok, uninitValue, tokenlist, settings); - result = valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, *settings); + valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, *settings); for (auto&& p : *analyzer.partialReads) { Token* tok2 = p.first; @@ -8018,8 +8017,7 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings* settings) if (partial) continue; - if (result.terminate != Analyzer::Terminate::Modified) - valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist, settings); + valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist, settings); } } From 08aac77710bbb007912809a889769cb0f9c2f30b Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 11:38:23 -0500 Subject: [PATCH 03/14] Rename match function --- lib/valueflow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 45ebfb6dc42..2727e04c915 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2429,7 +2429,7 @@ struct ValueFlowAnalyzer : Analyzer { return settings; } - bool matchEqual(const Token* tok) const { + bool matchLifetime(const Token* tok) const { if (match(tok)) return true; if(astIsRHS(tok) && Token::simpleMatch(tok->astParent(), ".")) @@ -2810,7 +2810,7 @@ struct ValueFlowAnalyzer : Analyzer { return Action::None; lifeTok = v.tokvalue; } - if (lifeTok && matchEqual(lifeTok)) { + if (lifeTok && matchLifetime(lifeTok)) { Action a = Action::Read; if (isModified(tok).isModified()) a = Action::Invalid; From c48da15e5c33508ff1d5f08e805db4734af336b2 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 11:38:34 -0500 Subject: [PATCH 04/14] Format --- lib/valueflow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 2727e04c915..72958b1174f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2429,10 +2429,11 @@ struct ValueFlowAnalyzer : Analyzer { return settings; } - bool matchLifetime(const Token* tok) const { + bool matchLifetime(const Token* tok) const + { if (match(tok)) return true; - if(astIsRHS(tok) && Token::simpleMatch(tok->astParent(), ".")) + if (astIsRHS(tok) && Token::simpleMatch(tok->astParent(), ".")) return match(tok->astParent()); return false; } From 2cdd596ef56ceb659e14e74237d0b625bec051c6 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 11:54:05 -0500 Subject: [PATCH 05/14] Update tests --- test/testuninitvar.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index f7432725df5..c02d05108ef 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -6181,7 +6181,7 @@ class TestUninitVar : public TestFixture { " memcpy(wcsin, x, sizeof(wcsstruct));\n" // <- warning " x->wcsprm = NULL;\n" // <- no warning "}"); - ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: x.wcsprm\n", errout.str()); + ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: x\n", errout.str()); valueFlowUninit("struct wcsstruct {\n" " int *wcsprm;\n" @@ -6897,7 +6897,7 @@ class TestUninitVar : public TestFixture { " int a = ab.a;\n" " int b = ab.b;\n" "}"); - ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: ab.b\n", errout.str()); + TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: ab.b\n", "", errout.str()); // STL class member valueFlowUninit("struct A {\n" @@ -7009,7 +7009,7 @@ class TestUninitVar : public TestFixture { " memcpy(in, s, sizeof(S));\n" " s->p = NULL;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s.p\n", + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str()); valueFlowUninit("struct S {\n" // #11321 @@ -7270,7 +7270,7 @@ class TestUninitVar : public TestFixture { " A::B b;\n" " x.push_back(b);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: b.i\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: b\n", errout.str()); valueFlowUninit("struct A {\n" " struct B {\n" @@ -7294,7 +7294,7 @@ class TestUninitVar : public TestFixture { " A a;\n" " x.push_back(a);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: a.j\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: a\n", errout.str()); valueFlowUninit("struct S { struct T { int* p; } t[2]; };\n" // #11018 "void f() {\n" From b73d9cfd9537939aac73a6b62e0c060831f22d80 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 21:11:15 -0500 Subject: [PATCH 06/14] Update function --- lib/valueflow.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 72958b1174f..8ebc7a88e31 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2429,13 +2429,17 @@ struct ValueFlowAnalyzer : Analyzer { return settings; } - bool matchLifetime(const Token* tok) const + Action matchLifetime(const Token* tok) const { + if (!tok) + return Action::None; if (match(tok)) - return true; + return Action::Match; + if (Token::simpleMatch(tok, ".") && matchLifetime(tok->astOperand1()) != Action::None) + return Action::Read; if (astIsRHS(tok) && Token::simpleMatch(tok->astParent(), ".")) - return match(tok->astParent()); - return false; + return matchLifetime(tok->astParent()); + return Action::None; } struct ConditionState { @@ -2811,7 +2815,10 @@ struct ValueFlowAnalyzer : Analyzer { return Action::None; lifeTok = v.tokvalue; } - if (lifeTok && matchLifetime(lifeTok)) { + if (!lifeTok) + return Action::None; + Action la = matchLifetime(lifeTok); + if (la.matches()) { Action a = Action::Read; if (isModified(tok).isModified()) a = Action::Invalid; @@ -2820,6 +2827,8 @@ struct ValueFlowAnalyzer : Analyzer { if (inconclusiveRef && a.isModified()) return Action::Inconclusive; return a; + } else if (la.isRead()) { + return isAliasModified(tok); } return Action::None; From 7e4ee1278f339dc86df629c61bb3013bf6db9c68 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 21:12:10 -0500 Subject: [PATCH 07/14] Rename function --- lib/valueflow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 8ebc7a88e31..ef8561e36ae 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2429,16 +2429,16 @@ struct ValueFlowAnalyzer : Analyzer { return settings; } - Action matchLifetime(const Token* tok) const + Action analyzeLifetime(const Token* tok) const { if (!tok) return Action::None; if (match(tok)) return Action::Match; - if (Token::simpleMatch(tok, ".") && matchLifetime(tok->astOperand1()) != Action::None) + if (Token::simpleMatch(tok, ".") && analyzeLifetime(tok->astOperand1()) != Action::None) return Action::Read; if (astIsRHS(tok) && Token::simpleMatch(tok->astParent(), ".")) - return matchLifetime(tok->astParent()); + return analyzeLifetime(tok->astParent()); return Action::None; } @@ -2817,7 +2817,7 @@ struct ValueFlowAnalyzer : Analyzer { } if (!lifeTok) return Action::None; - Action la = matchLifetime(lifeTok); + Action la = analyzeLifetime(lifeTok); if (la.matches()) { Action a = Action::Read; if (isModified(tok).isModified()) From 5826730821fa66d1e3ae377afc4c6b1e8beccf26 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 21:55:08 -0500 Subject: [PATCH 08/14] Format --- test/testuninitvar.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index c02d05108ef..54783b8ab02 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -7009,8 +7009,7 @@ class TestUninitVar : public TestFixture { " memcpy(in, s, sizeof(S));\n" " s->p = NULL;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", - errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str()); valueFlowUninit("struct S {\n" // #11321 " int a = 0;\n" From b4610c051af179bdea4d6c87c924e1317e180ca2 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 22:26:10 -0500 Subject: [PATCH 09/14] Fix another unit test --- lib/checkuninitvar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index ca701d69723..239f1ad8d9a 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -710,7 +710,9 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var if (!suppressErrors && Token::Match(tok, "%name% . %name%") && tok->strAt(2) == membervar && Token::Match(tok->next()->astParent(), "%cop%|return|throw|?")) uninitStructMemberError(tok, tok->str() + "." + membervar); else if (mTokenizer->isCPP() && !suppressErrors && Token::Match(tok, "%name%") && Token::Match(tok->astParent(), "return|throw|?")) { - if (std::any_of(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isUninitValue))) + if (std::any_of(tok->values().cbegin(), tok->values().cend(), [](const ValueFlow::Value& v) { + return v.isUninitValue() && !v.isInconclusive(); + })) uninitStructMemberError(tok, tok->str() + "." + membervar); } } From d48845121cd11915336afd6713231a7a8bd5d34b Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Aug 2023 22:29:30 -0500 Subject: [PATCH 10/14] Add comment --- lib/valueflow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 09002fc65fd..460bae8aa07 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2429,6 +2429,7 @@ struct ValueFlowAnalyzer : Analyzer { return settings; } + // Returns Action::Match if its an exact match, return Action::Read if it partially matches the lifetime Action analyzeLifetime(const Token* tok) const { if (!tok) From 7b64167dc9adf81f2bcacb21e62e33b6cb4ffac6 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 13 Aug 2023 12:51:48 -0500 Subject: [PATCH 11/14] Fix todo test --- lib/valueflow.cpp | 7 +++++-- test/testuninitvar.cpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 460bae8aa07..2f6bd5d0f02 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -641,9 +641,10 @@ static void setTokenValue(Token* tok, } } - if (Token::simpleMatch(parent, "=") && astIsRHS(tok) && !value.isLifetimeValue()) { + if (Token::simpleMatch(parent, "=") && astIsRHS(tok)) { setTokenValue(parent, std::move(value), settings); - return; + if (!value.isUninitValue()) + return; } if (value.isContainerSizeValue() && astIsContainer(tok)) { @@ -3343,6 +3344,8 @@ static std::string lifetimeType(const Token *tok, const ValueFlow::Value *val) case ValueFlow::Value::LifetimeKind::Address: if (astIsPointer(tok)) result = "pointer"; + else if (Token::simpleMatch(tok, "=") && astIsPointer(tok->astOperand2())) + result = "pointer"; else result = "object"; break; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index e1855d5b79b..9cc8b5030cb 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -6925,7 +6925,7 @@ class TestUninitVar : public TestFixture { " int a = ab.a;\n" " int b = ab.b;\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: ab.b\n", "", errout.str()); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: ab.b\n", errout.str()); // STL class member valueFlowUninit("struct A {\n" From cfcc6aad4e1e127604f440c2417b35c082e0e8d4 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 13 Aug 2023 12:55:58 -0500 Subject: [PATCH 12/14] Remove else --- lib/valueflow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 2f6bd5d0f02..5eff1c8e58f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2829,7 +2829,8 @@ struct ValueFlowAnalyzer : Analyzer { if (inconclusiveRef && a.isModified()) return Action::Inconclusive; return a; - } else if (la.isRead()) { + } + if (la.isRead()) { return isAliasModified(tok); } return Action::None; From a73436053e4f8856523c6b5f998c5c9225f46464 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 13 Aug 2023 18:14:57 -0500 Subject: [PATCH 13/14] Remove move --- lib/valueflow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5eff1c8e58f..ac3bfd4006d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -642,7 +642,7 @@ static void setTokenValue(Token* tok, } if (Token::simpleMatch(parent, "=") && astIsRHS(tok)) { - setTokenValue(parent, std::move(value), settings); + setTokenValue(parent, value, settings); if (!value.isUninitValue()) return; } From ca9d626ce0fff1f0a3cdaa3a6d8cd5cc9eb174d7 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 13 Aug 2023 18:15:32 -0500 Subject: [PATCH 14/14] Format --- lib/valueflow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index ac3bfd4006d..9cccfa2bc88 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2829,7 +2829,7 @@ struct ValueFlowAnalyzer : Analyzer { if (inconclusiveRef && a.isModified()) return Action::Inconclusive; return a; - } + } if (la.isRead()) { return isAliasModified(tok); }