missingReturn; Fixed false positives
This commit is contained in:
parent
9fc5b9472d
commit
c6f7a78ebb
|
@ -271,21 +271,26 @@ void CheckFunctions::checkMissingReturn()
|
||||||
|
|
||||||
static const Token *checkMissingReturnScope(const Token *tok)
|
static const Token *checkMissingReturnScope(const Token *tok)
|
||||||
{
|
{
|
||||||
tok = tok->previous();
|
const Token *lastStatement = nullptr;
|
||||||
while (tok) {
|
while ((tok = tok->previous()) != nullptr) {
|
||||||
if (tok->str() == "{")
|
if (tok->str() == "{")
|
||||||
return tok->next();
|
return lastStatement ? lastStatement : tok->next();
|
||||||
if (tok->str() == "}") {
|
if (tok->str() == "}") {
|
||||||
for (const Token *prev = tok->link()->previous(); prev && prev->scope() == tok->scope() && !Token::Match(prev, "[;{}]"); prev = prev->previous()) {
|
for (const Token *prev = tok->link()->previous(); prev && prev->scope() == tok->scope() && !Token::Match(prev, "[;{}]"); prev = prev->previous()) {
|
||||||
if (prev->isKeyword() && Token::Match(prev, "return|throw"))
|
if (prev->isKeyword() && Token::Match(prev, "return|throw"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (tok->scope()->type == Scope::ScopeType::eSwitch) {
|
if (tok->scope()->type == Scope::ScopeType::eSwitch) {
|
||||||
// find break/default
|
// find reachable break / !default
|
||||||
bool hasDefault = false;
|
bool hasDefault = false;
|
||||||
|
bool reachable = false;
|
||||||
for (const Token *switchToken = tok->link(); switchToken != tok; switchToken = switchToken->next()) {
|
for (const Token *switchToken = tok->link(); switchToken != tok; switchToken = switchToken->next()) {
|
||||||
if (Token::simpleMatch(switchToken, "break ;"))
|
if (reachable && Token::simpleMatch(switchToken, "break ;"))
|
||||||
return switchToken;
|
return switchToken;
|
||||||
|
if (switchToken->isKeyword() && Token::Match(switchToken, "return|throw"))
|
||||||
|
reachable = false;
|
||||||
|
if (Token::Match(switchToken, "case|default"))
|
||||||
|
reachable = true;
|
||||||
if (Token::simpleMatch(switchToken, "default :"))
|
if (Token::simpleMatch(switchToken, "default :"))
|
||||||
hasDefault = true;
|
hasDefault = true;
|
||||||
else if (switchToken->str() == "{" && switchToken->scope()->isLoopScope())
|
else if (switchToken->str() == "{" && switchToken->scope()->isLoopScope())
|
||||||
|
@ -309,9 +314,8 @@ static const Token *checkMissingReturnScope(const Token *tok)
|
||||||
}
|
}
|
||||||
if (tok->isKeyword() && Token::Match(tok, "return|throw"))
|
if (tok->isKeyword() && Token::Match(tok, "return|throw"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (Token::Match(tok, "; !!}"))
|
if (Token::Match(tok, "; !!}") && !lastStatement)
|
||||||
return tok->next();
|
lastStatement = tok->next();
|
||||||
tok = tok->previous();
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,12 +385,6 @@ public:
|
||||||
mTokType == eBoolean || mTokType == eLiteral || mTokType == eEnumerator);
|
mTokType == eBoolean || mTokType == eLiteral || mTokType == eEnumerator);
|
||||||
setFlag(fIsLiteral, memoizedIsLiteral);
|
setFlag(fIsLiteral, memoizedIsLiteral);
|
||||||
}
|
}
|
||||||
void isKeyword(const bool kwd) {
|
|
||||||
if (kwd)
|
|
||||||
tokType(eKeyword);
|
|
||||||
else if (mTokType == eKeyword)
|
|
||||||
tokType(eName);
|
|
||||||
}
|
|
||||||
bool isKeyword() const {
|
bool isKeyword() const {
|
||||||
return mTokType == eKeyword;
|
return mTokType == eKeyword;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1379,6 +1379,13 @@ private:
|
||||||
check("auto foo4() -> void {}");
|
check("auto foo4() -> void {}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// unreachable code..
|
||||||
|
check("int foo(int x) {\n"
|
||||||
|
" return 1;\n"
|
||||||
|
" (void)x;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// switch
|
// switch
|
||||||
check("int f() {\n"
|
check("int f() {\n"
|
||||||
" switch (x) {\n"
|
" switch (x) {\n"
|
||||||
|
@ -1388,6 +1395,14 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
|
||||||
|
|
||||||
|
check("int f() {\n"
|
||||||
|
" switch (x) {\n"
|
||||||
|
" case 1: return 2; break;\n"
|
||||||
|
" default: return 1;\n"
|
||||||
|
" }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// if/else
|
// if/else
|
||||||
check("int f(int x) {\n"
|
check("int f(int x) {\n"
|
||||||
" if (x) {\n"
|
" if (x) {\n"
|
||||||
|
|
Loading…
Reference in New Issue