diff --git a/lib/library.cpp b/lib/library.cpp index 15fa7ac0a..879a50168 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -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; +} + diff --git a/lib/library.h b/lib/library.h index 3afce05f7..d681f39c1 100644 --- a/lib/library.h +++ b/lib/library.h @@ -134,6 +134,8 @@ public: return (it != _noreturn.end() && !it->second); } + bool isScopeNoReturn(const Token *end, std::string *unknownFunc) const; + class ArgumentChecks { public: ArgumentChecks() : diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8484d6015..38c059d1f 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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 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 configuration"); } - - return false; + return ret; } //--------------------------------------------------------------------------- diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 54c3be2e6..ce32cb5ad 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -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);