Fixed #6711 (Add namespace support to library files)

This commit is contained in:
Daniel Marjamäki 2015-08-09 19:55:33 +02:00
parent 9627fccdc5
commit b70fe4c609
3 changed files with 57 additions and 5 deletions

View File

@ -4520,6 +4520,19 @@
<strz/> <strz/>
</arg> </arg>
</function> </function>
<function name="std::strcpy">
<noreturn>false</noreturn>
<leak-ignore/>
<arg nr="1">
<not-null/>
<minsize type="strlen" arg="2"/>
</arg>
<arg nr="2">
<not-null/>
<not-uninit/>
<strz/>
</arg>
</function>
<!-- wchar_t *wcscpy(wchar_t *deststr, const wchar_t *srcstr); --> <!-- wchar_t *wcscpy(wchar_t *deststr, const wchar_t *srcstr); -->
<function name="wcscpy"> <function name="wcscpy">
<noreturn>false</noreturn> <noreturn>false</noreturn>

View File

@ -608,12 +608,27 @@ bool Library::isargvalid(const Token *ftok, int argnr, const MathLib::bigint arg
return false; 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 const Library::ArgumentChecks * Library::getarg(const Token *ftok, int argnr) const
{ {
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return nullptr; return nullptr;
std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it1; std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it1;
it1 = argumentChecks.find(ftok->str()); it1 = argumentChecks.find(functionName(ftok));
if (it1 == argumentChecks.end()) if (it1 == argumentChecks.end())
return nullptr; return nullptr;
const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.find(argnr); const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.find(argnr);
@ -678,12 +693,13 @@ const Library::Container* Library::detectContainer(const Token* typeStart) const
} }
return nullptr; return nullptr;
} }
// returns true if ftok is not a library function // returns true if ftok is not a library function
bool Library::isNotLibraryFunction(const Token *ftok) const bool Library::isNotLibraryFunction(const Token *ftok) const
{ {
// methods are not library functions // methods are not library functions
// called from tokenizer, ast is not created properly yet // called from tokenizer, ast is not created properly yet
if (Token::Match(ftok->previous(),"::|.")) if (Token::Match(ftok->previous(),"."))
return true; return true;
if (ftok->function() && ftok->function()->nestedIn && ftok->function()->nestedIn->type != Scope::eGlobal) if (ftok->function() && ftok->function()->nestedIn && ftok->function()->nestedIn->type != Scope::eGlobal)
return true; return true;
@ -701,7 +717,7 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
else if (tok->link() && Token::Match(tok, "<|(|[")) else if (tok->link() && Token::Match(tok, "<|(|["))
tok = tok->link(); tok = tok->link();
} }
const std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it = argumentChecks.find(ftok->str()); const std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it = argumentChecks.find(functionName(ftok));
if (it == argumentChecks.end()) if (it == argumentChecks.end())
return (callargs != 0); return (callargs != 0);
int args = 0; int args = 0;
@ -720,7 +736,7 @@ bool Library::isnoreturn(const Token *ftok) const
return true; return true;
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return false; return false;
std::map<std::string, bool>::const_iterator it = _noreturn.find(ftok->str()); std::map<std::string, bool>::const_iterator it = _noreturn.find(functionName(ftok));
return (it != _noreturn.end() && it->second); return (it != _noreturn.end() && it->second);
} }
@ -730,7 +746,7 @@ bool Library::isnotnoreturn(const Token *ftok) const
return false; return false;
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
return false; return false;
std::map<std::string, bool>::const_iterator it = _noreturn.find(ftok->str()); std::map<std::string, bool>::const_iterator it = _noreturn.find(functionName(ftok));
return (it != _noreturn.end() && !it->second); return (it != _noreturn.end() && !it->second);
} }

View File

@ -39,6 +39,7 @@ private:
TEST_CASE(function_arg_any); TEST_CASE(function_arg_any);
TEST_CASE(function_arg_valid); TEST_CASE(function_arg_valid);
TEST_CASE(function_arg_minsize); TEST_CASE(function_arg_minsize);
TEST_CASE(function_namespace);
TEST_CASE(memory); TEST_CASE(memory);
TEST_CASE(memory2); // define extra "free" allocation functions TEST_CASE(memory2); // define extra "free" allocation functions
TEST_CASE(resource); TEST_CASE(resource);
@ -288,6 +289,28 @@ private:
} }
} }
void function_namespace() const {
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<def>\n"
" <function name=\"Foo::foo\">\n"
" <noreturn>false</noreturn>\n"
" </function>\n"
"</def>";
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 { void memory() const {
const char xmldata[] = "<?xml version=\"1.0\"?>\n" const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<def>\n" "<def>\n"