Set functions for calls through iterators (#4763)

This commit is contained in:
chrchr-github 2023-02-07 21:57:59 +01:00 committed by GitHub
parent 20ff2d7172
commit 8af1026696
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 49 additions and 31 deletions

View File

@ -2865,13 +2865,9 @@ void CheckClass::checkCopyCtorAndEqOperator()
for (const Scope * scope : mSymbolDatabase->classAndStructScopes) {
bool hasNonStaticVars = false;
for (std::list<Variable>::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
if (!var->isStatic()) {
hasNonStaticVars = true;
break;
}
}
const bool hasNonStaticVars = std::any_of(scope->varlist.begin(), scope->varlist.end(), [](const Variable& var) {
return !var.isStatic();
});
if (!hasNonStaticVars)
continue;

View File

@ -2860,7 +2860,8 @@ void CheckStl::useStlAlgorithm()
if (isEarlyExit(condBodyTok)) {
const Token *loopVar2 = Token::findmatch(condBodyTok, "%varid%", condBodyTok->link(), loopVar->varId());
std::string algo;
if (loopVar2)
if (loopVar2 ||
(isIteratorLoop && loopVar->variable() && precedes(loopVar->variable()->nameToken(), tok))) // iterator declared outside the loop
algo = "std::find_if";
else
algo = "std::any_of";

View File

@ -4409,15 +4409,9 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *
bool Scope::hasDefaultConstructor() const
{
if (numConstructors) {
std::list<Function>::const_iterator func;
for (func = functionList.cbegin(); func != functionList.cend(); ++func) {
if (func->type == Function::eConstructor && func->argCount() == 0)
return true;
}
}
return false;
return numConstructors > 0 && std::any_of(functionList.begin(), functionList.end(), [](const Function& func) {
return func.type == Function::eConstructor && func.argCount() == 0;
});
}
AccessControl Scope::defaultAccess() const
@ -5584,6 +5578,8 @@ const Function* SymbolDatabase::findFunction(const Token *tok) const
return var->typeScope()->findFunction(tok, var->valueType()->constness == 1);
if (var && var->smartPointerType() && var->smartPointerType()->classScope && tok1->next()->originalName() == "->")
return var->smartPointerType()->classScope->findFunction(tok, var->valueType()->constness == 1);
if (var && var->iteratorType() && var->iteratorType()->classScope && tok1->next()->originalName() == "->")
return var->iteratorType()->classScope->findFunction(tok, var->valueType()->constness == 1);
} else if (Token::simpleMatch(tok->previous()->astOperand1(), "(")) {
const Token *castTok = tok->previous()->astOperand1();
if (castTok->isCast()) {
@ -6280,12 +6276,11 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
const Scope *typeScope = vt1->typeScope;
if (!typeScope)
return;
for (std::list<Variable>::const_iterator it = typeScope->varlist.cbegin(); it != typeScope->varlist.cend(); ++it) {
if (it->nameToken()->str() == name) {
var = &*it;
break;
}
}
auto it = std::find_if(typeScope->varlist.begin(), typeScope->varlist.end(), [&name](const Variable& v) {
return v.nameToken()->str() == name;
});
if (it != typeScope->varlist.end())
var = &*it;
}
if (var)
setValueType(parent, *var);

View File

@ -3809,11 +3809,9 @@ void TemplateSimplifier::simplifyTemplates(
}
for (std::list<TokenAndName>::const_iterator it = mInstantiatedTemplates.cbegin(); it != mInstantiatedTemplates.cend(); ++it) {
std::list<TokenAndName>::iterator decl;
for (decl = mTemplateDeclarations.begin(); decl != mTemplateDeclarations.end(); ++decl) {
if (decl->token() == it->token())
break;
}
auto decl = std::find_if(mTemplateDeclarations.begin(), mTemplateDeclarations.end(), [&it](const TokenAndName& decl) {
return decl.token() == it->token();
});
if (decl != mTemplateDeclarations.end()) {
if (it->isSpecialization()) {
// delete the "template < >"

View File

@ -1955,9 +1955,7 @@ private:
" for (it = l.begin(); it != l.end(); ++it)\n"
" it->g(0);\n"
"}\n");
TODO_ASSERT_EQUALS("",
"[test.cpp:5]: (information) --check-library: There is no matching configuration for function F::g()\n",
errout.str());
ASSERT_EQUALS("", errout.str());
settings = settings_old;
}

View File

@ -5241,6 +5241,22 @@ private:
" return ret;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:5]: (style) Consider using std::any_of, std::all_of, std::none_of algorithm instead of a raw loop.\n", errout.str());
check("struct T {\n"
" std::vector<int> v0, v1;\n"
" void g();\n"
"};\n"
"void T::g() {\n"
" for (std::vector<int>::const_iterator it0 = v0.cbegin(); it0 != v0.cend(); ++it0) {\n"
" std::vector<int>::iterator it1;\n"
" for (it1 = v1.begin(); it1 != v1.end(); ++it1)\n"
" if (*it0 == *it1)\n"
" break;\n"
" if (it1 != v1.end())\n"
" v1.erase(it1);\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (style) Consider using std::find_if algorithm instead of a raw loop.\n", errout.str());
}
void loopAlgoMinMax() {

View File

@ -438,6 +438,7 @@ private:
TEST_CASE(findFunction42);
TEST_CASE(findFunction43); // #10087
TEST_CASE(findFunction44); // #11182
TEST_CASE(findFunction45);
TEST_CASE(findFunctionContainer);
TEST_CASE(findFunctionExternC);
TEST_CASE(findFunctionGlobalScope); // ::foo
@ -6959,6 +6960,19 @@ private:
}
}
void findFunction45() {
GET_SYMBOL_DB("struct S { void g(int); };\n"
"void f(std::vector<S>& v) {\n"
" std::vector<S>::iterator it = v.begin();\n"
" it->g(1);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
const Token *functok = Token::findsimplematch(tokenizer.tokens(), "g ( 1");
ASSERT(functok);
ASSERT(functok->function());
ASSERT(functok->function()->name() == "g");
ASSERT_EQUALS(1, functok->function()->tokenDef->linenr());
}
void findFunctionContainer() {
{