diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 556a7eccb..052fd4d4f 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -942,11 +942,9 @@ void CheckNullPointer::nullPointerByCheckAndDeRef() (Token::Match(tok2->link()->tokAt(-2), "[;{}.] %var% (") || Token::Match(tok2->link()->tokAt(-5), "[;{}] ( * %var% ) ("))) { // noreturn function? - // If inside null pointer check we unknown function call, we must - // assume that it can terminate the program and possible null pointer - // error wont ever happen. - if (tok2->strAt(2) == "}") { - if (!_settings->inconclusive) { + bool unknown = false; + if (_tokenizer->IsScopeNoReturn(tok2->tokAt(2), &unknown)) { + if (!unknown || !_settings->inconclusive) { break; } inconclusive = true; diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index df13977ea..4ed08b83a 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1097,11 +1097,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int *possibleInit = true; // might be a noreturn function.. - if (Token::simpleMatch(tok->tokAt(-2), ") ; }") && - Token::Match(tok->linkAt(-2)->tokAt(-2), "[;{}] %var% (") && - tok->linkAt(-2)->previous()->varId() == 0) { - ret = true; - } + if (_tokenizer->IsScopeNoReturn(tok)) + return true; break; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index f14c19d16..048171b15 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8380,7 +8380,38 @@ void Tokenizer::simplifyStd() // Helper functions for handling the tokens list //--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown) const +{ + if (unknown) + *unknown = false; + + if (Token::simpleMatch(endScopeToken->tokAt(-2), ") ; }")) { + const Token *tok = endScopeToken->linkAt(-2)->previous(); + + // function pointer call.. + if (tok && 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, "[;{}]")) { + if (unknown) + *unknown = true; + return true; + } + } + + return false; +} //--------------------------------------------------------------------------- diff --git a/lib/tokenize.h b/lib/tokenize.h index 88ce385a4..ba66b55ce 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -73,6 +73,14 @@ public: return !isC() && !isJavaOrCSharp(); } + /** + * Check if inner scope ends with a call to a noreturn function + * \param endScopeToken The '}' token + * \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' + */ + bool IsScopeNoReturn(const Token *endScopeToken, bool *unknown = 0) const; + /** * Tokenize code * @param code input stream for code, e.g.