Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / compilerplugins / clang / redundantpointerops.cxx
blobcaf6d47411706d5d3f0208274e7e3b70d2897c16
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9 #ifndef LO_CLANG_SHARED_PLUGINS
11 #include <cassert>
12 #include <string>
13 #include <iostream>
14 #include <fstream>
15 #include <set>
17 #include <clang/AST/CXXInheritance.h>
19 #include "check.hxx"
20 #include "plugin.hxx"
22 /**
23 * Look for:
24 * (&x)->y
25 * which can be transformed to:
26 * x.y
27 * And
28 * &*x
29 * which can be:
30 * x
32 * @TODO
33 * (*x).y
34 * which can be:
35 * x->y
38 namespace {
40 class RedundantPointerOps:
41 public loplugin::FilteringPlugin<RedundantPointerOps>
43 public:
44 explicit RedundantPointerOps(loplugin::InstantiationData const & data): FilteringPlugin(data) {}
46 virtual void run() override
48 if (preRun())
49 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
52 bool VisitFunctionDecl(FunctionDecl const *);
53 bool VisitMemberExpr(MemberExpr const *);
54 bool VisitUnaryOperator(UnaryOperator const *);
57 bool RedundantPointerOps::VisitFunctionDecl(FunctionDecl const * functionDecl)
59 if (ignoreLocation(functionDecl))
60 return true;
61 // if (functionDecl->getIdentifier() && functionDecl->getName() == "function6b")
62 // functionDecl->dump();
63 return true;
66 bool RedundantPointerOps::VisitMemberExpr(MemberExpr const * memberExpr)
68 if (ignoreLocation(memberExpr))
69 return true;
70 if (memberExpr->getBeginLoc().isMacroID())
71 return true;
72 auto base = memberExpr->getBase()->IgnoreParenImpCasts();
73 //parentStmt(parentStmt(memberExpr))->dump();
74 if (memberExpr->isArrow())
76 if (auto unaryOp = dyn_cast<UnaryOperator>(base))
78 if (unaryOp->getOpcode() == UO_AddrOf)
79 report(
80 DiagnosticsEngine::Warning,
81 "'&' followed by '->' operating on %0, rather use '.'",
82 memberExpr->getBeginLoc())
83 << memberExpr->getBase()->getType()->getPointeeType()
84 << memberExpr->getSourceRange();
87 else if (auto operatorCallExpr = dyn_cast<CXXOperatorCallExpr>(base))
89 if (operatorCallExpr->getOperator() == OO_Amp)
90 report(
91 DiagnosticsEngine::Warning,
92 "'&' followed by '->' operating on %0, rather use '.'",
93 memberExpr->getBeginLoc())
94 << memberExpr->getBase()->getType()->getPointeeType()
95 << memberExpr->getSourceRange();
98 else if (auto cxxMemberCallExpr = dyn_cast<CXXMemberCallExpr>(base))
100 auto methodDecl = cxxMemberCallExpr->getMethodDecl();
101 if (methodDecl->getIdentifier() && methodDecl->getName() == "get")
103 auto const e = cxxMemberCallExpr->getImplicitObjectArgument();
104 if (loplugin::isSmartPointerType(e))
105 report(
106 DiagnosticsEngine::Warning,
107 "'get()' followed by '->' operating on %0, just use '->'",
108 memberExpr->getBeginLoc())
109 << e->IgnoreImpCasts()->getType().getLocalUnqualifiedType()
110 << memberExpr->getSourceRange();
114 // else
115 // {
116 // if (auto unaryOp = dyn_cast<UnaryOperator>(base))
117 // {
118 // if (unaryOp->getOpcode() == UO_Deref)
119 // report(
120 // DiagnosticsEngine::Warning, "'*' followed by '.', rather use '->'",
121 // memberExpr->getLocStart())
122 // << memberExpr->getSourceRange();
124 // }
125 // }
126 return true;
129 bool RedundantPointerOps::VisitUnaryOperator(UnaryOperator const * unaryOperator)
131 if (ignoreLocation(unaryOperator))
132 return true;
133 if (unaryOperator->getBeginLoc().isMacroID())
134 return true;
135 if (unaryOperator->getOpcode() != UO_Deref)
136 return true;
137 auto subExpr = unaryOperator->getSubExpr()->IgnoreParenImpCasts();
138 auto innerOp = dyn_cast<UnaryOperator>(subExpr);
139 if (innerOp && innerOp->getOpcode() == UO_AddrOf)
140 report(
141 DiagnosticsEngine::Warning, "'&' followed by '*' operating on %0, rather use '.'",
142 unaryOperator->getBeginLoc())
143 << innerOp->getSubExpr()->getType() << unaryOperator->getSourceRange();
144 if (auto cxxMemberCallExpr = dyn_cast<CXXMemberCallExpr>(subExpr))
146 auto methodDecl = cxxMemberCallExpr->getMethodDecl();
147 if (methodDecl->getIdentifier() && methodDecl->getName() == "get")
149 auto const e = cxxMemberCallExpr->getImplicitObjectArgument();
150 if (loplugin::isSmartPointerType(e))
151 report(
152 DiagnosticsEngine::Warning,
153 "'*' followed by '.get()' operating on %0, just use '*'",
154 unaryOperator->getBeginLoc())
155 << e->IgnoreImpCasts()->getType().getLocalUnqualifiedType()
156 << unaryOperator->getSourceRange();
159 return true;
162 loplugin::Plugin::Registration< RedundantPointerOps > redundantpointerops("redundantpointerops");
164 } // namespace
166 #endif // LO_CLANG_SHARED_PLUGINS
168 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */