summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2016-07-15 12:26:27 +0200
committerStephan Bergmann <sbergman@redhat.com>2016-07-15 14:08:07 +0000
commit018e89337d18e5aa153faae5b3df41188d1c174c (patch)
treeda48d5c39425ed43a04a376315bbf7f24621991d /compilerplugins
parent5a3653f87502e40cf00d8f1ed1c0ecf5a979e67d (diff)
Improve loplugin:unnecessaryoverride
<sberg> thorsten, remember what that "TODO" in SvxAccessibleTextPropertySet::getSupportedServiceNames was to be about exactly, in a909acb7009acadffa53e74ea05ddb88803490f1 ? <thorsten> sberg: that's a nonsense, prolly copy'n'pasted, or a 'please review me' <sberg> thorsten, OK, thanks (that override will eventually go away with loplugin:unnecessaryoverride, and the TODO comment be lost) Change-Id: Iba964c61768459aac4067bbd4e1f7d4f78f6adac Reviewed-on: https://gerrit.libreoffice.org/27232 Reviewed-by: Stephan Bergmann <sbergman@redhat.com> Tested-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/unnecessaryoverride.cxx62
1 files changed, 55 insertions, 7 deletions
diff --git a/compilerplugins/clang/unnecessaryoverride.cxx b/compilerplugins/clang/unnecessaryoverride.cxx
index 8a882af9c362..06a468c0f61d 100644
--- a/compilerplugins/clang/unnecessaryoverride.cxx
+++ b/compilerplugins/clang/unnecessaryoverride.cxx
@@ -12,6 +12,8 @@
#include <iostream>
#include <fstream>
#include <set>
+
+#include "compat.hxx"
#include "plugin.hxx"
/**
@@ -67,16 +69,61 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
const CXXMethodDecl* overriddenMethodDecl = *methodDecl->begin_overridden_methods();
+ if (compat::getReturnType(*methodDecl).getCanonicalType()
+ != compat::getReturnType(*overriddenMethodDecl).getCanonicalType())
+ {
+ return true;
+ }
+ //TODO: check for identical exception specifications
+
const CompoundStmt* compoundStmt = dyn_cast<CompoundStmt>(methodDecl->getBody());
if (!compoundStmt || compoundStmt->size() != 1)
return true;
- const Stmt* firstStmt = compoundStmt->body_front();
- if (const ReturnStmt* returnStmt = dyn_cast<ReturnStmt>(firstStmt)) {
- firstStmt = returnStmt->getRetValue();
+ auto returnStmt = dyn_cast<ReturnStmt>(compoundStmt->body_front());
+ if (returnStmt == nullptr) {
+ return true;
}
- if (!firstStmt)
+ auto returnExpr = returnStmt->getRetValue();
+ if (returnExpr == nullptr) {
return true;
- const CXXMemberCallExpr* callExpr = dyn_cast<CXXMemberCallExpr>(firstStmt);
+ }
+ returnExpr = returnExpr->IgnoreImplicit();
+
+ // In something like
+ //
+ // Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery(
+ // const rtl::OUString& sql)
+ // throw(SQLException, RuntimeException, std::exception)
+ // {
+ // return OCommonStatement::executeQuery( sql );
+ // }
+ //
+ // look down through all the
+ //
+ // ReturnStmt
+ // `-ExprWithCleanups
+ // `-CXXConstructExpr
+ // `-MaterializeTemporaryExpr
+ // `-ImplicitCastExpr
+ // `-CXXBindTemporaryExpr
+ // `-CXXMemberCallExpr
+ //
+ // where the fact that the overriding and overridden function have identical
+ // return types makes us confident that all we need to check here is whether
+ // there's an (arbitrary, one-argument) CXXConstructorExpr and
+ // CXXBindTemporaryExpr in between:
+ if (auto ctorExpr = dyn_cast<CXXConstructExpr>(returnExpr)) {
+ if (ctorExpr->getNumArgs() == 1) {
+ if (auto tempExpr = dyn_cast<CXXBindTemporaryExpr>(
+ ctorExpr->getArg(0)->IgnoreImplicit()))
+ {
+ returnExpr = tempExpr->getSubExpr();
+ }
+ }
+ }
+
+ const CXXMemberCallExpr* callExpr = dyn_cast<CXXMemberCallExpr>(
+ returnExpr->IgnoreParenImpCasts());
if (!callExpr || callExpr->getMethodDecl() != overriddenMethodDecl)
return true;
const ImplicitCastExpr* expr1 = dyn_cast_or_null<ImplicitCastExpr>(callExpr->getImplicitObjectArgument());
@@ -92,9 +139,10 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
}
report(
- DiagnosticsEngine::Warning, "method just calls parent method",
+ DiagnosticsEngine::Warning, "%0 virtual function just calls %1 parent",
methodDecl->getSourceRange().getBegin())
- << methodDecl->getSourceRange();
+ << methodDecl->getAccess() << overriddenMethodDecl->getAccess()
+ << methodDecl->getSourceRange();
if (methodDecl->getCanonicalDecl()->getLocation() != methodDecl->getLocation()) {
const CXXMethodDecl* pOther = methodDecl->getCanonicalDecl();
report(