Skip to content

Commit 8af1026

Browse files
Set functions for calls through iterators (#4763)
1 parent 20ff2d7 commit 8af1026

7 files changed

Lines changed: 49 additions & 31 deletions

File tree

lib/checkclass.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2865,13 +2865,9 @@ void CheckClass::checkCopyCtorAndEqOperator()
28652865

28662866
for (const Scope * scope : mSymbolDatabase->classAndStructScopes) {
28672867

2868-
bool hasNonStaticVars = false;
2869-
for (std::list<Variable>::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
2870-
if (!var->isStatic()) {
2871-
hasNonStaticVars = true;
2872-
break;
2873-
}
2874-
}
2868+
const bool hasNonStaticVars = std::any_of(scope->varlist.begin(), scope->varlist.end(), [](const Variable& var) {
2869+
return !var.isStatic();
2870+
});
28752871
if (!hasNonStaticVars)
28762872
continue;
28772873

lib/checkstl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2860,7 +2860,8 @@ void CheckStl::useStlAlgorithm()
28602860
if (isEarlyExit(condBodyTok)) {
28612861
const Token *loopVar2 = Token::findmatch(condBodyTok, "%varid%", condBodyTok->link(), loopVar->varId());
28622862
std::string algo;
2863-
if (loopVar2)
2863+
if (loopVar2 ||
2864+
(isIteratorLoop && loopVar->variable() && precedes(loopVar->variable()->nameToken(), tok))) // iterator declared outside the loop
28642865
algo = "std::find_if";
28652866
else
28662867
algo = "std::any_of";

lib/symboldatabase.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4409,15 +4409,9 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *
44094409

44104410
bool Scope::hasDefaultConstructor() const
44114411
{
4412-
if (numConstructors) {
4413-
std::list<Function>::const_iterator func;
4414-
4415-
for (func = functionList.cbegin(); func != functionList.cend(); ++func) {
4416-
if (func->type == Function::eConstructor && func->argCount() == 0)
4417-
return true;
4418-
}
4419-
}
4420-
return false;
4412+
return numConstructors > 0 && std::any_of(functionList.begin(), functionList.end(), [](const Function& func) {
4413+
return func.type == Function::eConstructor && func.argCount() == 0;
4414+
});
44214415
}
44224416

44234417
AccessControl Scope::defaultAccess() const
@@ -5584,6 +5578,8 @@ const Function* SymbolDatabase::findFunction(const Token *tok) const
55845578
return var->typeScope()->findFunction(tok, var->valueType()->constness == 1);
55855579
if (var && var->smartPointerType() && var->smartPointerType()->classScope && tok1->next()->originalName() == "->")
55865580
return var->smartPointerType()->classScope->findFunction(tok, var->valueType()->constness == 1);
5581+
if (var && var->iteratorType() && var->iteratorType()->classScope && tok1->next()->originalName() == "->")
5582+
return var->iteratorType()->classScope->findFunction(tok, var->valueType()->constness == 1);
55875583
} else if (Token::simpleMatch(tok->previous()->astOperand1(), "(")) {
55885584
const Token *castTok = tok->previous()->astOperand1();
55895585
if (castTok->isCast()) {
@@ -6280,12 +6276,11 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
62806276
const Scope *typeScope = vt1->typeScope;
62816277
if (!typeScope)
62826278
return;
6283-
for (std::list<Variable>::const_iterator it = typeScope->varlist.cbegin(); it != typeScope->varlist.cend(); ++it) {
6284-
if (it->nameToken()->str() == name) {
6285-
var = &*it;
6286-
break;
6287-
}
6288-
}
6279+
auto it = std::find_if(typeScope->varlist.begin(), typeScope->varlist.end(), [&name](const Variable& v) {
6280+
return v.nameToken()->str() == name;
6281+
});
6282+
if (it != typeScope->varlist.end())
6283+
var = &*it;
62896284
}
62906285
if (var)
62916286
setValueType(parent, *var);

lib/templatesimplifier.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3809,11 +3809,9 @@ void TemplateSimplifier::simplifyTemplates(
38093809
}
38103810

38113811
for (std::list<TokenAndName>::const_iterator it = mInstantiatedTemplates.cbegin(); it != mInstantiatedTemplates.cend(); ++it) {
3812-
std::list<TokenAndName>::iterator decl;
3813-
for (decl = mTemplateDeclarations.begin(); decl != mTemplateDeclarations.end(); ++decl) {
3814-
if (decl->token() == it->token())
3815-
break;
3816-
}
3812+
auto decl = std::find_if(mTemplateDeclarations.begin(), mTemplateDeclarations.end(), [&it](const TokenAndName& decl) {
3813+
return decl.token() == it->token();
3814+
});
38173815
if (decl != mTemplateDeclarations.end()) {
38183816
if (it->isSpecialization()) {
38193817
// delete the "template < >"

test/testfunctions.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,9 +1955,7 @@ class TestFunctions : public TestFixture {
19551955
" for (it = l.begin(); it != l.end(); ++it)\n"
19561956
" it->g(0);\n"
19571957
"}\n");
1958-
TODO_ASSERT_EQUALS("",
1959-
"[test.cpp:5]: (information) --check-library: There is no matching configuration for function F::g()\n",
1960-
errout.str());
1958+
ASSERT_EQUALS("", errout.str());
19611959

19621960
settings = settings_old;
19631961
}

test/teststl.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5241,6 +5241,22 @@ class TestStl : public TestFixture {
52415241
" return ret;\n"
52425242
"}\n");
52435243
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());
5244+
5245+
check("struct T {\n"
5246+
" std::vector<int> v0, v1;\n"
5247+
" void g();\n"
5248+
"};\n"
5249+
"void T::g() {\n"
5250+
" for (std::vector<int>::const_iterator it0 = v0.cbegin(); it0 != v0.cend(); ++it0) {\n"
5251+
" std::vector<int>::iterator it1;\n"
5252+
" for (it1 = v1.begin(); it1 != v1.end(); ++it1)\n"
5253+
" if (*it0 == *it1)\n"
5254+
" break;\n"
5255+
" if (it1 != v1.end())\n"
5256+
" v1.erase(it1);\n"
5257+
" }\n"
5258+
"}\n");
5259+
ASSERT_EQUALS("[test.cpp:9]: (style) Consider using std::find_if algorithm instead of a raw loop.\n", errout.str());
52445260
}
52455261

52465262
void loopAlgoMinMax() {

test/testsymboldatabase.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ class TestSymbolDatabase : public TestFixture {
438438
TEST_CASE(findFunction42);
439439
TEST_CASE(findFunction43); // #10087
440440
TEST_CASE(findFunction44); // #11182
441+
TEST_CASE(findFunction45);
441442
TEST_CASE(findFunctionContainer);
442443
TEST_CASE(findFunctionExternC);
443444
TEST_CASE(findFunctionGlobalScope); // ::foo
@@ -6959,6 +6960,19 @@ class TestSymbolDatabase : public TestFixture {
69596960
}
69606961
}
69616962

6963+
void findFunction45() {
6964+
GET_SYMBOL_DB("struct S { void g(int); };\n"
6965+
"void f(std::vector<S>& v) {\n"
6966+
" std::vector<S>::iterator it = v.begin();\n"
6967+
" it->g(1);\n"
6968+
"}\n");
6969+
ASSERT_EQUALS("", errout.str());
6970+
const Token *functok = Token::findsimplematch(tokenizer.tokens(), "g ( 1");
6971+
ASSERT(functok);
6972+
ASSERT(functok->function());
6973+
ASSERT(functok->function()->name() == "g");
6974+
ASSERT_EQUALS(1, functok->function()->tokenDef->linenr());
6975+
}
69626976

69636977
void findFunctionContainer() {
69646978
{

0 commit comments

Comments
 (0)