From c71c25ee0d3bd23aa3ab76df145fb34a2402ebe7 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 3 Mar 2025 21:49:22 +0100 Subject: [PATCH 1/2] Fix #13669 FP knownConditionTrueFalse for size variable declared in for loop --- lib/astutils.cpp | 2 +- lib/symboldatabase.cpp | 4 +++- lib/valueflow.cpp | 2 ++ test/testother.cpp | 11 +++++++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index da7b9e73234..eeac1bc1bae 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2986,7 +2986,7 @@ bool isVariablesChanged(const Token* start, const bool globalvar = std::any_of(vars.cbegin(), vars.cend(), [](const Variable* var) { return var->isGlobal(); }); - for (const Token* tok = start; tok != end; tok = tok->next()) { + for (const Token* tok = start; tok && tok != end; tok = tok->next()) { if (tok->varId() == 0 || varids.count(tok->varId()) == 0) { if (globalvar && Token::Match(tok, "%name% (")) // TODO: Is global variable really changed by function call? diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 511af3bbea0..8452a5ce664 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2295,9 +2295,11 @@ bool Variable::isUnsigned() const const Token * Variable::declEndToken() const { Token const * declEnd = typeStartToken(); - while (declEnd && !Token::Match(declEnd, "[;,)={]")) { + while (declEnd && !Token::Match(declEnd, "[;:,)={]")) { if (declEnd->link() && Token::Match(declEnd,"(|[|<")) declEnd = declEnd->link(); + if (declEnd->variable() && declEnd->variable() != this) + return nullptr; declEnd = declEnd->next(); } return declEnd; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 13547c07c7f..0e600dc8bb3 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2243,6 +2243,8 @@ struct LifetimeStore { if (!var) continue; const Token * const varDeclEndToken = var->declEndToken(); + if (!varDeclEndToken) + continue; for (const Token *tok3 = tok; tok3 && tok3 != varDeclEndToken; tok3 = tok3->previous()) { if (tok3->varId() == var->declarationId()) { update |= LifetimeStore{tok3, message, type, inconclusive} diff --git a/test/testother.cpp b/test/testother.cpp index 01f4ffbe395..e67b5f64a70 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -7820,6 +7820,17 @@ class TestOther : public TestFixture { " for (; t && t->str() == s; t = t->next());\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void f(std::string &out, const std::vector &list) {\n" // #13669 + " for (int i = 0, size = list.size(); i < size; i++) {\n" + " out += list[i];\n" + " if (size > 0 && i < (size - 2))\n" + " out += \",\";\n" + " else if (i == (size - 1))\n" + " out += \".\";\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void duplicateExpressionTernary() { // #6391 From 4d264a5822255cae48a53eefa876999f1f37031b Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 4 Mar 2025 20:41:17 +0100 Subject: [PATCH 2/2] Return declEndToken for loop variables --- lib/symboldatabase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 8452a5ce664..96e8712759a 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2295,11 +2295,11 @@ bool Variable::isUnsigned() const const Token * Variable::declEndToken() const { Token const * declEnd = typeStartToken(); + if (declEnd->tokAt(-1) && Token::simpleMatch(declEnd->tokAt(-2), "for (")) + declEnd = nameToken(); while (declEnd && !Token::Match(declEnd, "[;:,)={]")) { if (declEnd->link() && Token::Match(declEnd,"(|[|<")) declEnd = declEnd->link(); - if (declEnd->variable() && declEnd->variable() != this) - return nullptr; declEnd = declEnd->next(); } return declEnd;