missing return; write inconclusive error if function ends with unknown function-like macro
This commit is contained in:
parent
02682ab17d
commit
9362c1fc6c
|
@ -252,6 +252,7 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib
|
||||||
|
|
||||||
void CheckFunctions::checkMissingReturn()
|
void CheckFunctions::checkMissingReturn()
|
||||||
{
|
{
|
||||||
|
const bool inconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive);
|
||||||
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
||||||
for (const Scope *scope : symbolDatabase->functionScopes) {
|
for (const Scope *scope : symbolDatabase->functionScopes) {
|
||||||
const Function *function = scope->function;
|
const Function *function = scope->function;
|
||||||
|
@ -266,8 +267,20 @@ void CheckFunctions::checkMissingReturn()
|
||||||
if (Function::returnsVoid(function, true))
|
if (Function::returnsVoid(function, true))
|
||||||
continue;
|
continue;
|
||||||
const Token *errorToken = checkMissingReturnScope(scope->bodyEnd, mSettings->library);
|
const Token *errorToken = checkMissingReturnScope(scope->bodyEnd, mSettings->library);
|
||||||
if (errorToken)
|
if (errorToken) {
|
||||||
missingReturnError(errorToken);
|
missingReturnError(errorToken);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inconclusive && Token::simpleMatch(scope->bodyEnd->tokAt(-2), ") ; }")) {
|
||||||
|
const Token *ftok = scope->bodyEnd->linkAt(-2)->previous();
|
||||||
|
if (mSettings->library.isNotLibraryFunction(ftok)) {
|
||||||
|
const Token *tok = ftok;
|
||||||
|
while (Token::Match(tok->tokAt(-2), "%name% :: %name%"))
|
||||||
|
tok = tok->tokAt(-2);
|
||||||
|
if (Token::Match(tok->previous(), "[;{}] %name% (|::"))
|
||||||
|
missingReturnError(tok, Certainty::inconclusive);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,8 +351,13 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (tok->str() == "goto" && !isForwardJump(tok))
|
if (tok->str() == "goto" && !isForwardJump(tok))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (Token::Match(tok, "%name% (") && !library.isnotnoreturn(tok))
|
if (Token::Match(tok, "%name% (") && !library.isnotnoreturn(tok)) {
|
||||||
|
const Token *start = tok;
|
||||||
|
while (Token::Match(start->tokAt(-2), "%name% :: %name%"))
|
||||||
|
start = start->tokAt(-2);
|
||||||
|
if (Token::Match(start->previous(), "[;{}] %name% ::|("))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
if (Token::Match(tok, "[;{}] %name% :"))
|
if (Token::Match(tok, "[;{}] %name% :"))
|
||||||
return tok;
|
return tok;
|
||||||
if (Token::Match(tok, "; !!}") && !lastStatement)
|
if (Token::Match(tok, "; !!}") && !lastStatement)
|
||||||
|
@ -348,10 +366,10 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckFunctions::missingReturnError(const Token* tok)
|
void CheckFunctions::missingReturnError(const Token* tok, Certainty::CertaintyLevel certainty)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error, "missingReturn",
|
reportError(tok, Severity::error, "missingReturn",
|
||||||
"Found a exit path from function with non-void return type that has missing return statement", CWE758, Certainty::normal);
|
"Found a exit path from function with non-void return type that has missing return statement", CWE758, certainty);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Detect passing wrong values to <cmath> functions like atan(0, x);
|
// Detect passing wrong values to <cmath> functions like atan(0, x);
|
||||||
|
|
|
@ -122,7 +122,7 @@ private:
|
||||||
void memsetZeroBytesError(const Token *tok);
|
void memsetZeroBytesError(const Token *tok);
|
||||||
void memsetFloatError(const Token *tok, const std::string &var_value);
|
void memsetFloatError(const Token *tok, const std::string &var_value);
|
||||||
void memsetValueOutOfRangeError(const Token *tok, const std::string &value);
|
void memsetValueOutOfRangeError(const Token *tok, const std::string &value);
|
||||||
void missingReturnError(const Token *tok);
|
void missingReturnError(const Token *tok, Certainty::CertaintyLevel certainty=Certainty::normal);
|
||||||
void copyElisionError(const Token *tok);
|
void copyElisionError(const Token *tok);
|
||||||
|
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE {
|
||||||
|
|
|
@ -39,6 +39,7 @@ private:
|
||||||
settings.severity.enable(Severity::warning);
|
settings.severity.enable(Severity::warning);
|
||||||
settings.severity.enable(Severity::performance);
|
settings.severity.enable(Severity::performance);
|
||||||
settings.severity.enable(Severity::portability);
|
settings.severity.enable(Severity::portability);
|
||||||
|
settings.certainty.enable(Certainty::inconclusive);
|
||||||
settings.libraries.emplace_back("posix");
|
settings.libraries.emplace_back("posix");
|
||||||
settings.standards.c = Standards::C11;
|
settings.standards.c = Standards::C11;
|
||||||
settings.standards.cpp = Standards::CPP11;
|
settings.standards.cpp = Standards::CPP11;
|
||||||
|
@ -1490,7 +1491,11 @@ private:
|
||||||
|
|
||||||
check("int f(int x) { assert(0); }");
|
check("int f(int x) { assert(0); }");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("int f(int x) { RETURN(0); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (error, inconclusive) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// NRVO check
|
// NRVO check
|
||||||
void returnLocalStdMove1() {
|
void returnLocalStdMove1() {
|
||||||
check("struct A{}; A f() { A var; return std::move(var); }");
|
check("struct A{}; A f() { A var; return std::move(var); }");
|
||||||
|
|
Loading…
Reference in New Issue