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 &it3->second;
return nullptr; 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); return (it != _noreturn.end() && !it->second);
} }
bool isScopeNoReturn(const Token *end, std::string *unknownFunc) const;
class ArgumentChecks { class ArgumentChecks {
public: public:
ArgumentChecks() : ArgumentChecks() :

View File

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

View File

@ -867,24 +867,12 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
// After conditional code.. // After conditional code..
if (ok && !scopeEnd.empty() && Token::simpleMatch(top->link(), ") {")) { if (ok && !scopeEnd.empty() && Token::simpleMatch(top->link(), ") {")) {
Token *after = top->link()->linkAt(1); Token *after = top->link()->linkAt(1);
if (Token::simpleMatch(after->tokAt(-2), ") ; }")) { std::string unknownFunction;
const Token *funcname = after->linkAt(-2)->previous(); if (settings->library.isScopeNoReturn(after,&unknownFunction)) {
const Token *start = funcname; if (settings->debugwarnings && !unknownFunction.empty())
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"); bailout(tokenlist, errorLogger, after, "possible noreturn scope");
continue; continue;
} }
}
}
if (Token::simpleMatch(after, "} else {")) { if (Token::simpleMatch(after, "} else {")) {
after = after->linkAt(2); after = after->linkAt(2);
if (Token::simpleMatch(after->tokAt(-2), ") ; }")) { if (Token::simpleMatch(after->tokAt(-2), ") ; }")) {