Fix 11605: FN useStlAlgo with multiple conditions (#4873)
This commit is contained in:
parent
b0e8ed3117
commit
9351eddbca
|
@ -1981,17 +1981,18 @@ bool isUniqueExpression(const Token* tok)
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return true;
|
return true;
|
||||||
const std::string returnType = fun->retType ? fun->retType->name() : fun->retDef->stringifyList(fun->tokenDef);
|
const std::string returnType = fun->retType ? fun->retType->name() : fun->retDef->stringifyList(fun->tokenDef);
|
||||||
for (const Function& f:scope->functionList) {
|
if (!std::all_of(scope->functionList.begin(), scope->functionList.end(), [&](const Function& f) {
|
||||||
if (f.type != Function::eFunction)
|
if (f.type != Function::eFunction)
|
||||||
continue;
|
return true;
|
||||||
|
|
||||||
const std::string freturnType = f.retType ? f.retType->name() : f.retDef->stringifyList(f.returnDefEnd());
|
const std::string freturnType = f.retType ? f.retType->name() : f.retDef->stringifyList(f.returnDefEnd());
|
||||||
if (f.argumentList.size() == fun->argumentList.size() &&
|
if (f.argumentList.size() == fun->argumentList.size() && returnType == freturnType &&
|
||||||
returnType == freturnType &&
|
|
||||||
f.name() != fun->name()) {
|
f.name() != fun->name()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
|
}))
|
||||||
|
return false;
|
||||||
} else if (tok->variable()) {
|
} else if (tok->variable()) {
|
||||||
const Variable * var = tok->variable();
|
const Variable * var = tok->variable();
|
||||||
const Scope * scope = var->scope();
|
const Scope * scope = var->scope();
|
||||||
|
|
|
@ -2780,7 +2780,7 @@ void CheckOther::pointerPositiveError(const Token *tok, const ValueFlow::Value *
|
||||||
/* check if a constructor in given class scope takes a reference */
|
/* check if a constructor in given class scope takes a reference */
|
||||||
static bool constructorTakesReference(const Scope * const classScope)
|
static bool constructorTakesReference(const Scope * const classScope)
|
||||||
{
|
{
|
||||||
for (const Function &constructor : classScope->functionList) {
|
return std::any_of(classScope->functionList.begin(), classScope->functionList.end(), [&](const Function& constructor) {
|
||||||
if (constructor.isConstructor()) {
|
if (constructor.isConstructor()) {
|
||||||
for (int argnr = 0U; argnr < constructor.argCount(); argnr++) {
|
for (int argnr = 0U; argnr < constructor.argCount(); argnr++) {
|
||||||
const Variable * const argVar = constructor.getArgumentVar(argnr);
|
const Variable * const argVar = constructor.getArgumentVar(argnr);
|
||||||
|
@ -2789,8 +2789,8 @@ static bool constructorTakesReference(const Scope * const classScope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
return false;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
154
lib/checkstl.cpp
154
lib/checkstl.cpp
|
@ -2670,6 +2670,142 @@ static std::string minmaxCompare(const Token *condTok, nonneg int loopVar, nonne
|
||||||
return algo;
|
return algo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct LoopAnalyzer {
|
||||||
|
const Token* bodyTok = nullptr;
|
||||||
|
const Token* loopVar = nullptr;
|
||||||
|
const Settings* settings = nullptr;
|
||||||
|
std::set<nonneg int> varsChanged = {};
|
||||||
|
|
||||||
|
explicit LoopAnalyzer(const Token* tok, const Settings* psettings)
|
||||||
|
: bodyTok(tok->next()->link()->next()), settings(psettings)
|
||||||
|
{
|
||||||
|
const Token* splitTok = tok->next()->astOperand2();
|
||||||
|
if (Token::simpleMatch(splitTok, ":") && splitTok->previous()->varId() != 0) {
|
||||||
|
loopVar = splitTok->previous();
|
||||||
|
}
|
||||||
|
if (valid()) {
|
||||||
|
findChangedVariables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool isLoopVarChanged() const {
|
||||||
|
return varsChanged.count(loopVar->varId()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isModified(const Token* tok) const
|
||||||
|
{
|
||||||
|
if (tok->variable() && tok->variable()->isConst())
|
||||||
|
return false;
|
||||||
|
int n = 1 + (astIsPointer(tok) ? 1 : 0);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
bool inconclusive = false;
|
||||||
|
if (isVariableChangedByFunctionCall(tok, i, settings, &inconclusive))
|
||||||
|
return true;
|
||||||
|
if (inconclusive)
|
||||||
|
return true;
|
||||||
|
if (isVariableChanged(tok, i, settings, true))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Predicate, class F>
|
||||||
|
void findTokens(Predicate pred, F f) const
|
||||||
|
{
|
||||||
|
for (const Token* tok = bodyTok; precedes(tok, bodyTok->link()); tok = tok->next()) {
|
||||||
|
if (pred(tok))
|
||||||
|
f(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Predicate>
|
||||||
|
const Token* findToken(Predicate pred) const
|
||||||
|
{
|
||||||
|
for (const Token* tok = bodyTok; precedes(tok, bodyTok->link()); tok = tok->next()) {
|
||||||
|
if (pred(tok))
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasGotoOrBreak() const
|
||||||
|
{
|
||||||
|
return findToken([](const Token* tok) {
|
||||||
|
return Token::Match(tok, "goto|break");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const {
|
||||||
|
return bodyTok && loopVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string findAlgo() const
|
||||||
|
{
|
||||||
|
if (!valid())
|
||||||
|
return "";
|
||||||
|
bool loopVarChanged = isLoopVarChanged();
|
||||||
|
if (!loopVarChanged && varsChanged.empty()) {
|
||||||
|
if (hasGotoOrBreak())
|
||||||
|
return "";
|
||||||
|
bool alwaysTrue = true;
|
||||||
|
bool alwaysFalse = true;
|
||||||
|
auto hasReturn = [](const Token* tok) {
|
||||||
|
return Token::simpleMatch(tok, "return");
|
||||||
|
};
|
||||||
|
findTokens(hasReturn, [&](const Token* tok) {
|
||||||
|
const Token* returnTok = tok->astOperand1();
|
||||||
|
if (!returnTok || !returnTok->hasKnownIntValue() || !astIsBool(returnTok)) {
|
||||||
|
alwaysTrue = false;
|
||||||
|
alwaysFalse = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(returnTok->values().front().intvalue ? alwaysTrue : alwaysFalse) &= true;
|
||||||
|
(returnTok->values().front().intvalue ? alwaysFalse : alwaysTrue) &= false;
|
||||||
|
});
|
||||||
|
if (alwaysTrue == alwaysFalse)
|
||||||
|
return "";
|
||||||
|
if (alwaysTrue)
|
||||||
|
return "std::any_of";
|
||||||
|
else
|
||||||
|
return "std::all_of or std::none_of";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLocalVar(const Variable* var) const
|
||||||
|
{
|
||||||
|
if (!var)
|
||||||
|
return false;
|
||||||
|
if (var->isPointer() || var->isReference())
|
||||||
|
return false;
|
||||||
|
if (var->declarationId() == loopVar->varId())
|
||||||
|
return false;
|
||||||
|
const Scope* scope = var->scope();
|
||||||
|
return scope->isNestedIn(bodyTok->scope());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void findChangedVariables()
|
||||||
|
{
|
||||||
|
std::set<nonneg int> vars;
|
||||||
|
for (const Token* tok = bodyTok; precedes(tok, bodyTok->link()); tok = tok->next()) {
|
||||||
|
if (tok->varId() == 0)
|
||||||
|
continue;
|
||||||
|
if (vars.count(tok->varId()) > 0)
|
||||||
|
continue;
|
||||||
|
if (isLocalVar(tok->variable())) {
|
||||||
|
vars.insert(tok->varId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isModified(tok))
|
||||||
|
continue;
|
||||||
|
varsChanged.insert(tok->varId());
|
||||||
|
vars.insert(tok->varId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void CheckStl::useStlAlgorithm()
|
void CheckStl::useStlAlgorithm()
|
||||||
{
|
{
|
||||||
if (!mSettings->severity.isEnabled(Severity::style))
|
if (!mSettings->severity.isEnabled(Severity::style))
|
||||||
|
@ -2694,6 +2830,13 @@ void CheckStl::useStlAlgorithm()
|
||||||
continue;
|
continue;
|
||||||
if (!Token::simpleMatch(tok->next()->link(), ") {"))
|
if (!Token::simpleMatch(tok->next()->link(), ") {"))
|
||||||
continue;
|
continue;
|
||||||
|
LoopAnalyzer a{tok, mSettings};
|
||||||
|
std::string algoName = a.findAlgo();
|
||||||
|
if (!algoName.empty()) {
|
||||||
|
useStlAlgorithmError(tok, algoName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const Token *bodyTok = tok->next()->link()->next();
|
const Token *bodyTok = tok->next()->link()->next();
|
||||||
const Token *splitTok = tok->next()->astOperand2();
|
const Token *splitTok = tok->next()->astOperand2();
|
||||||
const Token* loopVar{};
|
const Token* loopVar{};
|
||||||
|
@ -2880,16 +3023,15 @@ static bool isKnownEmptyContainer(const Token* tok)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return false;
|
return false;
|
||||||
for (const ValueFlow::Value& v:tok->values()) {
|
return std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) {
|
||||||
if (!v.isKnown())
|
if (!v.isKnown())
|
||||||
continue;
|
return false;
|
||||||
if (!v.isContainerSizeValue())
|
if (!v.isContainerSizeValue())
|
||||||
continue;
|
return false;
|
||||||
if (v.intvalue != 0)
|
if (v.intvalue != 0)
|
||||||
continue;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
});
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckStl::knownEmptyContainer()
|
void CheckStl::knownEmptyContainer()
|
||||||
|
|
|
@ -5128,7 +5128,7 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
||||||
|
|
||||||
bool Scope::hasInlineOrLambdaFunction() const
|
bool Scope::hasInlineOrLambdaFunction() const
|
||||||
{
|
{
|
||||||
for (const Scope *s : nestedList) {
|
return std::any_of(nestedList.begin(), nestedList.end(), [&](const Scope* s) {
|
||||||
// Inline function
|
// Inline function
|
||||||
if (s->type == Scope::eUnconditional && Token::simpleMatch(s->bodyStart->previous(), ") {"))
|
if (s->type == Scope::eUnconditional && Token::simpleMatch(s->bodyStart->previous(), ") {"))
|
||||||
return true;
|
return true;
|
||||||
|
@ -5137,8 +5137,8 @@ bool Scope::hasInlineOrLambdaFunction() const
|
||||||
return true;
|
return true;
|
||||||
if (s->hasInlineOrLambdaFunction())
|
if (s->hasInlineOrLambdaFunction())
|
||||||
return true;
|
return true;
|
||||||
}
|
return false;
|
||||||
return false;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scope::findFunctionInBase(const std::string & name, nonneg int args, std::vector<const Function *> & matches) const
|
void Scope::findFunctionInBase(const std::string & name, nonneg int args, std::vector<const Function *> & matches) const
|
||||||
|
|
116
test/teststl.cpp
116
test/teststl.cpp
|
@ -170,6 +170,7 @@ private:
|
||||||
TEST_CASE(loopAlgoIncrement);
|
TEST_CASE(loopAlgoIncrement);
|
||||||
TEST_CASE(loopAlgoConditional);
|
TEST_CASE(loopAlgoConditional);
|
||||||
TEST_CASE(loopAlgoMinMax);
|
TEST_CASE(loopAlgoMinMax);
|
||||||
|
TEST_CASE(loopAlgoMultipleReturn);
|
||||||
|
|
||||||
TEST_CASE(invalidContainer);
|
TEST_CASE(invalidContainer);
|
||||||
TEST_CASE(invalidContainerLoop);
|
TEST_CASE(invalidContainerLoop);
|
||||||
|
@ -574,7 +575,7 @@ private:
|
||||||
" return true;\n"
|
" return true;\n"
|
||||||
" return false;\n"
|
" return false;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("test.cpp:6:style:Consider using std::any_of algorithm instead of a raw loop.\n", errout.str());
|
ASSERT_EQUALS("test.cpp:5:style:Consider using std::any_of algorithm instead of a raw loop.\n", errout.str());
|
||||||
|
|
||||||
checkNormal("std::vector<int> range(int n);\n"
|
checkNormal("std::vector<int> range(int n);\n"
|
||||||
"bool f(bool b) {\n"
|
"bool f(bool b) {\n"
|
||||||
|
@ -587,7 +588,7 @@ private:
|
||||||
" return true;\n"
|
" return true;\n"
|
||||||
" return false;\n"
|
" return false;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("test.cpp:8:style:Consider using std::any_of algorithm instead of a raw loop.\n", errout.str());
|
ASSERT_EQUALS("test.cpp:7:style:Consider using std::any_of algorithm instead of a raw loop.\n", errout.str());
|
||||||
|
|
||||||
checkNormal("bool g();\n"
|
checkNormal("bool g();\n"
|
||||||
"int f(int x) {\n"
|
"int f(int x) {\n"
|
||||||
|
@ -5120,7 +5121,8 @@ private:
|
||||||
" return true;\n"
|
" return true;\n"
|
||||||
"}\n",
|
"}\n",
|
||||||
true);
|
true);
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (style) Consider using std::any_of algorithm instead of a raw loop.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Consider using std::all_of or std::none_of algorithm instead of a raw loop.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
check("bool pred(int x);\n"
|
check("bool pred(int x);\n"
|
||||||
"bool foo() {\n"
|
"bool foo() {\n"
|
||||||
|
@ -5293,7 +5295,8 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
" return false;\n"
|
" return false;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Consider using std::any_of algorithm instead of a raw loop.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (style) Consider using std::any_of algorithm instead of a raw loop.\n",
|
||||||
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void loopAlgoMinMax() {
|
void loopAlgoMinMax() {
|
||||||
|
@ -5338,6 +5341,111 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (style) Consider using std::accumulate algorithm instead of a raw loop.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (style) Consider using std::accumulate algorithm instead of a raw loop.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loopAlgoMultipleReturn()
|
||||||
|
{
|
||||||
|
check("bool f(const std::vector<int>& v) {\n"
|
||||||
|
" for (auto i : v) {\n"
|
||||||
|
" if (i < 0)\n"
|
||||||
|
" continue;\n"
|
||||||
|
" if (i)\n"
|
||||||
|
" return true;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Consider using std::any_of algorithm instead of a raw loop.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("bool g(const std::vector<int>& v) {\n"
|
||||||
|
" for (auto i : v) {\n"
|
||||||
|
" if (i % 5 == 0)\n"
|
||||||
|
" return true;\n"
|
||||||
|
" if (i % 7 == 0)\n"
|
||||||
|
" return true;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Consider using std::any_of algorithm instead of a raw loop.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("bool g(const std::vector<int>& v) {\n"
|
||||||
|
" for (auto i : v) {\n"
|
||||||
|
" if (i % 5 == 0)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" if (i % 7 == 0)\n"
|
||||||
|
" return true;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("bool g(std::vector<int>& v) {\n"
|
||||||
|
" for (auto& i : v) {\n"
|
||||||
|
" if (i % 5 == 0)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" if (i % 7 == 0)\n"
|
||||||
|
" i++;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("bool g(const std::vector<int>& v, int& j) {\n"
|
||||||
|
" for (auto i : v) {\n"
|
||||||
|
" if (i % 5 == 0)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" if (i % 7 == 0)\n"
|
||||||
|
" j++;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("bool g(const std::vector<int>& v, int& j) {\n"
|
||||||
|
" for (auto i : v) {\n"
|
||||||
|
" int& k = j;\n"
|
||||||
|
" if (i % 5 == 0)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" if (i % 7 == 0)\n"
|
||||||
|
" k++;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("bool g(const std::vector<int>& v, int& j) {\n"
|
||||||
|
" for (auto i : v) {\n"
|
||||||
|
" int* k = &j;\n"
|
||||||
|
" if (i % 5 == 0)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" if (i % 7 == 0)\n"
|
||||||
|
" (*k)++;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("bool g(const std::vector<int>& v, int j) {\n"
|
||||||
|
" for (auto i : v) {\n"
|
||||||
|
" int k = j;\n"
|
||||||
|
" if (i % 5 == 0)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" if (i % 7 == 0)\n"
|
||||||
|
" k++;\n"
|
||||||
|
" }\n"
|
||||||
|
" return false;\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Consider using std::all_of or std::none_of algorithm instead of a raw loop.\n",
|
||||||
|
errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void invalidContainer() {
|
void invalidContainer() {
|
||||||
check("void f(std::vector<int> &v) {\n"
|
check("void f(std::vector<int> &v) {\n"
|
||||||
" auto v0 = v.begin();\n"
|
" auto v0 = v.begin();\n"
|
||||||
|
|
|
@ -202,12 +202,14 @@ private:
|
||||||
|
|
||||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
for (const ValueFlow::Value& val:tok->values()) {
|
if (std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& val) {
|
||||||
if (val.isSymbolicValue())
|
if (val.isSymbolicValue())
|
||||||
continue;
|
return false;
|
||||||
if (val.isKnown() && val.intvalue == value)
|
if (val.isKnown() && val.intvalue == value)
|
||||||
return true;
|
return true;
|
||||||
}
|
return false;
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,12 +224,14 @@ private:
|
||||||
|
|
||||||
for (const Token* tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token* tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
for (const ValueFlow::Value& val : tok->values()) {
|
if (std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& val) {
|
||||||
if (!val.isSymbolicValue())
|
if (!val.isSymbolicValue())
|
||||||
continue;
|
return false;
|
||||||
if (val.isKnown() && val.intvalue == value && val.tokvalue->expressionString() == expr)
|
if (val.isKnown() && val.intvalue == value && val.tokvalue->expressionString() == expr)
|
||||||
return true;
|
return true;
|
||||||
}
|
return false;
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,12 +247,14 @@ private:
|
||||||
|
|
||||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
for (const ValueFlow::Value& val:tok->values()) {
|
if (std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& val) {
|
||||||
if (val.isSymbolicValue())
|
if (val.isSymbolicValue())
|
||||||
continue;
|
return false;
|
||||||
if (val.isImpossible() && val.intvalue == value)
|
if (val.isImpossible() && val.intvalue == value)
|
||||||
return true;
|
return true;
|
||||||
}
|
return false;
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,12 +270,14 @@ private:
|
||||||
|
|
||||||
for (const Token* tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token* tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
for (const ValueFlow::Value& val : tok->values()) {
|
if (std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& val) {
|
||||||
if (!val.isSymbolicValue())
|
if (!val.isSymbolicValue())
|
||||||
continue;
|
return false;
|
||||||
if (val.isImpossible() && val.intvalue == value && val.tokvalue->expressionString() == expr)
|
if (val.isImpossible() && val.intvalue == value && val.tokvalue->expressionString() == expr)
|
||||||
return true;
|
return true;
|
||||||
}
|
return false;
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,12 +293,14 @@ private:
|
||||||
|
|
||||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
if (tok->str() == "x" && tok->linenr() == linenr) {
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
for (const ValueFlow::Value& val:tok->values()) {
|
if (std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& val) {
|
||||||
if (val.isSymbolicValue())
|
if (val.isSymbolicValue())
|
||||||
continue;
|
return false;
|
||||||
if (val.isInconclusive() && val.intvalue == value)
|
if (val.isInconclusive() && val.intvalue == value)
|
||||||
return true;
|
return true;
|
||||||
}
|
return false;
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue