diff --git a/lib/library.cpp b/lib/library.cpp index 05d414180..7019b1e52 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -33,7 +33,7 @@ Library::Library() : allocid(0) _dealloc["fclose"] = allocid; } -Library::Library(const Library &lib) : use(lib.use), ignore(lib.ignore), noreturn(lib.noreturn), allocid(lib.allocid), _alloc(lib._alloc), _dealloc(lib._dealloc) +Library::Library(const Library &lib) : use(lib.use), ignore(lib.ignore), allocid(lib.allocid), _alloc(lib._alloc), _dealloc(lib._dealloc), _noreturn(lib._noreturn) { } @@ -69,9 +69,28 @@ bool Library::load(const char path[]) else if (strcmp(node->Name(),"ignore")==0) ignore.insert(node->GetText()); - else if (strcmp(node->Name(),"noreturn")==0) - noreturn.insert(node->GetText()); - else + else if (strcmp(node->Name(),"function")==0) { + const char *name = node->Attribute("name"); + if (name == NULL) + return false; + + for (const tinyxml2::XMLElement *functionnode = node->FirstChildElement(); functionnode; functionnode = functionnode->NextSiblingElement()) { + if (strcmp(functionnode->Name(),"noreturn")==0) + _noreturn[name] = (strcmp(functionnode->GetText(), "true") == 0); + else if (strcmp(functionnode->Name(),"arg")==0 && functionnode->Attribute("nr") != NULL) { + const int nr = atoi(functionnode->Attribute("nr")); + + const char *nullpointer = functionnode->Attribute("nullpointer"); + const char *uninitdata = functionnode->Attribute("uninitdata"); + const char *uninitderefdata = functionnode->Attribute("uninitderefdata"); + + functionArgument[name][nr].nullpointer = (nullpointer != NULL); + functionArgument[name][nr].uninitdata = (uninitdata != NULL); + functionArgument[name][nr].uninitderefdata = (uninitderefdata != NULL); + } else + return false; + } + } else return false; } return true; diff --git a/lib/library.h b/lib/library.h index 62e8bc0c0..6a70f7b72 100644 --- a/lib/library.h +++ b/lib/library.h @@ -60,12 +60,31 @@ public: std::set use; std::set ignore; - std::set noreturn; + + bool isnoreturn(const std::string &name) const { + std::map::const_iterator it = _noreturn.find(name); + return (it != _noreturn.end() && it->second); + } + + bool isnotnoreturn(const std::string &name) const { + std::map::const_iterator it = _noreturn.find(name); + return (it != _noreturn.end() && !it->second); + } + + struct Argument { + bool nullpointer; + bool uninitdata; + bool uninitderefdata; + }; + + // function name, argument nr => argument data + std::map > functionArgument; private: int allocid; std::map _alloc; // allocation functions std::map _dealloc; // deallocation functions + std::map _noreturn; // is function noreturn? int getid(const std::map &data, const std::string &name) const { const std::map::const_iterator it = data.find(name); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5ec9b4aac..9d06b5f59 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7731,7 +7731,7 @@ void Tokenizer::simplifyStd() //--------------------------------------------------------------------------- -bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown) +bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown) const { if (unknown) *unknown = false; @@ -7755,6 +7755,13 @@ bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown) while (tok && (Token::Match(tok, "::|.") || tok->isName())) tok = tok->previous(); + if (Token::Match(tok, "[;{}] %var% (")) { + if (_settings->library.isnoreturn(tok->next()->str())) + return true; + if (_settings->library.isnotnoreturn(tok->next()->str())) + return false; + } + if (Token::Match(tok, "[;{}]")) { if (unknown) *unknown = true; diff --git a/lib/tokenize.h b/lib/tokenize.h index 494abc84b..f91793a2c 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -63,7 +63,7 @@ public: * \param unknown set to true if it's unknown if the scope is noreturn * \return true if scope ends with a function call that might be 'noreturn' */ - static bool IsScopeNoReturn(const Token *endScopeToken, bool *unknown = 0); + bool IsScopeNoReturn(const Token *endScopeToken, bool *unknown = 0) const; /** * Tokenize code