1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
9 #ifndef LO_CLANG_SHARED_PLUGINS
17 #include <clang/AST/CXXInheritance.h>
19 #include "config_clang.h"
25 * look for places we can use std::make_shared
30 class MakeShared
: public loplugin::FilteringPlugin
<MakeShared
>
33 explicit MakeShared(loplugin::InstantiationData
const& data
)
34 : FilteringPlugin(data
)
38 virtual bool preRun() override
40 StringRef
fn(handler
.getMainFileName());
41 // TODO something weird with protected base classes going on here
42 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/filter/excel/xeextlst.cxx"))
44 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/filter/excel/xecontent.cxx"))
46 // no idea what is going on here
47 if (loplugin::isSamePathname(fn
, SRCDIR
"/svx/source/sidebar/nbdtmg.cxx"))
50 // legitimate use of moving std::unique_ptr to std::shared_ptr
51 if (loplugin::isSamePathname(fn
, SRCDIR
"/comphelper/source/container/enumerablemap.cxx"))
53 if (loplugin::isSamePathname(fn
, SRCDIR
"/svl/source/items/style.cxx"))
55 if (loplugin::isSamePathname(fn
, SRCDIR
"/vcl/source/app/weldutils.cxx"))
57 if (loplugin::isSamePathname(fn
, SRCDIR
"/sfx2/source/appl/appopen.cxx"))
59 if (loplugin::isSamePathname(fn
, SRCDIR
"/svx/source/table/tablertfimporter.cxx"))
61 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/ui/docshell/externalrefmgr.cxx"))
63 if (loplugin::isSamePathname(fn
, SRCDIR
"/sw/source/core/attr/swatrset.cxx"))
65 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/ui/condformat/condformatdlg.cxx"))
67 if (loplugin::isSamePathname(fn
, SRCDIR
"/sw/source/core/layout/frmtool.cxx"))
69 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/filter/excel/xihelper.cxx"))
71 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/filter/excel/xeformula.cxx"))
73 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/filter/excel/xichart.cxx"))
75 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/filter/html/htmlpars.cxx"))
77 if (loplugin::isSamePathname(fn
, SRCDIR
"/sc/source/ui/view/cellsh1.cxx"))
79 if (loplugin::isSamePathname(fn
, SRCDIR
"/sw/source/filter/html/htmltab.cxx"))
81 if (loplugin::isSamePathname(fn
, SRCDIR
"/sw/source/filter/ww8/docxattributeoutput.cxx"))
86 virtual void run() override
89 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
92 bool shouldVisitTemplateInstantiations() const { return true; }
94 bool VisitCXXConstructExpr(CXXConstructExpr
const*);
95 bool VisitCXXMemberCallExpr(CXXMemberCallExpr
const*);
96 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr
const*);
97 bool VisitVarDecl(VarDecl
const*);
100 bool MakeShared::VisitCXXConstructExpr(CXXConstructExpr
const* constructExpr
)
102 if (ignoreLocation(constructExpr
))
104 if (!loplugin::TypeCheck(constructExpr
->getType()).ClassOrStruct("shared_ptr").StdNamespace())
106 if (!(constructExpr
->getNumArgs() == 1
107 || (constructExpr
->getNumArgs() > 1 && isa
<CXXDefaultArgExpr
>(constructExpr
->getArg(1)))))
109 auto arg0
= constructExpr
->getArg(0)->IgnoreParenImpCasts();
110 auto cxxNewExpr
= dyn_cast
<CXXNewExpr
>(arg0
);
113 auto construct2
= cxxNewExpr
->getConstructExpr();
116 if (construct2
->getConstructor()->getAccess() != AS_public
)
118 if (construct2
->getNumArgs() == 1
119 && isa
<CXXStdInitializerListExpr
>(construct2
->getArg(0)))
123 else if (loplugin::TypeCheck(arg0
->getType()).ClassOrStruct("shared_ptr").StdNamespace())
125 else if (loplugin::TypeCheck(arg0
->getType()).ClassOrStruct("weak_ptr").StdNamespace())
127 else if (arg0
->getType()->isDependentType())
129 else if (isa
<CXXNullPtrLiteralExpr
>(arg0
))
131 else if (auto const call
= dyn_cast
<CallExpr
>(arg0
))
133 if (auto const decl
= call
->getDirectCallee())
135 // Don't warn about cases where e.g. the Bitmap* result of calling Windows'
136 // Bitmap::FromBITMAPINFO is wrapped in a shared_ptr:
137 if (decl
->getReturnType()->isPointerType()
138 && compiler
.getSourceManager().isInSystemHeader(decl
->getLocation()))
145 StringRef fn
= getFilenameOfLocation(
146 compiler
.getSourceManager().getSpellingLoc(constructExpr
->getBeginLoc()));
147 if (loplugin::isSamePathname(fn
, SRCDIR
"/include/o3tl/make_shared.hxx"))
149 if (loplugin::isSamePathname(fn
, SRCDIR
"/svl/source/items/stylepool.cxx"))
152 report(DiagnosticsEngine::Warning
, "rather use make_shared than constructing from %0",
153 constructExpr
->getBeginLoc())
154 << arg0
->getType() << constructExpr
->getSourceRange();
158 bool MakeShared::VisitCXXMemberCallExpr(CXXMemberCallExpr
const* cxxMemberCallExpr
)
160 if (ignoreLocation(cxxMemberCallExpr
))
163 if (cxxMemberCallExpr
->getNumArgs() != 1)
166 // cannot find a way to use the loplugin::DeclCheck stuff here
168 = dyn_cast
<ClassTemplateSpecializationDecl
>(cxxMemberCallExpr
->getRecordDecl());
171 auto cxxRecordDecl
= templateDecl
->getSpecializedTemplate()->getTemplatedDecl();
172 if (!cxxRecordDecl
->getName().contains("shared_ptr"))
175 if (auto const id
= cxxMemberCallExpr
->getMethodDecl()->getIdentifier())
177 if (id
->getName() != "reset")
180 auto cxxNewExpr
= dyn_cast
<CXXNewExpr
>(cxxMemberCallExpr
->getArg(0)->IgnoreParenImpCasts());
183 if (cxxNewExpr
->getConstructExpr()
184 && cxxNewExpr
->getConstructExpr()->getConstructor()->getAccess() != AS_public
)
187 StringRef fn
= getFilenameOfLocation(
188 compiler
.getSourceManager().getSpellingLoc(cxxMemberCallExpr
->getBeginLoc()));
189 if (loplugin::isSamePathname(fn
, SRCDIR
"/include/o3tl/make_shared.hxx"))
192 report(DiagnosticsEngine::Warning
, "rather use make_shared", cxxNewExpr
->getBeginLoc())
193 << cxxNewExpr
->getSourceRange();
198 bool MakeShared::VisitCXXOperatorCallExpr(CXXOperatorCallExpr
const* operCallExpr
)
200 if (ignoreLocation(operCallExpr
))
202 if (!operCallExpr
->isAssignmentOp())
205 if (!loplugin::TypeCheck(operCallExpr
->getType()).ClassOrStruct("shared_ptr").StdNamespace())
208 if (loplugin::TypeCheck(operCallExpr
->getArg(1)->getType())
209 .ClassOrStruct("shared_ptr")
213 report(DiagnosticsEngine::Warning
, "rather use make_shared than constructing from %0",
214 operCallExpr
->getBeginLoc())
215 << operCallExpr
->getArg(1)->getType() << operCallExpr
->getSourceRange();
220 bool MakeShared::VisitVarDecl(VarDecl
const* varDecl
)
222 if (ignoreLocation(varDecl
))
224 if (!varDecl
->hasInit())
227 if (!loplugin::TypeCheck(varDecl
->getType()).ClassOrStruct("shared_ptr").StdNamespace())
230 if (varDecl
->getInit()->getType().isNull())
232 if (varDecl
->getInit()->getType()->isDependentType())
234 if (loplugin::TypeCheck(varDecl
->getInit()->IgnoreParenImpCasts()->getType())
235 .ClassOrStruct("shared_ptr")
239 report(DiagnosticsEngine::Warning
, "rather use make_shared than constructing from %0",
240 varDecl
->getBeginLoc())
241 << varDecl
->getInit()->getType() << varDecl
->getSourceRange();
246 loplugin::Plugin::Registration
<MakeShared
> makeshared("makeshared", false);
250 #endif // LO_CLANG_SHARED_PLUGINS
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */