--------------------------------------------------------------------------- catch(const exception & err) { throw err; // <- should be just "throw;" } ---------------------------------------------------------------------------
| 164 | // } |
| 165 | //--------------------------------------------------------------------------- |
| 166 | void CheckExceptionSafetyImpl::checkRethrowCopy() |
| 167 | { |
| 168 | if (!mSettings.severity.isEnabled(Severity::style) && !mSettings.isPremiumEnabled("exceptRethrowCopy")) |
| 169 | return; |
| 170 | |
| 171 | logChecker("CheckExceptionSafety::checkRethrowCopy"); // style |
| 172 | |
| 173 | const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 174 | |
| 175 | for (const Scope &scope : symbolDatabase->scopeList) { |
| 176 | if (scope.type != ScopeType::eCatch) |
| 177 | continue; |
| 178 | |
| 179 | const unsigned int varid = scope.bodyStart->tokAt(-2)->varId(); |
| 180 | if (varid) { |
| 181 | for (const Token* tok = scope.bodyStart->next(); tok && tok != scope.bodyEnd; tok = tok->next()) { |
| 182 | if (Token::simpleMatch(tok, "catch (") && tok->linkAt(1) && tok->linkAt(1)->next()) { // Don't check inner catch - it is handled in another iteration of outer loop. |
| 183 | tok = tok->linkAt(1)->linkAt(1); |
| 184 | if (!tok) |
| 185 | break; |
| 186 | } else if (Token::Match(tok, "%varid% .", varid)) { |
| 187 | const Token *parent = tok->astParent(); |
| 188 | while (Token::simpleMatch(parent->astParent(), ".")) |
| 189 | parent = parent->astParent(); |
| 190 | if (Token::Match(parent->astParent(), "%assign%|++|--|(") && parent == parent->astParent()->astOperand1()) |
| 191 | break; |
| 192 | } else if (Token::Match(tok, "throw %varid% ;", varid)) |
| 193 | rethrowCopyError(tok, tok->strAt(1)); |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | void CheckExceptionSafetyImpl::rethrowCopyError(const Token * const tok, const std::string &varname) |
| 200 | { |
no test coverage detected