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/.
20 Find destructors that only contain a single call to delete of a field. In which
21 case that field should really be managed by unique_ptr.
27 public loplugin::FilteringPlugin
<UseUniquePtr
>
30 explicit UseUniquePtr(loplugin::InstantiationData
const & data
):
31 FilteringPlugin(data
) {}
33 virtual void run() override
35 fn
= handler
.getMainFileName();
36 loplugin::normalizeDotDotInFilePath(fn
);
37 // can't change these because we pass them down to the SfxItemPool stuff
38 if (fn
== SRCDIR
"/sc/source/core/data/docpool.cxx")
40 // this just too clever for me
41 if (fn
== SRCDIR
"/sc/source/core/tool/chgtrack.cxx")
44 if (fn
== SRCDIR
"/pyuno/source/module/pyuno_runtime.cxx")
46 // m_pExampleSet here is very badly managed. sometimes it is owning, sometimes not,
47 // and the logic depends on overriding methods.
48 if (fn
== SRCDIR
"/sfx2/source/dialog/tabdlg.cxx")
50 // pLongArr is being deleted here because we temporarily overwrite a pointer to someone else's buffer, with a pointer
52 if (fn
== SRCDIR
"/editeng/source/misc/txtrange.cxx")
54 // can't use std::set<std::unique_ptr<>> until C++14
55 if (fn
== SRCDIR
"/editeng/source/misc/svxacorr.cxx")
57 // horrible horrible spawn of evil ownership and deletion here
58 if (fn
== SRCDIR
"/sfx2/source/view/ipclient.cxx")
60 // sometimes it owns, sometimes it doesn't
61 if (fn
== SRCDIR
"/editeng/source/misc/svxacorr.cxx")
63 // SwDoc::m_PageDescs has weird handling
64 if (fn
== SRCDIR
"/sw/source/core/doc/docnew.cxx")
66 // SwRedlineData::pNext and pExtraData have complex handling
67 if (fn
== SRCDIR
"/sw/source/core/doc/docredln.cxx")
69 // ScTempDocSource::pTempDoc
70 if (fn
== SRCDIR
"/sc/source/ui/unoobj/funcuno.cxx")
72 // SwAttrIter::m_pFont
73 if (fn
== SRCDIR
"/sw/source/core/text/itratr.cxx"
74 || fn
== SRCDIR
"/sw/source/core/text/redlnitr.cxx")
77 if (fn
== SRCDIR
"/sw/source/core/text/wrong.cxx")
79 // SwLineLayout::m_pNext
80 if (fn
== SRCDIR
"/sw/source/core/text/porlay.cxx")
82 // ODatabaseExport::m_aDestColumns
83 if (fn
== SRCDIR
"/dbaccess/source/ui/misc/DExport.cxx")
85 // ScTabView::pDrawActual and pDrawOld
86 if (fn
== SRCDIR
"/sc/source/ui/view/tabview5.cxx")
88 // SwHTMLParser::m_pPendStack
89 if (fn
== SRCDIR
"/sw/source/filter/html/htmlcss1.cxx")
91 // Visual Studio 2017 has trouble with these
92 if (fn
== SRCDIR
"/comphelper/source/property/MasterPropertySet.cxx"
93 || fn
== SRCDIR
"/comphelper/source/property/MasterPropertySetInfo.cxx")
95 // SwTableLine::m_aBoxes
96 if (fn
== SRCDIR
"/sw/source/core/table/swtable.cxx")
98 // SwHTMLParser::m_pFormImpl
99 if (fn
== SRCDIR
"/sw/source/filter/html/htmlform.cxx")
101 // SwHTMLParser::m_pPendStack, pNext
102 if (fn
== SRCDIR
"/sw/source/filter/html/htmltab.cxx")
104 // SaveLine::pBox, pNext
105 if (fn
== SRCDIR
"/sw/source/core/undo/untbl.cxx")
107 // RedlineInfo::pNextRedline
108 if (fn
== SRCDIR
"/sw/source/filter/xml/XMLRedlineImportHelper.cxx")
110 // SfxObjectShell::pMedium
111 if (fn
== SRCDIR
"/sfx2/source/doc/objxtor.cxx")
114 if (fn
== SRCDIR
"/sw/source/filter/ww8/wrtww8.cxx")
117 if (fn
== SRCDIR
"/sw/source/filter/ww8/ww8par2.cxx")
119 // ZipOutputStream, ownership of ZipEntry is horribly complicated here
120 if (fn
== SRCDIR
"/package/source/zipapi/ZipOutputStream.cxx")
123 if (fn
== SRCDIR
"/sal/rtl/locale.cxx")
125 // std::vector<ScLookupCacheMap*> is tricky, changing it would require moving lots of class definitions around
126 if (fn
== SRCDIR
"/sc/source/core/data/documen2.cxx"
127 || fn
== SRCDIR
"/sc/source/core/tool/interpretercontext.cxx")
130 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
133 bool VisitFunctionDecl(const FunctionDecl
* );
134 bool VisitCXXDeleteExpr(const CXXDeleteExpr
* );
135 bool TraverseFunctionDecl(FunctionDecl
* );
136 bool TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl
* );
137 bool TraverseCXXMethodDecl(CXXMethodDecl
* );
138 bool TraverseCXXConstructorDecl(CXXConstructorDecl
* );
139 bool TraverseCXXConversionDecl(CXXConversionDecl
* );
140 bool TraverseCXXDestructorDecl(CXXDestructorDecl
* );
141 bool TraverseConstructorInitializer(CXXCtorInitializer
*);
144 void CheckCompoundStmt(const FunctionDecl
*, const CompoundStmt
* );
145 void CheckIfStmt(const FunctionDecl
*, const IfStmt
* );
146 void CheckCXXForRangeStmt(const FunctionDecl
*, const CXXForRangeStmt
* );
147 void CheckLoopDelete(const FunctionDecl
*, const Stmt
* );
148 void CheckLoopDelete(const FunctionDecl
*, const CXXDeleteExpr
* );
149 void CheckDeleteExpr(const FunctionDecl
*, const CXXDeleteExpr
*);
150 void CheckDeleteLocalVar(const FunctionDecl
*, const CXXDeleteExpr
*, const VarDecl
*);
151 void CheckDeleteParmVar(const CXXDeleteExpr
*, const ParmVarDecl
*);
152 void CheckParenExpr(const FunctionDecl
*, const ParenExpr
*);
153 void CheckMemberDeleteExpr(const FunctionDecl
*, const CXXDeleteExpr
*,
154 const MemberExpr
*, StringRef message
);
155 FunctionDecl
const * mpCurrentFunctionDecl
= nullptr;
159 bool UseUniquePtr::VisitFunctionDecl(const FunctionDecl
* functionDecl
)
161 if (ignoreLocation(functionDecl
))
163 if (isInUnoIncludeFile(functionDecl
))
166 const CompoundStmt
* compoundStmt
= dyn_cast_or_null
< CompoundStmt
>( functionDecl
->getBody() );
167 if (!compoundStmt
|| compoundStmt
->size() == 0)
170 CheckCompoundStmt(functionDecl
, compoundStmt
);
176 * check for simple call to delete i.e. direct unconditional call, or if-guarded call
178 void UseUniquePtr::CheckCompoundStmt(const FunctionDecl
* functionDecl
, const CompoundStmt
* compoundStmt
)
180 for (auto i
= compoundStmt
->body_begin(); i
!= compoundStmt
->body_end(); ++i
)
182 if (auto cxxForRangeStmt
= dyn_cast
<CXXForRangeStmt
>(*i
))
183 CheckCXXForRangeStmt(functionDecl
, cxxForRangeStmt
);
184 else if (auto forStmt
= dyn_cast
<ForStmt
>(*i
))
185 CheckLoopDelete(functionDecl
, forStmt
->getBody());
186 else if (auto whileStmt
= dyn_cast
<WhileStmt
>(*i
))
187 CheckLoopDelete(functionDecl
, whileStmt
->getBody());
188 // check for unconditional inner compound statements
189 else if (auto innerCompoundStmt
= dyn_cast
<CompoundStmt
>(*i
))
190 CheckCompoundStmt(functionDecl
, innerCompoundStmt
);
191 else if (auto deleteExpr
= dyn_cast
<CXXDeleteExpr
>(*i
))
192 CheckDeleteExpr(functionDecl
, deleteExpr
);
193 else if (auto parenExpr
= dyn_cast
<ParenExpr
>(*i
))
194 CheckParenExpr(functionDecl
, parenExpr
);
195 else if (auto ifStmt
= dyn_cast
<IfStmt
>(*i
))
196 CheckIfStmt(functionDecl
, ifStmt
);
200 // Check for conditional deletes like:
201 // if (m_pField != nullptr) delete m_pField;
202 void UseUniquePtr::CheckIfStmt(const FunctionDecl
* functionDecl
, const IfStmt
* ifStmt
)
204 auto cond
= ifStmt
->getCond()->IgnoreImplicit();
205 if (auto ifCondMemberExpr
= dyn_cast
<MemberExpr
>(cond
))
207 // ignore "if (bMine)"
208 if (!loplugin::TypeCheck(ifCondMemberExpr
->getType()).Pointer())
212 else if (auto binaryOp
= dyn_cast
<BinaryOperator
>(cond
))
214 if (!isa
<MemberExpr
>(binaryOp
->getLHS()->IgnoreImplicit()))
216 if (!isa
<CXXNullPtrLiteralExpr
>(binaryOp
->getRHS()->IgnoreImplicit()))
220 else // ignore anything more complicated
223 auto deleteExpr
= dyn_cast
<CXXDeleteExpr
>(ifStmt
->getThen());
226 CheckDeleteExpr(functionDecl
, deleteExpr
);
230 auto parenExpr
= dyn_cast
<ParenExpr
>(ifStmt
->getThen());
233 CheckParenExpr(functionDecl
, parenExpr
);
237 auto ifThenCompoundStmt
= dyn_cast
<CompoundStmt
>(ifStmt
->getThen());
238 if (!ifThenCompoundStmt
)
240 for (auto j
= ifThenCompoundStmt
->body_begin(); j
!= ifThenCompoundStmt
->body_end(); ++j
)
242 auto ifDeleteExpr
= dyn_cast
<CXXDeleteExpr
>(*j
);
244 CheckDeleteExpr(functionDecl
, ifDeleteExpr
);
245 ParenExpr
const * parenExpr
= dyn_cast
<ParenExpr
>(*j
);
247 CheckParenExpr(functionDecl
, parenExpr
);
251 void UseUniquePtr::CheckDeleteExpr(const FunctionDecl
* functionDecl
, const CXXDeleteExpr
* deleteExpr
)
253 auto deleteExprArg
= deleteExpr
->getArgument()->IgnoreParens()->IgnoreImplicit();
256 if (const MemberExpr
* memberExpr
= dyn_cast
<MemberExpr
>(deleteExprArg
))
258 // ignore delete static_cast<T>(p)->other;
259 if (!isa
<CXXThisExpr
>(memberExpr
->getBase()->IgnoreCasts()))
261 // don't always own this
262 if (fn
== SRCDIR
"/editeng/source/editeng/impedit2.cxx")
264 // this member needs to get passed via an extern "C" API
265 if (fn
== SRCDIR
"/sd/source/filter/sdpptwrp.cxx")
267 // ownership complicated between this and the group
268 if (fn
== SRCDIR
"/sc/source/core/data/formulacell.cxx")
271 if (fn
== SRCDIR
"/sw/source/filter/html/parcss1.cxx")
274 if (fn
== SRCDIR
"/sw/source/filter/writer/writer.cxx")
277 if (fn
== SRCDIR
"/sc/source/filter/html/htmlpars.cxx")
279 // complicated pimpl stuff in SalLayoutGlyphs
280 if (fn
== SRCDIR
"/vcl/source/gdi/impglyphitem.cxx")
283 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, memberExpr
,
284 "unconditional call to delete on a member, should be using std::unique_ptr");
288 const ArraySubscriptExpr
* arrayExpr
= dyn_cast
<ArraySubscriptExpr
>(deleteExprArg
);
291 auto baseMemberExpr
= dyn_cast
<MemberExpr
>(arrayExpr
->getBase()->IgnoreParens()->IgnoreImplicit());
293 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, baseMemberExpr
,
294 "unconditional call to delete on an array member, should be using std::unique_ptr");
299 bool any_equal(std::string
const & needle
, T first
) {
300 return needle
== first
;
303 template<typename T
, typename
... Args
>
304 bool any_equal(std::string
const & needle
, T first
, Args
... args
) {
305 return needle
== first
|| any_equal(needle
, args
...);
308 void UseUniquePtr::CheckDeleteLocalVar(const FunctionDecl
* functionDecl
, const CXXDeleteExpr
* deleteExpr
, const VarDecl
* varDecl
)
310 // ignore globals for now
311 if (varDecl
->hasGlobalStorage())
314 // Ignore times when we are casting from void* to init the var, normally indicates
315 // some complex memory management.
316 if (varDecl
->getInit())
318 if (auto explicitCast
= dyn_cast
<ExplicitCastExpr
>(varDecl
->getInit()))
320 if (loplugin::TypeCheck(explicitCast
->getSubExpr()->getType()).Pointer().Void())
325 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sal/qa/"))
327 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/comphelper/qa/"))
329 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/cppuhelper/qa/"))
331 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/libreofficekit/qa/"))
333 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/vcl/qa/"))
335 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sc/qa/"))
337 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sfx2/qa/"))
339 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/smoketest/"))
341 if (loplugin::hasPathnamePrefix(fn
, WORKDIR
))
344 if (fn
== SRCDIR
"/vcl/source/gdi/regband.cxx")
346 // this thing relies on explicit delete
347 if (loplugin::TypeCheck(varDecl
->getType()).Pointer().Class("VersionCompat").GlobalNamespace())
349 if (loplugin::TypeCheck(varDecl
->getType()).Pointer().Class("IMapCompat").GlobalNamespace())
351 // passing data to gtk API and I can't figure out the types
352 if (fn
== SRCDIR
"/vcl/unx/gtk3/gtk3gtkdata.cxx"
353 || fn
== SRCDIR
"/vcl/unx/gtk/gtkdata.cxx")
355 // sometimes this stuff is held by tools::SvRef, sometimes by std::unique_ptr .....
356 if (fn
== SRCDIR
"/sot/source/unoolestorage/xolesimplestorage.cxx")
358 // don't feel like messing with this chunk of sfx2
359 if (fn
== SRCDIR
"/sfx2/source/appl/appinit.cxx")
361 if (fn
== SRCDIR
"/svx/source/svdraw/svdobj.cxx")
363 if (fn
== SRCDIR
"/svx/source/svdraw/svdmodel.cxx")
366 if (fn
== SRCDIR
"/basic/source/comp/parser.cxx")
368 if (fn
== SRCDIR
"/basic/source/runtime/runtime.cxx")
371 if (fn
== SRCDIR
"/svx/source/form/filtnav.cxx")
373 // using clucene macros
374 if (fn
== SRCDIR
"/helpcompiler/source/HelpSearch.cxx")
377 if (fn
== SRCDIR
"/filter/source/graphicfilter/ios2met/ios2met.cxx")
379 // no idea what this is trying to do
380 if (fn
== SRCDIR
"/cui/source/customize/SvxMenuConfigPage.cxx")
382 // I cannot follow the ownership of OSQLParseNode's
383 if (fn
== SRCDIR
"/dbaccess/source/core/api/SingleSelectQueryComposer.cxx")
385 if (fn
== SRCDIR
"/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx")
388 if (fn
== SRCDIR
"/formula/source/core/api/FormulaCompiler.cxx")
390 // smuggling data around via SvxFontListItem
391 if (fn
== SRCDIR
"/extensions/source/propctrlr/fontdialog.cxx")
394 if (fn
== SRCDIR
"/sc/source/ui/docshell/documentlinkmgr.cxx")
397 if (fn
== SRCDIR
"/sc/source/core/data/stlpool.cxx")
400 if (fn
== SRCDIR
"/sc/source/core/tool/autoform.cxx")
402 // unsure about ownership
403 if (fn
== SRCDIR
"/xmlsecurity/source/framework/saxeventkeeperimpl.cxx")
405 // ScTokenArray ownership complicated between this and the group
406 if (fn
== SRCDIR
"/sc/source/core/data/formulacell.cxx")
409 if (fn
== SRCDIR
"/sw/source/core/doc/tblafmt.cxx")
412 if (fn
== SRCDIR
"/sc/source/ui/unoobj/tokenuno.cxx")
414 // SwDoc::DelTextFormatColl
415 if (fn
== SRCDIR
"/sw/source/core/doc/docfmt.cxx")
417 // SwRootFrame::CalcFrameRects
418 if (fn
== SRCDIR
"/sw/source/core/layout/trvlfrm.cxx")
421 if (fn
== SRCDIR
"/sw/source/core/undo/SwUndoPageDesc.cxx")
423 // unsure about the SwLinePortion ownership
424 if (fn
== SRCDIR
"/sw/source/core/text/itrform2.cxx")
426 // can't follow the ownership
427 if (fn
== SRCDIR
"/sw/source/filter/html/htmlatr.cxx")
429 // SwTextFormatter::BuildMultiPortion complicated
430 if (fn
== SRCDIR
"/sw/source/core/text/pormulti.cxx")
432 // SwXMLExport::ExportTableLines
433 if (fn
== SRCDIR
"/sw/source/filter/xml/xmltble.cxx")
435 // SwPagePreview::~SwPagePreview
436 if (fn
== SRCDIR
"/sw/source/uibase/uiview/pview.cxx")
438 // alloc/free routines for the hand constructed virtual function table
439 if (fn
== SRCDIR
"/sal/textenc/convertisciidevangari.cxx")
441 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/bridges/"))
444 if (fn
== SRCDIR
"/sal/rtl/bootstrap.cxx")
446 // too complicated for my small brain
447 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/cppu/"))
450 if (fn
== SRCDIR
"/vcl/source/gdi/octree.cxx")
453 if (fn
== SRCDIR
"/vcl/source/filter/graphicfilter.cxx")
456 if (fn
== SRCDIR
"/svtools/source/control/ctrltool.cxx")
459 if (fn
== SRCDIR
"/sfx2/source/control/msgpool.cxx")
462 if (fn
== SRCDIR
"/svx/source/sdr/contact/objectcontact.cxx")
464 // memory management in this module is a mess
465 if (fn
== SRCDIR
"/idlc/source/aststack.cxx")
468 if (fn
== SRCDIR
"/cui/source/customize/cfg.cxx")
471 if (fn
== SRCDIR
"/lotuswordpro/source/filter/lwpfribptr.cxx")
474 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/connectivity/source/drivers/file/"))
477 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/unodevtools/source/skeletonmaker/"))
480 llvm::StringRef parentName
;
481 if (auto cxxMethodDecl
= dyn_cast
<CXXMethodDecl
>(functionDecl
))
483 parentName
= cxxMethodDecl
->getParent()->getName();
486 // no idea what is going on here
487 if (parentName
== "ScChangeActionLinkEntry")
490 if (parentName
== "SfxItemSet" || parentName
== "SfxItemPool")
493 if (parentName
== "ScFunctionList" || parentName
== "SwNodes"
494 || parentName
== "SwUnoCursor" || parentName
== "SortedResultSet"
495 || parentName
== "Atom" || parentName
== "RegionBand" || parentName
== "WMFWriter"
496 || parentName
== "Scheduler" || parentName
== "OpenGLContext"
497 || parentName
== "WizardDialog")
499 // manual ref counting
500 if (parentName
== "ScBroadcastAreaSlot")
503 if (any_equal(parentName
, "SwFormatField", "FontPropertyBox", "SdFontPropertyBox",
504 "SwHTMLParser", "PDFWriterImpl", "SbiParser", "DictionaryList", "SwGlossaryHdl", "SwGlossaryGroupDlg"))
507 if (any_equal(parentName
, "SbTreeListBox"))
510 if (functionDecl
->getIdentifier())
512 std::string name
= functionDecl
->getName();
513 if (!parentName
.empty())
514 name
= std::string(parentName
) + "::" + name
;
517 if (name
== "Proxy_free" || name
== "s_free" || name
== "binuno_proxy_free")
519 if (name
== "SvpSalFrame::ReleaseGraphics")
521 // don't feel like changing the API functions in registry
522 if (name
== "createRegistry" || name
== "openRegistry" || name
== "closeRegistry" || name
== "destroyRegistry"
523 || name
== "reg_openRegistry")
526 if (any_equal(name
, "TypeWriter::createBlop", "ImplDeleteConfigData", "Config::DeleteGroup",
527 "Config::DeleteKey", "E3dView::DoDepthArrange",
528 "DXFBlocks::Clear", "DXFTables::Clear", "DXFEntities::Clear",
529 "PSWriter::WritePS", "PSWriter::ImplWriteActions", "CUtList::Destroy",
530 "ScBroadcastAreaSlotMachine::UpdateBroadcastAreas"))
533 if (any_equal(name
, "write_uInt16s_FromOUString", "ProgressMonitor::removeText",
534 "StgDirEntry::SetSize", "UCBStorage::CopyStorageElement_Impl"
535 "OutputDevice::ImplDrawPolyPolygon", "OutputDevice::ImplDrawPolyPolygon",
536 "ImplListBox::InsertEntry", "Edit::dispose",
537 "ViewContact::deleteAllVOCs", "SfxViewFrame::ReleaseObjectShell_Impl",
538 "SfxViewFrame::SwitchToViewShell_Impl", "OfaSmartTagOptionsTabPage::ClearListBox",
539 "OfaSmartTagOptionsTabPage::FillItemSet", "doc_destroy", "lo_destroy",
540 "callColumnFormatDialog"))
543 if (any_equal(name
, "UCBStorage::OpenStorage_Impl", "SdTransferable::GetData"))
545 // complicated ownership
546 if (any_equal(name
, "ParseCMAP", "OpenGLSalBitmap::CreateTexture", "X11SalGraphicsImpl::drawAlphaBitmap"
547 "SvEmbedTransferHelper::GetData", "ORoadmap::dispose",
548 "BrowseBox::SetMode", "ExportDialog::GetFilterData", "disposeComVariablesForBasic",
549 "ImpEditEngine::ImpRemoveParagraph", "FactoryImpl::createAdapter",
550 "SfxStateCache::SetVisibleState", "SfxBindings::QueryState",
551 "ViewContact::deleteAllVOCs", "SvxMSDffManager::ProcessObj", "SvEmbedTransferHelper::GetData",
552 "SvXMLExportPropertyMapper::Filter_", "SdXMLExport::ImpGetOrCreatePageMasterInfo",
553 "SfxDocumentDescPage::FillItemSet", "SfxCustomPropertiesPage::FillItemSet",
554 "SfxCmisPropertiesPage::FillItemSet", "SfxObjectShell::DoSaveCompleted",
555 "SfxObjectShell::DoSave_Impl", "SfxObjectShell::PreDoSaveAs_Impl", "SfxObjectShell::Save_Impl",
556 "SfxFrame::DoClose_Impl", "SfxBaseModel::load",
557 "SdrTextObj::TakeTextRect", "SdrTableObj::TakeTextRect", "SdrObjCustomShape::TakeTextRect",
558 "CellProperties::ItemSetChanged", "CellProperties::ItemChange",
559 "TableLayouter::SetBorder", "TableLayouter::ClearBorderLayout",
560 "ImpXPolygon::Resize", "SvxTextEditSourceImpl::GetBackgroundTextForwarder",
561 "Svx3DSceneObject::setPropertyValueImpl", "lcl_RemoveTextEditOutlinerViews",
562 "SdrObjEditView::SdrEndTextEdit", "SvxShape::_setPropertyValue",
563 "AccessibleShape::Init", "AccessibleCell::Init",
564 "SdrTableRtfExporter::WriteCell", "GalleryItem::_getPropertyValues",
565 "VMLExport::StartShape", "DrawingML::WriteText",
566 "MtfTools::DrawText", "FormulaTokenArray::RewriteMissing",
567 "OSQLParseNode::negateSearchCondition", "OSQLParseNodesContainer::clearAndDelete",
568 "SdFilter::GetLibrarySymbol", "SdPage::SetObjText",
569 "SdDrawDocument::InsertBookmarkAsPage", "SdDrawDocument::InsertBookmarkAsObject",
570 "SdDrawDocument::RemoveUnnecessaryMasterPages",
571 "ScTable::CopyConditionalFormat", "ScTable::ValidQuery",
572 "ScTable::SetOptimalHeight", "ScTable::SetOptimalHeightOnly", "ScCompiler::CompileString",
573 "ScProgress::DeleteInterpretProgress", "ScInterpreter::ScBase",
574 "UCBStorage::CopyStorageElement_Impl", "X11SalGraphicsImpl::drawAlphaBitmap",
575 "MasterPagesSelector::ClearPageSet", "View::IsPresObjSelected",
576 "SdDrawPagesAccess::remove", "SdMasterPagesAccess::remove", "View::InsertData",
577 "RemoteServer::execute", "Implementation::ReleaseOutlinerView",
578 "SwFormat::CopyAttrs", "FinitCore", "SwCursorShell::MoveFieldType", "SwExtraPainter::PaintExtra",
579 "SwMarginPortion::AdjustRight", "SwPaintQueue::Repaint", "SwTOXMgr::UpdateOrInsertTOX",
580 "SwBaseShell::Execute", "WW8Export::WriteSdrTextObj"))
582 // complicated delete
583 if (name
== "X11SalObject::CreateObject")
588 DiagnosticsEngine::Warning
,
589 "call to delete on a var, should be using std::unique_ptr",
590 compat::getBeginLoc(deleteExpr
))
591 << deleteExpr
->getSourceRange();
593 DiagnosticsEngine::Note
,
595 compat::getBeginLoc(varDecl
))
596 << varDecl
->getSourceRange();
600 * Look for DELETEZ expressions.
602 void UseUniquePtr::CheckParenExpr(const FunctionDecl
* functionDecl
, const ParenExpr
* parenExpr
)
604 auto binaryOp
= dyn_cast
<BinaryOperator
>(parenExpr
->getSubExpr());
605 if (!binaryOp
|| binaryOp
->getOpcode() != BO_Comma
)
607 auto deleteExpr
= dyn_cast
<CXXDeleteExpr
>(binaryOp
->getLHS());
610 CheckDeleteExpr(functionDecl
, deleteExpr
);
613 void UseUniquePtr::CheckLoopDelete(const FunctionDecl
* functionDecl
, const Stmt
* bodyStmt
)
615 if (auto deleteExpr
= dyn_cast
<CXXDeleteExpr
>(bodyStmt
))
616 CheckLoopDelete(functionDecl
, deleteExpr
);
617 else if (auto compoundStmt
= dyn_cast
<CompoundStmt
>(bodyStmt
))
619 for (auto i
= compoundStmt
->body_begin(); i
!= compoundStmt
->body_end(); ++i
)
621 if (auto deleteExpr
= dyn_cast
<CXXDeleteExpr
>(*i
))
622 CheckLoopDelete(functionDecl
, deleteExpr
);
627 void UseUniquePtr::CheckLoopDelete(const FunctionDecl
* functionDecl
, const CXXDeleteExpr
* deleteExpr
)
629 const MemberExpr
* memberExpr
= nullptr;
630 const VarDecl
* varDecl
= nullptr;
631 const Expr
* subExpr
= deleteExpr
->getArgument();
632 // drill down looking for a MemberExpr
635 subExpr
= subExpr
->IgnoreParens()->IgnoreImplicit();
636 if ((memberExpr
= dyn_cast
<MemberExpr
>(subExpr
)))
638 if (memberExpr
->getMemberDecl()->getName() == "first" || memberExpr
->getMemberDecl()->getName() == "second")
640 subExpr
= memberExpr
->getBase();
641 memberExpr
= nullptr;
646 else if (auto declRefExpr
= dyn_cast
<DeclRefExpr
>(subExpr
))
648 if ((varDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl())))
651 else if (auto arraySubscriptExpr
= dyn_cast
<ArraySubscriptExpr
>(subExpr
))
652 subExpr
= arraySubscriptExpr
->getBase();
653 else if (auto cxxOperatorCallExpr
= dyn_cast
<CXXOperatorCallExpr
>(subExpr
))
655 // look for deletes of an iterator object where the iterator is over a member field
656 if (auto declRefExpr
= dyn_cast
<DeclRefExpr
>(cxxOperatorCallExpr
->getArg(0)->IgnoreImplicit()))
658 if (auto iterVarDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl()))
660 auto init
= iterVarDecl
->getInit();
663 init
= compat::IgnoreImplicit(init
);
664 if (!compat::CPlusPlus17(compiler
.getLangOpts()))
665 if (auto x
= dyn_cast
<CXXConstructExpr
>(init
))
667 init
= compat::IgnoreImplicit(x
->getArg(0));
668 if (auto x
= dyn_cast
<CXXConstructExpr
>(init
))
669 if (x
->getNumArgs() == 1
670 || (x
->getNumArgs() >= 2 && isa
<CXXDefaultArgExpr
>(x
->getArg(1))))
672 init
= compat::IgnoreImplicit(x
->getArg(0));
674 if (auto x
= dyn_cast
<CXXMemberCallExpr
>(init
))
675 init
= x
->getImplicitObjectArgument()->IgnoreParenImpCasts();
676 if ((memberExpr
= dyn_cast
<MemberExpr
>(init
)))
678 // look for deletes of an iterator object where the iterator is over a var
679 if (auto declRefExpr2
= dyn_cast
<DeclRefExpr
>(init
))
681 if ((varDecl
= dyn_cast
<VarDecl
>(declRefExpr2
->getDecl())))
687 // look for deletes like "delete m_pField[0]"
688 if (cxxOperatorCallExpr
->getOperator() == OO_Subscript
)
690 subExpr
= cxxOperatorCallExpr
->getArg(0)->IgnoreImplicit();
691 if ((memberExpr
= dyn_cast
<MemberExpr
>(subExpr
)))
693 if (auto declRefExpr
= dyn_cast
<DeclRefExpr
>(subExpr
))
695 if ((varDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl())))
707 // OStorage_Impl::Commit very complicated ownership passing going on
708 if (fn
== SRCDIR
"/package/source/xstor/xstorage.cxx")
711 if (fn
== SRCDIR
"/vcl/source/gdi/print.cxx")
714 if (fn
== SRCDIR
"/basic/source/runtime/runtime.cxx")
717 if (fn
== SRCDIR
"/sw/source/core/bastyp/swcache.cxx")
720 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, memberExpr
, "rather manage this member with std::some_container<std::unique_ptr<T>>");
725 // ignore if the value for the var comes from somewhere else
726 if (varDecl
->hasInit() && isa
<ExplicitCastExpr
>(varDecl
->getInit()->IgnoreImpCasts()))
729 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/vcl/qa/"))
732 if (fn
== SRCDIR
"/registry/source/reflwrit.cxx")
735 if (fn
== SRCDIR
"/tools/source/generic/config.cxx")
738 if (fn
== SRCDIR
"/vcl/source/gdi/regband.cxx")
741 if (fn
== SRCDIR
"/vcl/source/gdi/regionband.cxx")
744 if (fn
== SRCDIR
"/vcl/source/gdi/octree.cxx")
747 if (fn
== SRCDIR
"/vcl/source/app/scheduler.cxx")
750 if (fn
== SRCDIR
"/vcl/source/filter/wmf/wmfwr.cxx")
753 if (fn
== SRCDIR
"/vcl/source/filter/graphicfilter.cxx")
756 if (fn
== SRCDIR
"/vcl/source/app/salvtables.cxx")
758 // undo code is tricky
759 if (fn
== SRCDIR
"/svl/source/undo/undo.cxx")
761 // subclass that messes with parent class in constructor/destructor, yuck
762 if (fn
== SRCDIR
"/svtools/source/contnr/imivctl1.cxx")
765 if (fn
== SRCDIR
"/connectivity/source/parse/sqlnode.cxx")
767 // the whole svx model/contact/view thing confuses me
768 if (fn
== SRCDIR
"/svx/source/sdr/contact/viewcontact.cxx")
770 if (fn
== SRCDIR
"/svx/source/sdr/contact/objectcontact.cxx")
773 if (fn
== SRCDIR
"/svx/source/unodialogs/textconversiondlgs/chinese_dictionarydialog.cxx")
776 if (fn
== SRCDIR
"/svx/source/svdraw/svdundo.cxx")
778 // TODO the lazydelete stuff should probably just be ripped out altogether now that we have VclPtr
779 if (fn
== SRCDIR
"/vcl/source/helper/lazydelete.cxx")
782 if (fn
== SRCDIR
"/filter/source/graphicfilter/idxf/dxfblkrd.cxx")
784 if (fn
== SRCDIR
"/filter/source/graphicfilter/idxf/dxftblrd.cxx")
786 if (fn
== SRCDIR
"/lotuswordpro/source/filter/utlist.cxx")
788 if (fn
== SRCDIR
"/lotuswordpro/source/filter/lwpfribptr.cxx")
791 if (fn
== SRCDIR
"/sd/source/ui/sidebar/MasterPagesSelector.cxx")
794 if (fn
== SRCDIR
"/sd/source/filter/ppt/pptatom.cxx")
797 if (fn
== SRCDIR
"/sc/source/core/data/funcdesc.cxx")
800 if (fn
== SRCDIR
"/sw/source/core/crsr/crsrsh.cxx")
803 if (fn
== SRCDIR
"/sw/source/core/docnode/nodes.cxx")
806 if (fn
== SRCDIR
"/sw/source/core/unocore/unocrsr.cxx")
809 if (fn
== SRCDIR
"/filter/source/graphicfilter/idxf/dxfentrd.cxx")
812 if (fn
== SRCDIR
"/filter/source/graphicfilter/ios2met/ios2met.cxx")
814 // sometimes owning, sometimes not
815 if (fn
== SRCDIR
"/sw/qa/core/Test-BigPtrArray.cxx")
819 DiagnosticsEngine::Warning
,
820 "loopdelete: rather manage this var with std::some_container<std::unique_ptr<T>>",
821 compat::getBeginLoc(deleteExpr
))
822 << deleteExpr
->getSourceRange();
824 DiagnosticsEngine::Note
,
826 compat::getBeginLoc(varDecl
))
827 << varDecl
->getSourceRange();
831 void UseUniquePtr::CheckCXXForRangeStmt(const FunctionDecl
* functionDecl
, const CXXForRangeStmt
* cxxForRangeStmt
)
833 CXXDeleteExpr
const * deleteExpr
= nullptr;
834 if (auto compoundStmt
= dyn_cast
<CompoundStmt
>(cxxForRangeStmt
->getBody()))
836 for (auto i
= compoundStmt
->body_begin(); i
!= compoundStmt
->body_end(); ++i
)
837 if ((deleteExpr
= dyn_cast
<CXXDeleteExpr
>(*i
)))
841 deleteExpr
= dyn_cast
<CXXDeleteExpr
>(cxxForRangeStmt
->getBody());
845 // check for delete of member
846 if (auto memberExpr
= dyn_cast
<MemberExpr
>(cxxForRangeStmt
->getRangeInit()))
848 auto fieldDecl
= dyn_cast
<FieldDecl
>(memberExpr
->getMemberDecl());
852 // appears to just randomly leak stuff, and it involves some lex/yacc stuff
853 if (fn
== SRCDIR
"/idlc/source/aststack.cxx")
856 if (fn
== SRCDIR
"/vcl/source/gdi/print.cxx")
858 // sometimes it's an owning field, sometimes not
859 if (fn
== SRCDIR
"/i18npool/source/localedata/localedata.cxx")
862 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, memberExpr
, "rather manage this with std::some_container<std::unique_ptr<T>>");
865 // check for delete of var
866 if (auto declRefExpr
= dyn_cast
<DeclRefExpr
>(cxxForRangeStmt
->getRangeInit()->IgnoreParens()->IgnoreImplicit()))
868 auto varDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl());
872 // don't feel like messing with this part of sfx2
873 if (fn
== SRCDIR
"/sfx2/source/control/msgpool.cxx")
875 if (fn
== SRCDIR
"/sfx2/source/doc/doctemplates.cxx")
878 if (fn
== SRCDIR
"/hwpfilter/source/grammar.cxx")
880 if (fn
== SRCDIR
"/hwpfilter/source/formula.cxx")
882 // no idea why, but ui tests crash afterwards in weird ways
883 if (fn
== SRCDIR
"/svtools/source/control/roadmap.cxx")
885 // sometimes it owns it, sometimes it does not
886 if (fn
== SRCDIR
"/dbaccess/source/ui/misc/WCopyTable.cxx")
889 if (fn
== SRCDIR
"/dbaccess/source/ui/misc/UITools.cxx")
892 if (fn
== SRCDIR
"/sw/source/core/bastyp/init.cxx")
895 if (fn
== SRCDIR
"/reportdesign/source/ui/misc/UITools.cxx")
898 if (fn
== SRCDIR
"/reportdesign/source/ui/report/ReportController.cxx")
901 if (fn
== SRCDIR
"/svx/source/sdr/contact/viewcontact.cxx")
903 if (fn
== SRCDIR
"/svx/source/sdr/contact/objectcontact.cxx")
907 DiagnosticsEngine::Warning
,
908 "rather manage this var with std::some_container<std::unique_ptr<T>>",
909 compat::getBeginLoc(deleteExpr
))
910 << deleteExpr
->getSourceRange();
912 DiagnosticsEngine::Note
,
914 compat::getBeginLoc(varDecl
))
915 << varDecl
->getSourceRange();
919 void UseUniquePtr::CheckMemberDeleteExpr(const FunctionDecl
* functionDecl
, const CXXDeleteExpr
* deleteExpr
,
920 const MemberExpr
* memberExpr
, StringRef message
)
922 // ignore union games
923 const FieldDecl
* fieldDecl
= dyn_cast
<FieldDecl
>(memberExpr
->getMemberDecl());
926 TagDecl
const * td
= dyn_cast
<TagDecl
>(fieldDecl
->getDeclContext());
930 // ignore calling delete on someone else's field
931 if (auto methodDecl
= dyn_cast
<CXXMethodDecl
>(functionDecl
))
932 if (fieldDecl
->getParent() != methodDecl
->getParent() )
935 if (ignoreLocation(fieldDecl
))
937 // to ignore things like the CPPUNIT macros
938 if (loplugin::hasPathnamePrefix(fn
, WORKDIR
"/"))
940 // passes and stores pointers to member fields
941 if (fn
== SRCDIR
"/sot/source/sdstor/stgdir.hxx")
943 // something platform-specific
944 if (fn
== SRCDIR
"/hwpfilter/source/htags.h")
946 // passes pointers to member fields
947 if (fn
== SRCDIR
"/sd/inc/sdpptwrp.hxx")
949 // @TODO intrusive linked-lists here, with some trickiness
950 if (fn
== SRCDIR
"/sw/source/filter/html/parcss1.hxx")
952 // @TODO SwDoc has some weird ref-counting going on
953 if (fn
== SRCDIR
"/sw/inc/shellio.hxx")
955 // @TODO it's sharing pointers with another class
956 if (fn
== SRCDIR
"/sc/inc/formulacell.hxx")
958 // some weird stuff going on here around struct Entity
959 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sax/"))
961 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/include/sax/"))
963 // manipulation of tree structures ie. StgAvlNode, don't lend themselves to std::unique_ptr
964 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sot/"))
966 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/include/sot/"))
968 // the std::vector is being passed to another class
969 if (fn
== SRCDIR
"/sfx2/source/explorer/nochaos.cxx")
971 auto tc
= loplugin::TypeCheck(fieldDecl
->getType());
972 // these sw::Ring based classes do not lend themselves to std::unique_ptr management
973 if (tc
.Pointer().Class("SwNodeIndex").GlobalNamespace() || tc
.Pointer().Class("SwShellTableCursor").GlobalNamespace()
974 || tc
.Pointer().Class("SwBlockCursor").GlobalNamespace() || tc
.Pointer().Class("SwVisibleCursor").GlobalNamespace()
975 || tc
.Pointer().Class("SwShellCursor").GlobalNamespace())
977 // there is a loop in ~ImplPrnQueueList deleting stuff on a global data structure
978 if (fn
== SRCDIR
"/vcl/inc/print.h")
980 // painful linked list
981 if (fn
== SRCDIR
"/basic/source/inc/runtime.hxx")
983 // not sure how the node management is working here
984 if (fn
== SRCDIR
"/i18npool/source/localedata/saxparser.cxx")
986 // has a pointer that it only sometimes owns
987 if (fn
== SRCDIR
"/editeng/source/editeng/impedit.hxx")
991 DiagnosticsEngine::Warning
,
993 compat::getBeginLoc(deleteExpr
))
994 << deleteExpr
->getSourceRange();
996 DiagnosticsEngine::Note
,
998 compat::getBeginLoc(fieldDecl
))
999 << fieldDecl
->getSourceRange();
1002 bool UseUniquePtr::TraverseFunctionDecl(FunctionDecl
* functionDecl
)
1004 if (ignoreLocation(functionDecl
))
1007 auto oldCurrent
= mpCurrentFunctionDecl
;
1008 mpCurrentFunctionDecl
= functionDecl
;
1009 bool ret
= RecursiveASTVisitor::TraverseFunctionDecl(functionDecl
);
1010 mpCurrentFunctionDecl
= oldCurrent
;
1015 bool UseUniquePtr::TraverseCXXMethodDecl(CXXMethodDecl
* methodDecl
)
1017 if (ignoreLocation(methodDecl
))
1020 auto oldCurrent
= mpCurrentFunctionDecl
;
1021 mpCurrentFunctionDecl
= methodDecl
;
1022 bool ret
= RecursiveASTVisitor::TraverseCXXMethodDecl(methodDecl
);
1023 mpCurrentFunctionDecl
= oldCurrent
;
1028 bool UseUniquePtr::TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl
* methodDecl
)
1030 if (ignoreLocation(methodDecl
))
1033 auto oldCurrent
= mpCurrentFunctionDecl
;
1034 mpCurrentFunctionDecl
= methodDecl
;
1035 bool ret
= RecursiveASTVisitor::TraverseCXXDeductionGuideDecl(methodDecl
);
1036 mpCurrentFunctionDecl
= oldCurrent
;
1041 bool UseUniquePtr::TraverseCXXConstructorDecl(CXXConstructorDecl
* methodDecl
)
1043 if (ignoreLocation(methodDecl
))
1046 auto oldCurrent
= mpCurrentFunctionDecl
;
1047 mpCurrentFunctionDecl
= methodDecl
;
1048 bool ret
= RecursiveASTVisitor::TraverseCXXConstructorDecl(methodDecl
);
1049 mpCurrentFunctionDecl
= oldCurrent
;
1054 bool UseUniquePtr::TraverseCXXConversionDecl(CXXConversionDecl
* methodDecl
)
1056 if (ignoreLocation(methodDecl
))
1059 auto oldCurrent
= mpCurrentFunctionDecl
;
1060 mpCurrentFunctionDecl
= methodDecl
;
1061 bool ret
= RecursiveASTVisitor::TraverseCXXConversionDecl(methodDecl
);
1062 mpCurrentFunctionDecl
= oldCurrent
;
1067 bool UseUniquePtr::TraverseCXXDestructorDecl(CXXDestructorDecl
* methodDecl
)
1069 if (ignoreLocation(methodDecl
))
1072 auto oldCurrent
= mpCurrentFunctionDecl
;
1073 mpCurrentFunctionDecl
= methodDecl
;
1074 bool ret
= RecursiveASTVisitor::TraverseCXXDestructorDecl(methodDecl
);
1075 mpCurrentFunctionDecl
= oldCurrent
;
1080 bool UseUniquePtr::TraverseConstructorInitializer(CXXCtorInitializer
* ctorInit
)
1082 if (!ctorInit
->getSourceLocation().isValid() || ignoreLocation(ctorInit
->getSourceLocation()))
1084 if (!ctorInit
->getMember())
1086 if (!loplugin::TypeCheck(ctorInit
->getMember()->getType()).Class("unique_ptr").StdNamespace())
1088 auto constructExpr
= dyn_cast_or_null
<CXXConstructExpr
>(ctorInit
->getInit());
1089 if (!constructExpr
|| constructExpr
->getNumArgs() == 0)
1091 auto init
= constructExpr
->getArg(0)->IgnoreImpCasts();
1092 if (!isa
<DeclRefExpr
>(init
))
1095 StringRef fn
= getFileNameOfSpellingLoc(compiler
.getSourceManager().getSpellingLoc(ctorInit
->getSourceLocation()));
1096 // don't feel like fiddling with the yacc parser
1097 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/idlc/"))
1099 // cannot change URE
1100 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx"))
1104 DiagnosticsEngine::Warning
,
1105 "should be passing via std::unique_ptr param",
1106 ctorInit
->getSourceLocation())
1107 << ctorInit
->getSourceRange();
1108 return RecursiveASTVisitor
<UseUniquePtr
>::TraverseConstructorInitializer(ctorInit
);
1111 // Only checks for calls to delete on a pointer param
1112 bool UseUniquePtr::VisitCXXDeleteExpr(const CXXDeleteExpr
* deleteExpr
)
1114 if (!mpCurrentFunctionDecl
)
1116 if (ignoreLocation(mpCurrentFunctionDecl
))
1118 if (isInUnoIncludeFile(compat::getBeginLoc(mpCurrentFunctionDecl
->getCanonicalDecl())))
1120 auto declRefExpr
= dyn_cast
<DeclRefExpr
>(deleteExpr
->getArgument()->IgnoreParenImpCasts()->IgnoreImplicit());
1123 if (auto parmVarDecl
= dyn_cast
<ParmVarDecl
>(declRefExpr
->getDecl()))
1124 CheckDeleteParmVar(deleteExpr
, parmVarDecl
);
1125 else if (auto varDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl()))
1126 CheckDeleteLocalVar(mpCurrentFunctionDecl
, deleteExpr
, varDecl
);
1130 void UseUniquePtr::CheckDeleteParmVar(const CXXDeleteExpr
* deleteExpr
, const ParmVarDecl
* )
1132 if (mpCurrentFunctionDecl
->getIdentifier())
1134 auto name
= mpCurrentFunctionDecl
->getName();
1135 if (name
== "delete_IncludesCollection" || name
== "convertName"
1136 || name
== "createNamedType"
1137 || name
== "typelib_typedescriptionreference_release" || name
== "deleteExceptions"
1138 || name
== "uno_threadpool_destroy"
1139 || name
== "AddRanges_Impl"
1140 || name
== "DestroySalInstance"
1141 || name
== "ImplHandleUserEvent"
1142 || name
== "releaseDecimalPtr" // TODO, basic
1143 || name
== "replaceAndReset" // TODO, connectivity
1144 || name
== "intrusive_ptr_release"
1145 || name
== "FreeParaList"
1146 || name
== "DeleteSdrUndoAction" // TODO, sc
1147 || name
== "lcl_MergeGCBox" || name
== "lcl_MergeGCLine" || name
== "lcl_DelHFFormat")
1150 if (auto cxxMethodDecl
= dyn_cast
<CXXMethodDecl
>(mpCurrentFunctionDecl
))
1152 auto parentName
= cxxMethodDecl
->getParent()->getName();
1153 // include/o3tl/deleter.hxx
1154 if (parentName
== "default_delete")
1156 // TODO Bitmap::ReleaseAccess
1157 // Tricky because it reverberates through other code and requires that BitmapWriteAccess move into /include again
1158 if (parentName
== "Bitmap")
1160 // TODO virtual ones are much trickier, leave for later
1161 if (cxxMethodDecl
->isVirtual())
1163 // sw/inc/unobaseclass.hxx holds SolarMutex while deleting
1164 if (parentName
== "UnoImplPtrDeleter")
1168 // StgAvlNode::Remove
1169 if (fn
== SRCDIR
"/sot/source/sdstor/stgavl.cxx")
1171 // SfxItemPool::ReleaseDefaults and SfxItemPool::Free
1172 if (fn
== SRCDIR
"/svl/source/items/itempool.cxx")
1175 if (fn
== SRCDIR
"/sw/source/core/text/txtfly.cxx")
1177 // too messy to cope with the SQL parser
1178 if (fn
== SRCDIR
"/connectivity/source/parse/sqlnode.cxx")
1180 // I can't figure out the ownership of the SfxMedium in the call site(s)
1181 if (fn
== SRCDIR
"/sfx2/source/doc/sfxbasemodel.cxx")
1183 // pointer passed via IMPL_LINK
1184 if (fn
== SRCDIR
"/sfx2/source/control/dispatch.cxx")
1186 // NavigatorTreeModel::Remove
1187 if (fn
== SRCDIR
"/svx/source/form/navigatortreemodel.cxx")
1189 // SdrModel::AddUndo
1190 if (fn
== SRCDIR
"/svx/source/svdraw/svdmodel.cxx")
1193 if (fn
== SRCDIR
"/basctl/source/basicide/baside3.cxx")
1195 // ActualizeProgress::TimeoutHdl
1196 if (fn
== SRCDIR
"/cui/source/dialogs/cuigaldlg.cxx")
1198 // ToolbarSaveInData::RemoveToolbar
1199 if (fn
== SRCDIR
"/cui/source/customize/cfg.cxx")
1201 // OStorage_Impl::RemoveElement very complicated ownership passing going on
1202 if (fn
== SRCDIR
"/package/source/xstor/xstorage.cxx")
1204 // actually held via shared_ptr, uses protected deleter object
1205 if (fn
== SRCDIR
"/sd/source/ui/framework/tools/FrameworkHelper.cxx")
1207 // actually held via shared_ptr, uses protected deleter object
1208 if (fn
== SRCDIR
"/sd/source/ui/presenter/CanvasUpdateRequester.cxx")
1210 // actually held via shared_ptr, uses protected deleter object
1211 if (fn
== SRCDIR
"/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx")
1213 // actually held via shared_ptr, uses protected deleter object
1214 if (fn
== SRCDIR
"/sd/source/ui/sidebar/MasterPageContainer.cxx")
1216 // actually held via shared_ptr, uses protected deleter object
1217 if (fn
== SRCDIR
"/sd/source/ui/tools/TimerBasedTaskExecution.cxx")
1219 // actually held via shared_ptr, uses protected deleter object
1220 if (fn
== SRCDIR
"/sd/source/ui/view/ViewShellImplementation.cxx")
1222 // ScBroadcastAreaSlot::StartListeningArea manual ref-counting of ScBroadcastArea
1223 if (fn
== SRCDIR
"/sc/source/core/data/bcaslot.cxx")
1225 // ScDrawLayer::AddCalcUndo undo stuff
1226 if (fn
== SRCDIR
"/sc/source/core/data/drwlayer.cxx")
1228 // ScTable::SetFormulaCell
1229 if (fn
== SRCDIR
"/sc/source/core/data/table2.cxx")
1231 // ScDocument::SetFormulaCell
1232 if (fn
== SRCDIR
"/sc/source/core/data/documen2.cxx")
1234 // RemoveEditAttribsHandler, stored in mdds block
1235 if (fn
== SRCDIR
"/sc/source/core/data/column2.cxx")
1237 // just turns into a mess
1238 if (fn
== SRCDIR
"/sc/source/ui/Accessibility/AccessibleDocument.cxx")
1240 // SwCache::DeleteObj, linked list
1241 if (fn
== SRCDIR
"/sw/source/core/bastyp/swcache.cxx")
1243 // SAXEventKeeperImpl::smashBufferNode
1244 if (fn
== SRCDIR
"/xmlsecurity/source/framework/saxeventkeeperimpl.cxx")
1246 // SwDoc::DeleteExtTextInput
1247 if (fn
== SRCDIR
"/sw/source/core/doc/extinput.cxx")
1249 // SwDoc::DelSectionFormat
1250 if (fn
== SRCDIR
"/sw/source/core/docnode/ndsect.cxx")
1252 // SwFrame::DestroyFrame
1253 if (fn
== SRCDIR
"/sw/source/core/layout/ssfrm.cxx")
1255 // SwGluePortion::Join
1256 if (fn
== SRCDIR
"/sw/source/core/text/porglue.cxx")
1258 // SwDoc::DelFrameFormat
1259 if (fn
== SRCDIR
"/sw/source/core/doc/docfmt.cxx")
1261 // SwTextAttr::Destroy
1262 if (fn
== SRCDIR
"/sw/source/core/txtnode/txatbase.cxx")
1264 // IMPL_LINK( SwDoc, AddDrawUndo, SdrUndoAction *, pUndo, void )
1265 if (fn
== SRCDIR
"/sw/source/core/undo/undraw.cxx")
1267 // SwHTMLParser::EndAttr
1268 if (fn
== SRCDIR
"/sw/source/filter/html/swhtml.cxx")
1270 // SwGlossaryHdl::Expand sometimes the pointer is owned, sometimes it is not
1271 if (fn
== SRCDIR
"/sw/source/uibase/dochdl/gloshdl.cxx")
1273 // SwWrtShell::Insert only owned sometimes
1274 if (fn
== SRCDIR
"/sw/source/uibase/wrtsh/wrtsh1.cxx")
1277 if (fn
== SRCDIR
"/unoxml/source/rdf/librdf_repository.cxx")
1279 // SmCursor::LineToList ran out of enthusiasm to rework the node handling
1280 if (fn
== SRCDIR
"/starmath/source/cursor.cxx")
1282 // XMLEventOASISTransformerContext::FlushEventMap
1283 if (fn
== SRCDIR
"/xmloff/source/transform/EventOASISTContext.cxx")
1285 // XMLEventOOoTransformerContext::FlushEventMap
1286 if (fn
== SRCDIR
"/xmloff/source/transform/EventOOoTContext.cxx")
1288 // SbiProcDef::Match
1289 if (fn
== SRCDIR
"/basic/source/comp/symtbl.cxx")
1293 Sometimes we can pass the param as std::unique_ptr<T>& or std::unique_ptr, sometimes the method
1294 just needs to be inlined, which normally exposes more simplification.
1297 DiagnosticsEngine::Warning
,
1298 "calling delete on a pointer param, should be either whitelisted or simplified",
1299 compat::getBeginLoc(deleteExpr
))
1300 << deleteExpr
->getSourceRange();
1304 loplugin::Plugin::Registration
< UseUniquePtr
> X("useuniqueptr", false);
1308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */