diff --git a/cfg/std.cfg b/cfg/std.cfg index 6a33ce410..36f0b53d9 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -4520,6 +4520,19 @@ + + false + + + + + + + + + + + false diff --git a/lib/library.cpp b/lib/library.cpp index 0aaf1050d..7ae08bc02 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -608,12 +608,27 @@ bool Library::isargvalid(const Token *ftok, int argnr, const MathLib::bigint arg return false; } +static std::string functionName(const Token *ftok) +{ + if (Token::simpleMatch(ftok->previous(), ".")) + return ""; + if (!Token::Match(ftok->tokAt(-2), "%name% ::")) + return ftok->str(); + std::string ret(ftok->str()); + ftok = ftok->tokAt(-2); + while (Token::Match(ftok, "%name% ::")) { + ret = ftok->str() + "::" + ret; + ftok = ftok->tokAt(-2); + } + return ret; +} + const Library::ArgumentChecks * Library::getarg(const Token *ftok, int argnr) const { if (isNotLibraryFunction(ftok)) return nullptr; std::map >::const_iterator it1; - it1 = argumentChecks.find(ftok->str()); + it1 = argumentChecks.find(functionName(ftok)); if (it1 == argumentChecks.end()) return nullptr; const std::map::const_iterator it2 = it1->second.find(argnr); @@ -678,12 +693,13 @@ const Library::Container* Library::detectContainer(const Token* typeStart) const } return nullptr; } + // returns true if ftok is not a library function bool Library::isNotLibraryFunction(const Token *ftok) const { // methods are not library functions // called from tokenizer, ast is not created properly yet - if (Token::Match(ftok->previous(),"::|.")) + if (Token::Match(ftok->previous(),".")) return true; if (ftok->function() && ftok->function()->nestedIn && ftok->function()->nestedIn->type != Scope::eGlobal) return true; @@ -701,7 +717,7 @@ bool Library::isNotLibraryFunction(const Token *ftok) const else if (tok->link() && Token::Match(tok, "<|(|[")) tok = tok->link(); } - const std::map >::const_iterator it = argumentChecks.find(ftok->str()); + const std::map >::const_iterator it = argumentChecks.find(functionName(ftok)); if (it == argumentChecks.end()) return (callargs != 0); int args = 0; @@ -720,7 +736,7 @@ bool Library::isnoreturn(const Token *ftok) const return true; if (isNotLibraryFunction(ftok)) return false; - std::map::const_iterator it = _noreturn.find(ftok->str()); + std::map::const_iterator it = _noreturn.find(functionName(ftok)); return (it != _noreturn.end() && it->second); } @@ -730,7 +746,7 @@ bool Library::isnotnoreturn(const Token *ftok) const return false; if (isNotLibraryFunction(ftok)) return false; - std::map::const_iterator it = _noreturn.find(ftok->str()); + std::map::const_iterator it = _noreturn.find(functionName(ftok)); return (it != _noreturn.end() && !it->second); } diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index abef5dc1c..4e5eed258 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -39,6 +39,7 @@ private: TEST_CASE(function_arg_any); TEST_CASE(function_arg_valid); TEST_CASE(function_arg_minsize); + TEST_CASE(function_namespace); TEST_CASE(memory); TEST_CASE(memory2); // define extra "free" allocation functions TEST_CASE(resource); @@ -288,6 +289,28 @@ private: } } + void function_namespace() const { + const char xmldata[] = "\n" + "\n" + " \n" + " false\n" + " \n" + ""; + tinyxml2::XMLDocument doc; + doc.Parse(xmldata, sizeof(xmldata)); + + TokenList tokenList(nullptr); + std::istringstream istr("Foo::foo();"); + tokenList.createTokens(istr); + + Library library; + library.load(doc); + ASSERT(library.use.empty()); + ASSERT(library.leakignore.empty()); + ASSERT(library.argumentChecks.empty()); + ASSERT(library.isnotnoreturn(tokenList.front()->tokAt(2))); + } + void memory() const { const char xmldata[] = "\n" "\n"