diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index c0a568f06..ff7952544 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -176,8 +176,12 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // using namespace else if (Token::Match(tok, "using namespace %type% ;|::")) { - // save location - scope->usingList.push_back(tok); + Scope::UsingInfo using_info; + + using_info.start = tok; // save location + using_info.scope = 0; // fill in later + + scope->usingList.push_back(using_info); tok = tok->tokAt(3); } @@ -669,6 +673,19 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } } + // fill in using info + for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) { + // check scope for match + scope = findScope(i->start->tokAt(2), &(*it)); + if (scope) { + // set found scope + i->scope = scope; + break; + } + } + } + // fill in variable info for (it = scopeList.begin(); it != scopeList.end(); ++it) { // find variables @@ -1633,16 +1650,16 @@ void SymbolDatabase::printOut(const char *title) const scope->needInitialization == Scope::False ? "False" : "Invalid") << std::endl; - std::list::const_iterator use; + std::list::const_iterator use; for (use = scope->usingList.begin(); use != scope->usingList.end(); ++use) { - std::cout << " using: " << (*use)->strAt(2); - const Token *tok1 = (*use)->tokAt(3); + std::cout << " using: " << use->scope << " " << use->start->strAt(2); + const Token *tok1 = use->start->tokAt(3); while (tok1 && tok1->str() == "::") { std::cout << "::" << tok1->strAt(1); tok1 = tok1->tokAt(2); } - std::cout << " " << _tokenizer->list.fileLine(*use) << std::endl; + std::cout << " " << _tokenizer->list.fileLine(use->start) << std::endl; } std::cout << " functionOf: " << scope->functionOf; @@ -1724,8 +1741,24 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s } const Scope *argType = NULL; - if (!typeTok->isStandardType()) + if (!typeTok->isStandardType()) { argType = symbolDatabase->findVariableType(scope, typeTok); + if (!argType) { + // look for variable type in any using namespace in this scope or above + const Scope *parent = scope; + while (parent) { + for (std::list::const_iterator ui = scope->usingList.begin(); + ui != scope->usingList.end(); ++ui) { + if (ui->scope) { + argType = symbolDatabase->findVariableType(ui->scope, typeTok); + if (argType) + break; + } + } + parent = parent->nestedIn; + } + } + } // skip default values if (tok->str() == "=") { @@ -2065,8 +2098,24 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess) const Scope *scope = NULL; - if (typetok) + if (typetok) { scope = check->findVariableType(this, typetok); + if (!scope) { + // look for variable type in any using namespace in this scope or above + const Scope *parent = this; + while (parent) { + for (std::list::const_iterator ui = parent->usingList.begin(); + ui != parent->usingList.end(); ++ui) { + if (ui->scope) { + scope = check->findVariableType(ui->scope, typetok); + if (scope) + break; + } + } + parent = parent->nestedIn; + } + } + } addVariable(vartok, typestart, vartok->previous(), varaccess, scope, this); } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 367b9df5a..6b635789e 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -451,6 +451,11 @@ public: Scope *scope; }; + struct UsingInfo { + const Token *start; + Scope *scope; + }; + enum ScopeType { eGlobal, eClass, eStruct, eUnion, eNamespace, eFunction, eIf, eElse, eElseIf, eFor, eWhile, eDo, eSwitch, eUnconditional, eTry, eCatch }; enum NeedInitialization { Unknown, True, False }; @@ -469,7 +474,7 @@ public: Scope *nestedIn; std::list nestedList; unsigned int numConstructors; - std::list usingList; + std::list usingList; NeedInitialization needInitialization; ScopeType type; diff --git a/test/teststl.cpp b/test/teststl.cpp index 59bb159a3..ea6922f4d 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -100,6 +100,7 @@ private: TEST_CASE(size1); TEST_CASE(size2); + TEST_CASE(size3); // Redundant conditions.. // if (ints.find(123) != ints.end()) ints.remove(123); @@ -1591,6 +1592,34 @@ private: ASSERT_EQUALS("[test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str()); } + void size3() { + check("namespace N {\n" + " class Zzz {\n" + " public:\n" + " std::list x;\n" + " };\n" + "}\n" + "using namespace N;\n" + "Zzz * zzz;\n" + "int main() {\n" + " if (zzz->x.size() > 0) { }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str()); + + check("namespace N {\n" + " class Zzz {\n" + " public:\n" + " std::list x;\n" + " };\n" + "}\n" + "using namespace N;\n" + "int main() {\n" + " Zzz * zzz;\n" + " if (zzz->x.size() > 0) { }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str()); + } + void redundantCondition2() { check("void f(string haystack)\n" "{\n"