summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/redundantpointerops.cxx
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2019-10-09 23:25:02 +0200
committerStephan Bergmann <sbergman@redhat.com>2019-10-10 08:41:06 +0200
commitc874294ad9fb178df47c66875bfbdec466e39763 (patch)
tree971d04af65ad062001134009dd5a0c49a48e90d0 /compilerplugins/clang/redundantpointerops.cxx
parent4c9cf046be055affee94a533f9db67f6fb0702cb (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.cxx38
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();
}
}