Refactoring: Move isScopeNoReturn implementation to library and reuse it both in ValueFlow and Tokenizer

This commit is contained in:
Daniel Marjamäki 2014-06-22 19:13:15 +02:00
parent c19fc08a68
commit ae81b09b58
4 changed files with 48 additions and 59 deletions

View File

@ -376,3 +376,35 @@ const Library::ArgumentChecks * Library::getarg(const std::string &functionName,
return &it3->second;
return nullptr;
}
bool Library::isScopeNoReturn(const Token *end, std::string *unknownFunc) const
{
if (unknownFunc)
unknownFunc->clear();
if (!Token::simpleMatch(end->tokAt(-2), ") ; }"))
return false;
const Token *funcname = end->linkAt(-2)->previous();
const Token *start = funcname;
if (funcname && Token::Match(funcname->tokAt(-3),"( * %var% )")) {
funcname = funcname->previous();
start = funcname->tokAt(-3);
} else if (funcname->isName()) {
while (Token::Match(start, "%var%|.|::"))
start = start->previous();
} else {
return false;
}
if (Token::Match(start,"[;{}]") && Token::Match(funcname, "%var% )| (")) {
if (funcname->str() == "exit")
return true;
if (!isnotnoreturn(funcname->str())) {
if (unknownFunc && !isnoreturn(funcname->str()))
*unknownFunc = funcname->str();
return true;
}
}
return false;
}

View File

@ -134,6 +134,8 @@ public:
return (it != _noreturn.end() && !it->second);
}
bool isScopeNoReturn(const Token *end, std::string *unknownFunc) const;
class ArgumentChecks {
public:
ArgumentChecks() :

View File

@ -7834,50 +7834,17 @@ void Tokenizer::simplifyStd()
bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown) const
{
std::string unknownFunc;
bool ret = _settings->library.isScopeNoReturn(endScopeToken,&unknownFunc);
if (unknown)
*unknown = false;
if (Token::simpleMatch(endScopeToken->tokAt(-2), ") ; }")) {
const Token *tok = endScopeToken->linkAt(-2)->previous();
if (!tok)
return true;
// function pointer call..
if (Token::Match(tok->tokAt(-4), "[;{}] ( * %var% )"))
return true;
if (!tok->isName())
return false;
if (tok->str() == "exit")
return true;
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 (_settings->checkLibrary && _settings->isEnabled("information")) {
reportError(tok->next(),
Severity::information,
"checkLibraryNoReturn",
"--check-library: Function " + tok->next()->str() + "() should have <noreturn> configuration");
}
}
if (Token::Match(tok, "[;{}]")) {
if (unknown)
*unknown = true;
return true;
}
*unknown = !unknownFunc.empty();
if (!unknownFunc.empty() && _settings->checkLibrary && _settings->isEnabled("information")) {
reportError(endScopeToken->previous(),
Severity::information,
"checkLibraryNoReturn",
"--check-library: Function " + unknownFunc + "() should have <noreturn> configuration");
}
return false;
return ret;
}
//---------------------------------------------------------------------------

View File

@ -867,23 +867,11 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
// After conditional code..
if (ok && !scopeEnd.empty() && Token::simpleMatch(top->link(), ") {")) {
Token *after = top->link()->linkAt(1);
if (Token::simpleMatch(after->tokAt(-2), ") ; }")) {
const Token *funcname = after->linkAt(-2)->previous();
const Token *start = funcname;
if (funcname && Token::Match(funcname->tokAt(-3),"( * %var% )")) {
funcname = funcname->previous();
start = funcname->tokAt(-3);
} else {
while (Token::Match(start, "%var%|.|::"))
start = start->previous();
}
if (Token::Match(start,"[;{}]") && Token::Match(funcname, "%var% )| (")) {
if (!settings->library.isnotnoreturn(funcname->str())) {
if (settings->debugwarnings)
bailout(tokenlist, errorLogger, after, "possible noreturn scope");
continue;
}
}
std::string unknownFunction;
if (settings->library.isScopeNoReturn(after,&unknownFunction)) {
if (settings->debugwarnings && !unknownFunction.empty())
bailout(tokenlist, errorLogger, after, "possible noreturn scope");
continue;
}
if (Token::simpleMatch(after, "} else {")) {
after = after->linkAt(2);