diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2019-10-09 23:25:02 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2019-10-10 08:41:06 +0200 |
commit | c874294ad9fb178df47c66875bfbdec466e39763 (patch) | |
tree | 971d04af65ad062001134009dd5a0c49a48e90d0 /compilerplugins/clang/redundantpointerops.cxx | |
parent | 4c9cf046be055affee94a533f9db67f6fb0702cb (diff) |
Fix detection of std::unique_ptr/shared_ptr in loplugin:redundantpointerops
...when the get member function is implemented in a base class, as happens for
std::shared_ptr in libstdc++ (where it is implemented in base __shared_ptr; see
also 7d361e96c9ea822790db21806e9fc05279423833 "loplugin:redundantpointerops").
And while at it, check for precisely the classes we are interested in (for which
we know the semantics of get and operator*), rather than any classes whose
unqualified names happen to match.
Change-Id: I0c85ba46f191a2ee038c8175d979aa0c1be765cd
Reviewed-on: https://gerrit.libreoffice.org/80585
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'compilerplugins/clang/redundantpointerops.cxx')
-rw-r--r-- | compilerplugins/clang/redundantpointerops.cxx | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/compilerplugins/clang/redundantpointerops.cxx b/compilerplugins/clang/redundantpointerops.cxx index dbb3ef7882fd..e2a97bc64350 100644 --- a/compilerplugins/clang/redundantpointerops.cxx +++ b/compilerplugins/clang/redundantpointerops.cxx @@ -15,6 +15,8 @@ #include <set> #include <clang/AST/CXXInheritance.h> + +#include "check.hxx" #include "compat.hxx" #include "plugin.hxx" @@ -129,13 +131,35 @@ bool RedundantPointerOps::VisitUnaryOperator(UnaryOperator const * unaryOperator auto methodDecl = cxxMemberCallExpr->getMethodDecl(); if (methodDecl->getIdentifier() && methodDecl->getName() == "get") { - auto className = cxxMemberCallExpr->getRecordDecl()->getName(); - if (className == "unique_ptr" || className == "shared_ptr" || className == "Reference" || className == "SvRef") - report( - DiagnosticsEngine::Warning, - "'*' followed by '.get()' operating on %0, just use '*'", - compat::getBeginLoc(unaryOperator)) - << compat::getObjectType(cxxMemberCallExpr) << unaryOperator->getSourceRange(); + auto const e = cxxMemberCallExpr->getImplicitObjectArgument(); + // First check the object type as written, in case the get member function is + // declared at a base class of std::unique_ptr or std::shared_ptr: + auto const t = e->IgnoreImpCasts()->getType(); + auto const tc1 = loplugin::TypeCheck(t); + if (!(tc1.ClassOrStruct("unique_ptr").StdNamespace() + || tc1.ClassOrStruct("shared_ptr").StdNamespace())) + { + // Then check the object type coerced to the type of the get member function, in + // case the type-as-written is derived from one of these types (tools::SvRef is + // final, but the rest are not; but note that this will fail when the type-as- + // written is derived from std::unique_ptr or std::shared_ptr for which the get + // member function is declared at a base class): + auto const tc2 = loplugin::TypeCheck(e->getType()); + if (!((tc2.ClassOrStruct("unique_ptr").StdNamespace() + || tc2.ClassOrStruct("shared_ptr").StdNamespace() + || (tc2.Class("Reference").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace()) + || tc2.Class("Reference").Namespace("rtl").GlobalNamespace() + || tc2.Class("SvRef").Namespace("tools").GlobalNamespace()))) + { + return true; + } + } + report( + DiagnosticsEngine::Warning, + "'*' followed by '.get()' operating on %0, just use '*'", + compat::getBeginLoc(unaryOperator)) + << t.getLocalUnqualifiedType() << unaryOperator->getSourceRange(); } } |