library: improved handling of noreturn. The Tokenizer::isScopeNoReturn will now try to use the library to determine if scope is noreturn.

This commit is contained in:
Daniel Marjamäki 2013-07-14 10:10:11 +02:00
parent 7d237579c9
commit b2f6e9e3eb
4 changed files with 52 additions and 7 deletions

View File

@ -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;

View File

@ -60,12 +60,31 @@ public:
std::set<std::string> use;
std::set<std::string> ignore;
std::set<std::string> noreturn;
bool isnoreturn(const std::string &name) const {
std::map<std::string,bool>::const_iterator it = _noreturn.find(name);
return (it != _noreturn.end() && it->second);
}
bool isnotnoreturn(const std::string &name) const {
std::map<std::string,bool>::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<std::string, std::map<int, Argument> > functionArgument;
private:
int allocid;
std::map<std::string, int> _alloc; // allocation functions
std::map<std::string, int> _dealloc; // deallocation functions
std::map<std::string, bool> _noreturn; // is function noreturn?
int getid(const std::map<std::string,int> &data, const std::string &name) const {
const std::map<std::string,int>::const_iterator it = data.find(name);

View File

@ -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;

View File

@ -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