Fixed #4352: Ensure that class provides an iterator interface.
This commit is contained in:
parent
0b22cb932e
commit
641ac5c02a
|
@ -67,9 +67,17 @@ void CheckStl::iterators()
|
|||
const Variable* var = symbolDatabase->getVariableFromVarId(iteratorId);
|
||||
|
||||
// Check that its an iterator
|
||||
if (!var || !var->isLocal() || !Token::Match(var->nameToken()->previous(), "iterator|const_iterator|reverse_iterator|const_reverse_iterator"))
|
||||
if (!var || !var->isLocal() || !Token::Match(var->typeEndToken(), "iterator|const_iterator|reverse_iterator|const_reverse_iterator"))
|
||||
continue;
|
||||
|
||||
if (var->type()) { // If it is defined, ensure that it is defined like an iterator
|
||||
// look for operator* and operator++
|
||||
const Function* end = var->type()->getFunction("operator*");
|
||||
const Function* incOperator = var->type()->getFunction("operator++");
|
||||
if (!end || end->argCount() > 0 || !incOperator)
|
||||
continue;
|
||||
}
|
||||
|
||||
// the validIterator flag says if the iterator has a valid value or not
|
||||
bool validIterator = Token::Match(var->nameToken()->next(), "[(=]");
|
||||
const Scope* invalidationScope = 0;
|
||||
|
|
|
@ -1456,6 +1456,24 @@ void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) cons
|
|||
}
|
||||
}
|
||||
|
||||
const Function* Type::getFunction(const std::string& funcName) const
|
||||
{
|
||||
if (classScope) {
|
||||
for (std::list<Function>::const_iterator i = classScope->functionList.begin(); i != classScope->functionList.end(); ++i)
|
||||
if (i->name() == funcName)
|
||||
return &*i;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < derivedFrom.size(); i++) {
|
||||
if (derivedFrom[i].type) {
|
||||
const Function* func = derivedFrom[i].type->getFunction(funcName);
|
||||
if (func)
|
||||
return func;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Variable::arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok)
|
||||
{
|
||||
bool isArray = false;
|
||||
|
|
|
@ -95,6 +95,8 @@ public:
|
|||
}
|
||||
|
||||
const Token *initBaseInfo(const Token *tok, const Token *tok1);
|
||||
|
||||
const Function* getFunction(const std::string& funcName) const;
|
||||
};
|
||||
|
||||
/** @brief Information about a member variable. */
|
||||
|
|
|
@ -93,6 +93,7 @@ private:
|
|||
TEST_CASE(stlBoundaries2);
|
||||
TEST_CASE(stlBoundaries3);
|
||||
TEST_CASE(stlBoundaries4); // #4364
|
||||
TEST_CASE(stlBoundaries5); // #4352
|
||||
|
||||
// if (str.find("ab"))
|
||||
TEST_CASE(if_find);
|
||||
|
@ -1329,6 +1330,26 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:4]: (error) Dangerous iterator comparison using operator< on 'std::forward_list'.\n", errout.str());
|
||||
}
|
||||
|
||||
void stlBoundaries5() {
|
||||
check("class iterator { int foo(); };\n"
|
||||
"int foo() {\n"
|
||||
" iterator i;\n"
|
||||
" return i.foo();;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("class iterator {\n"
|
||||
" Class operator*();\n"
|
||||
" iterator& operator++();\n"
|
||||
" int foo();\n"
|
||||
"};\n"
|
||||
"int foo() {\n"
|
||||
" iterator i;\n"
|
||||
" return i.foo();;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:8]: (error) Invalid iterator 'i' used.\n", errout.str());
|
||||
}
|
||||
|
||||
|
||||
void if_find() {
|
||||
// ---------------------------
|
||||
|
|
|
@ -576,6 +576,8 @@ private:
|
|||
ASSERT(function && function->token == tokenizer.tokens()->tokAt(4));
|
||||
ASSERT(function && function->hasBody && function->isInline);
|
||||
ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
|
||||
|
||||
ASSERT(db && db->findScopeByName("Fred") && db->findScopeByName("Fred")->definedType->getFunction("func") == function);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1434,6 +1436,15 @@ private:
|
|||
ASSERT(Bar_Sub && Bar_Sub->classScope && Bar_Sub->classScope->numConstructors == 2 && Bar_Sub->classScope->className == "Sub");
|
||||
}
|
||||
|
||||
void symboldatabase32() {
|
||||
GET_SYMBOL_DB("struct Base {\n"
|
||||
" void foo() {}\n"
|
||||
"};\n"
|
||||
"class Deri : Base {\n"
|
||||
"};");
|
||||
ASSERT(db && db->findScopeByName("Deri") && db->findScopeByName("Deri")->definedType->getFunction("foo"));
|
||||
}
|
||||
|
||||
void isImplicitlyVirtual() {
|
||||
{
|
||||
GET_SYMBOL_DB("class Base {\n"
|
||||
|
|
Loading…
Reference in New Issue