--------------------------------------------------------------------------- Find consecutive return, break, continue, goto or throw statements. e.g.: break; break; Detect dead code, that follows such a statement. e.g.: return(0); foo(); ---------------------------------------------------------------------------
| 1006 | // return(0); foo(); |
| 1007 | //--------------------------------------------------------------------------- |
| 1008 | void CheckOtherImpl::checkUnreachableCode() |
| 1009 | { |
| 1010 | // misra-c-2012-2.1 |
| 1011 | // misra-c-2023-2.1 |
| 1012 | // misra-cpp-2008-0-1-1 |
| 1013 | // autosar |
| 1014 | if (!mSettings.severity.isEnabled(Severity::style) && !mSettings.isPremiumEnabled("duplicateBreak") && !mSettings.isPremiumEnabled("unreachableCode")) |
| 1015 | return; |
| 1016 | |
| 1017 | logChecker("CheckOther::checkUnreachableCode"); // style |
| 1018 | |
| 1019 | const bool printInconclusive = mSettings.certainty.isEnabled(Certainty::inconclusive); |
| 1020 | const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 1021 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 1022 | if (scope->hasInlineOrLambdaFunction(nullptr, /*onlyInline*/ true)) |
| 1023 | continue; |
| 1024 | for (const Token* tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { |
| 1025 | const Token* secondBreak = nullptr; |
| 1026 | const Token* labelName = nullptr; |
| 1027 | if (tok->link() && Token::Match(tok, "(|[|<")) |
| 1028 | tok = tok->link(); |
| 1029 | else if (Token::Match(tok, "break|continue ;")) |
| 1030 | secondBreak = tok->tokAt(2); |
| 1031 | else if (Token::Match(tok, "[;{}:] return|throw") && tok->next()->isKeyword()) { |
| 1032 | if (Token::simpleMatch(tok->astParent(), "?")) |
| 1033 | continue; |
| 1034 | tok = tok->next(); // tok should point to return or throw |
| 1035 | for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { |
| 1036 | if (tok2->str() == "(" || tok2->str() == "{") |
| 1037 | tok2 = tok2->link(); |
| 1038 | if (tok2->str() == ";") { |
| 1039 | secondBreak = tok2->next(); |
| 1040 | break; |
| 1041 | } |
| 1042 | } |
| 1043 | } else if (Token::Match(tok, "goto %any% ;")) { |
| 1044 | secondBreak = tok->tokAt(3); |
| 1045 | labelName = tok->next(); |
| 1046 | } else if (Token::Match(tok, "%name% (") && mSettings.library.isnoreturn(tok) && !Token::Match(tok->next()->astParent(), "?|:")) { |
| 1047 | if ((!tok->function() || (tok->function()->token != tok && tok->function()->tokenDef != tok)) && tok->linkAt(1)->strAt(1) != "{") |
| 1048 | secondBreak = tok->linkAt(1)->tokAt(2); |
| 1049 | if (Token::simpleMatch(secondBreak, "return")) { |
| 1050 | // clarification for tools that function returns |
| 1051 | continue; |
| 1052 | } |
| 1053 | } |
| 1054 | while (Token::simpleMatch(secondBreak, "}") && secondBreak->scope()->type == ScopeType::eUnconditional) |
| 1055 | secondBreak = secondBreak->next(); |
| 1056 | if (secondBreak && secondBreak->scope()->nestedIn && secondBreak->scope()->nestedIn->type == ScopeType::eSwitch && |
| 1057 | tok->str() == "break") { |
| 1058 | while (Token::simpleMatch(secondBreak, "{") && secondBreak->scope()->type == ScopeType::eUnconditional) |
| 1059 | secondBreak = secondBreak->next(); |
| 1060 | } |
| 1061 | while (Token::simpleMatch(secondBreak, ";")) |
| 1062 | secondBreak = secondBreak->next(); |
| 1063 | |
| 1064 | // Statements follow directly, no line between them. (#3383) |
| 1065 | // TODO: Try to find a better way to avoid false positives due to preprocessor configurations. |
no test coverage detected