From 9291421840800a378cc972cca225ddeea4aa5e75 Mon Sep 17 00:00:00 2001
From: chrchr-github <78114321+chrchr-github@users.noreply.github.com>
Date: Sat, 4 Mar 2023 11:58:12 +0100
Subject: [PATCH] Fix #11595 FN useStlAlgorithm with complex condition (#4848)
---
cfg/std.cfg | 10 +++++-----
gui/threadresult.cpp | 8 +++-----
lib/checkstl.cpp | 24 ++++++++++++------------
lib/settings.h | 9 +++------
lib/token.cpp | 8 +++-----
test/teststl.cpp | 10 ++++++++++
6 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/cfg/std.cfg b/cfg/std.cfg
index 1e2544afb..9b7b03b9d 100644
--- a/cfg/std.cfg
+++ b/cfg/std.cfg
@@ -6895,19 +6895,19 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
-
+
-
+
-
+
-
+
-
+
diff --git a/gui/threadresult.cpp b/gui/threadresult.cpp
index 4d2d243db..52dfe4d96 100644
--- a/gui/threadresult.cpp
+++ b/gui/threadresult.cpp
@@ -114,11 +114,9 @@ void ThreadResult::setProject(const ImportProject &prj)
// Determine the total size of all of the files to check, so that we can
// show an accurate progress estimate
- quint64 sizeOfFiles = 0;
- for (const ImportProject::FileSettings& fs : prj.fileSettings) {
- sizeOfFiles += QFile(QString::fromStdString(fs.filename)).size();
- }
- mMaxProgress = sizeOfFiles;
+ mMaxProgress = std::accumulate(prj.fileSettings.begin(), prj.fileSettings.end(), quint64{ 0 }, [](quint64 v, const ImportProject::FileSettings& fs) {
+ return v + QFile(QString::fromStdString(fs.filename)).size();
+ });
}
void ThreadResult::clearFiles()
diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp
index 83ae5fb53..027f22f8c 100644
--- a/lib/checkstl.cpp
+++ b/lib/checkstl.cpp
@@ -2518,7 +2518,7 @@ static const Token *singleStatement(const Token *start)
return endStatement;
}
-static const Token *singleAssignInScope(const Token *start, nonneg int varid, bool &input)
+static const Token *singleAssignInScope(const Token *start, nonneg int varid, bool &input, const Settings* settings)
{
const Token *endStatement = singleStatement(start);
if (!endStatement)
@@ -2526,15 +2526,15 @@ static const Token *singleAssignInScope(const Token *start, nonneg int varid, bo
if (!Token::Match(start->next(), "%var% %assign%"))
return nullptr;
const Token *assignTok = start->tokAt(2);
- if (isVariableChanged(assignTok->next(), endStatement, assignTok->astOperand1()->varId(), false, nullptr, true))
+ if (isVariableChanged(assignTok->next(), endStatement, assignTok->astOperand1()->varId(), /*globalvar*/ false, settings, /*cpp*/ true))
return nullptr;
- if (isVariableChanged(assignTok->next(), endStatement, varid, false, nullptr, true))
+ if (isVariableChanged(assignTok->next(), endStatement, varid, /*globalvar*/ false, settings, /*cpp*/ true))
return nullptr;
input = Token::findmatch(assignTok->next(), "%varid%", endStatement, varid) || !Token::Match(start->next(), "%var% =");
return assignTok;
}
-static const Token *singleMemberCallInScope(const Token *start, nonneg int varid, bool &input)
+static const Token *singleMemberCallInScope(const Token *start, nonneg int varid, bool &input, const Settings* settings)
{
if (start->str() != "{")
return nullptr;
@@ -2551,7 +2551,7 @@ static const Token *singleMemberCallInScope(const Token *start, nonneg int varid
if (!Token::findmatch(dotTok->tokAt(2), "%varid%", endStatement, varid))
return nullptr;
input = Token::Match(start->next(), "%var% . %name% ( %varid% )", varid);
- if (isVariableChanged(dotTok->next(), endStatement, dotTok->astOperand1()->varId(), false, nullptr, true))
+ if (isVariableChanged(dotTok->next(), endStatement, dotTok->astOperand1()->varId(), /*globalvar*/ false, settings, /*cpp*/ true))
return nullptr;
return dotTok;
}
@@ -2571,7 +2571,7 @@ static const Token *singleIncrementInScope(const Token *start, nonneg int varid,
return varTok;
}
-static const Token *singleConditionalInScope(const Token *start, nonneg int varid)
+static const Token *singleConditionalInScope(const Token *start, nonneg int varid, const Settings* settings)
{
if (start->str() != "{")
return nullptr;
@@ -2588,7 +2588,7 @@ static const Token *singleConditionalInScope(const Token *start, nonneg int vari
return nullptr;
if (!Token::findmatch(start, "%varid%", bodyTok, varid))
return nullptr;
- if (isVariableChanged(start, bodyTok, varid, false, nullptr, true))
+ if (isVariableChanged(start, bodyTok, varid, /*globalvar*/ false, settings, /*cpp*/ true))
return nullptr;
return bodyTok;
}
@@ -2721,7 +2721,7 @@ void CheckStl::useStlAlgorithm()
// Check for single assignment
bool useLoopVarInAssign;
- const Token *assignTok = singleAssignInScope(bodyTok, loopVar->varId(), useLoopVarInAssign);
+ const Token *assignTok = singleAssignInScope(bodyTok, loopVar->varId(), useLoopVarInAssign, mSettings);
if (assignTok) {
if (!checkAssignee(assignTok->astOperand1()))
continue;
@@ -2751,7 +2751,7 @@ void CheckStl::useStlAlgorithm()
}
// Check for container calls
bool useLoopVarInMemCall;
- const Token *memberAccessTok = singleMemberCallInScope(bodyTok, loopVar->varId(), useLoopVarInMemCall);
+ const Token *memberAccessTok = singleMemberCallInScope(bodyTok, loopVar->varId(), useLoopVarInMemCall, mSettings);
if (memberAccessTok && !isIteratorLoop) {
const Token *memberCallTok = memberAccessTok->astOperand2();
const int contVarId = memberAccessTok->astOperand1()->varId();
@@ -2784,10 +2784,10 @@ void CheckStl::useStlAlgorithm()
}
// Check for conditionals
- const Token *condBodyTok = singleConditionalInScope(bodyTok, loopVar->varId());
+ const Token *condBodyTok = singleConditionalInScope(bodyTok, loopVar->varId(), mSettings);
if (condBodyTok) {
// Check for single assign
- assignTok = singleAssignInScope(condBodyTok, loopVar->varId(), useLoopVarInAssign);
+ assignTok = singleAssignInScope(condBodyTok, loopVar->varId(), useLoopVarInAssign, mSettings);
if (assignTok) {
if (!checkAssignee(assignTok->astOperand1()))
continue;
@@ -2815,7 +2815,7 @@ void CheckStl::useStlAlgorithm()
}
// Check for container call
- memberAccessTok = singleMemberCallInScope(condBodyTok, loopVar->varId(), useLoopVarInMemCall);
+ memberAccessTok = singleMemberCallInScope(condBodyTok, loopVar->varId(), useLoopVarInMemCall, mSettings);
if (memberAccessTok) {
const Token *memberCallTok = memberAccessTok->astOperand2();
const int contVarId = memberAccessTok->astOperand1()->varId();
diff --git a/lib/settings.h b/lib/settings.h
index b1dadd732..56d997659 100644
--- a/lib/settings.h
+++ b/lib/settings.h
@@ -390,12 +390,9 @@ public:
* @return true for the file to be excluded.
*/
bool configurationExcluded(const std::string &file) const {
- for (const std::string & configExcludePath : configExcludePaths) {
- if (file.length()>=configExcludePath.length() && file.compare(0,configExcludePath.length(),configExcludePath)==0) {
- return true;
- }
- }
- return false;
+ return std::any_of(configExcludePaths.begin(), configExcludePaths.end(), [&file](const std::string& path) {
+ return file.length() >= path.length() && file.compare(0, path.length(), path) == 0;
+ });
}
/**
diff --git a/lib/token.cpp b/lib/token.cpp
index c27c4e9fc..01a65e2c5 100644
--- a/lib/token.cpp
+++ b/lib/token.cpp
@@ -232,11 +232,9 @@ bool Token::isUpperCaseName() const
{
if (!isName())
return false;
- for (const char i : mStr) {
- if (std::islower(i))
- return false;
- }
- return true;
+ return std::none_of(mStr.begin(), mStr.end(), [](char c) {
+ return std::islower(c);
+ });
}
void Token::concatStr(std::string const& b)
diff --git a/test/teststl.cpp b/test/teststl.cpp
index ebd09f363..c519c184c 100644
--- a/test/teststl.cpp
+++ b/test/teststl.cpp
@@ -5284,6 +5284,16 @@ private:
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (style) Consider using std::find_if algorithm instead of a raw loop.\n", errout.str());
+
+ check("bool f(const std::set& set, const std::string& f) {\n" // #11595
+ " for (const std::string& s : set) {\n"
+ " if (f.length() >= s.length() && f.compare(0, s.length(), s) == 0) {\n"
+ " return true;\n"
+ " }\n"
+ " }\n"
+ " return false;\n"
+ "}\n");
+ ASSERT_EQUALS("[test.cpp:3]: (style) Consider using std::any_of algorithm instead of a raw loop.\n", errout.str());
}
void loopAlgoMinMax() {