improve unnecessarycatchthrow plugin

it is not legal to eliminate a catch/re-throw where the re-throw
expliciting mentions the exception variable and the exception variable
is a non-final class

Change-Id: I7fd88b0d004d2efa66aef2c0876e07f203da3c28
Reviewed-on: https://gerrit.libreoffice.org/42782
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin 2017-09-26 09:53:13 +02:00
parent cae3350917
commit ade2769232
2 changed files with 32 additions and 0 deletions

View file

@ -30,6 +30,29 @@ int main()
std::cout << "test";
throw;
}
}
void test1()
{
// cannot remove catch/throw where the throw is of a non-final class
struct B {};
struct D: B {};
try {
throw D();
} catch (B & b) {
throw b; // must not be removed
}
};
void test2()
{
struct F final {};
try {
throw F();
} catch (F const & f) { // expected-error {{unnecessary catch and throw [loplugin:unnecessarycatchthrow]}}
throw f;
}
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -58,6 +58,15 @@ bool UnnecessaryCatchThrow::VisitCXXTryStmt(CXXTryStmt const * tryStmt)
auto subExpr = throwExpr->getSubExpr();
if (subExpr)
{
if (auto cxxConstructExpr = dyn_cast<CXXConstructExpr>(subExpr)) {
if (!cxxConstructExpr->getConstructor()->isCopyConstructor())
return true;
if (!cxxConstructExpr->getConstructor()->getParent()->hasAttr<FinalAttr>())
return true;
if (cxxConstructExpr->getNumArgs() != 1)
return true;
subExpr = cxxConstructExpr->getArg(0);
}
auto declRefExpr = dyn_cast<DeclRefExpr>(subExpr->IgnoreImpCasts());
if (!declRefExpr)
return true;