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/.
16 #include "config_clang.h"
21 Find destructors that only contain a single call to delete of a field. In which
22 case that field should really be managed by unique_ptr.
28 public loplugin::FilteringPlugin
<UseUniquePtr
>
31 explicit UseUniquePtr(loplugin::InstantiationData
const & data
):
32 FilteringPlugin(data
) {}
34 virtual void run() override
36 fn
= handler
.getMainFileName().str();
37 loplugin::normalizeDotDotInFilePath(fn
);
38 // can't change these because we pass them down to the SfxItemPool stuff
39 if (fn
== SRCDIR
"/sc/source/core/data/docpool.cxx")
41 // this just too clever for me
42 if (fn
== SRCDIR
"/sc/source/core/tool/chgtrack.cxx")
45 if (fn
== SRCDIR
"/pyuno/source/module/pyuno_runtime.cxx")
47 // m_pExampleSet here is very badly managed. sometimes it is owning, sometimes not,
48 // and the logic depends on overriding methods.
49 if (fn
== SRCDIR
"/sfx2/source/dialog/tabdlg.cxx")
51 // pLongArr is being deleted here because we temporarily overwrite a pointer to someone else's buffer, with a pointer
53 if (fn
== SRCDIR
"/editeng/source/misc/txtrange.cxx")
55 // can't use std::set<std::unique_ptr<>> until C++14
56 if (fn
== SRCDIR
"/editeng/source/misc/svxacorr.cxx")
58 // horrible horrible spawn of evil ownership and deletion here
59 if (fn
== SRCDIR
"/sfx2/source/view/ipclient.cxx")
61 // sometimes it owns, sometimes it doesn't
62 if (fn
== SRCDIR
"/editeng/source/misc/svxacorr.cxx")
64 // SwDoc::m_PageDescs has weird handling
65 if (fn
== SRCDIR
"/sw/source/core/doc/docnew.cxx")
67 // SwRedlineData::pNext and pExtraData have complex handling
68 if (fn
== SRCDIR
"/sw/source/core/doc/docredln.cxx")
70 // ScTempDocSource::pTempDoc
71 if (fn
== SRCDIR
"/sc/source/ui/unoobj/funcuno.cxx")
73 // SwAttrIter::m_pFont
74 if (fn
== SRCDIR
"/sw/source/core/text/itratr.cxx"
75 || fn
== SRCDIR
"/sw/source/core/text/redlnitr.cxx")
78 if (fn
== SRCDIR
"/sw/source/core/text/wrong.cxx")
80 // SwLineLayout::m_pNext
81 if (fn
== SRCDIR
"/sw/source/core/text/porlay.cxx")
83 // ODatabaseExport::m_aDestColumns
84 if (fn
== SRCDIR
"/dbaccess/source/ui/misc/DExport.cxx")
86 // ScTabView::pDrawActual and pDrawOld
87 if (fn
== SRCDIR
"/sc/source/ui/view/tabview5.cxx")
89 // SwHTMLParser::m_pPendStack
90 if (fn
== SRCDIR
"/sw/source/filter/html/htmlcss1.cxx")
92 // Visual Studio 2017 has trouble with these
93 if (fn
== SRCDIR
"/comphelper/source/property/MasterPropertySet.cxx"
94 || fn
== SRCDIR
"/comphelper/source/property/MasterPropertySetInfo.cxx")
96 // SwTableLine::m_aBoxes
97 if (fn
== SRCDIR
"/sw/source/core/table/swtable.cxx")
99 // SwHTMLParser::m_pFormImpl
100 if (fn
== SRCDIR
"/sw/source/filter/html/htmlform.cxx")
102 // SwHTMLParser::m_pPendStack, pNext
103 if (fn
== SRCDIR
"/sw/source/filter/html/htmltab.cxx")
105 // SaveLine::pBox, pNext
106 if (fn
== SRCDIR
"/sw/source/core/undo/untbl.cxx")
108 // RedlineInfo::pNextRedline
109 if (fn
== SRCDIR
"/sw/source/filter/xml/XMLRedlineImportHelper.cxx")
111 // SfxObjectShell::pMedium
112 if (fn
== SRCDIR
"/sfx2/source/doc/objxtor.cxx")
115 if (fn
== SRCDIR
"/sw/source/filter/ww8/wrtww8.cxx")
118 if (fn
== SRCDIR
"/sw/source/filter/ww8/ww8par2.cxx")
120 // ZipOutputStream, ownership of ZipEntry is horribly complicated here
121 if (fn
== SRCDIR
"/package/source/zipapi/ZipOutputStream.cxx")
124 if (fn
== SRCDIR
"/sal/rtl/locale.cxx")
126 // std::vector<ScLookupCacheMap*> is tricky, changing it would require moving lots of class definitions around
127 if (fn
== SRCDIR
"/sc/source/core/data/documen2.cxx"
128 || fn
== SRCDIR
"/sc/source/core/tool/interpretercontext.cxx")
131 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
134 bool VisitFunctionDecl(const FunctionDecl
* );
135 bool VisitCXXDeleteExpr(const CXXDeleteExpr
* );
136 bool TraverseFunctionDecl(FunctionDecl
* );
137 bool TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl
* );
138 bool TraverseCXXMethodDecl(CXXMethodDecl
* );
139 bool TraverseCXXConstructorDecl(CXXConstructorDecl
* );
140 bool TraverseCXXConversionDecl(CXXConversionDecl
* );
141 bool TraverseCXXDestructorDecl(CXXDestructorDecl
* );
142 bool TraverseConstructorInitializer(CXXCtorInitializer
*);
145 void CheckCompoundStmt(const FunctionDecl
*, const CompoundStmt
* );
146 void CheckIfStmt(const FunctionDecl
*, const IfStmt
* );
147 void CheckCXXForRangeStmt(const FunctionDecl
*, const CXXForRangeStmt
* );
148 void CheckLoopDelete(const FunctionDecl
*, const Stmt
* );
149 void CheckLoopDelete(const FunctionDecl
*, const CXXDeleteExpr
* );
150 void CheckDeleteExpr(const FunctionDecl
*, const CXXDeleteExpr
*);
151 void CheckDeleteLocalVar(const FunctionDecl
*, const CXXDeleteExpr
*, const VarDecl
*);
152 void CheckDeleteParmVar(const CXXDeleteExpr
*, const ParmVarDecl
*);
153 void CheckParenExpr(const FunctionDecl
*, const ParenExpr
*);
154 void CheckMemberDeleteExpr(const FunctionDecl
*, const CXXDeleteExpr
*,
155 const MemberExpr
*, StringRef message
);
156 FunctionDecl
const * mpCurrentFunctionDecl
= nullptr;
160 bool UseUniquePtr::VisitFunctionDecl(const FunctionDecl
* functionDecl
)
162 if (ignoreLocation(functionDecl
))
164 if (isInUnoIncludeFile(functionDecl
))
167 const CompoundStmt
* compoundStmt
= dyn_cast_or_null
< CompoundStmt
>( functionDecl
->getBody() );
168 if (!compoundStmt
|| compoundStmt
->size() == 0)
171 CheckCompoundStmt(functionDecl
, compoundStmt
);
177 * check for simple call to delete i.e. direct unconditional call, or if-guarded call
179 void UseUniquePtr::CheckCompoundStmt(const FunctionDecl
* functionDecl
, const CompoundStmt
* compoundStmt
)
181 for (auto i
= compoundStmt
->body_begin(); i
!= compoundStmt
->body_end(); ++i
)
183 if (auto cxxForRangeStmt
= dyn_cast
<CXXForRangeStmt
>(*i
))
184 CheckCXXForRangeStmt(functionDecl
, cxxForRangeStmt
);
185 else if (auto forStmt
= dyn_cast
<ForStmt
>(*i
))
186 CheckLoopDelete(functionDecl
, forStmt
->getBody());
187 else if (auto whileStmt
= dyn_cast
<WhileStmt
>(*i
))
188 CheckLoopDelete(functionDecl
, whileStmt
->getBody());
189 // check for unconditional inner compound statements
190 else if (auto innerCompoundStmt
= dyn_cast
<CompoundStmt
>(*i
))
191 CheckCompoundStmt(functionDecl
, innerCompoundStmt
);
192 else if (auto deleteExpr
= dyn_cast
<CXXDeleteExpr
>(*i
))
193 CheckDeleteExpr(functionDecl
, deleteExpr
);
194 else if (auto parenExpr
= dyn_cast
<ParenExpr
>(*i
))
195 CheckParenExpr(functionDecl
, parenExpr
);
196 else if (auto ifStmt
= dyn_cast
<IfStmt
>(*i
))
197 CheckIfStmt(functionDecl
, ifStmt
);
201 // Check for conditional deletes like:
202 // if (m_pField != nullptr) delete m_pField;
203 void UseUniquePtr::CheckIfStmt(const FunctionDecl
* functionDecl
, const IfStmt
* ifStmt
)
205 auto cond
= ifStmt
->getCond()->IgnoreImplicit();
206 if (auto ifCondMemberExpr
= dyn_cast
<MemberExpr
>(cond
))
208 // ignore "if (bMine)"
209 if (!loplugin::TypeCheck(ifCondMemberExpr
->getType()).Pointer())
213 else if (auto binaryOp
= dyn_cast
<BinaryOperator
>(cond
))
215 if (!isa
<MemberExpr
>(binaryOp
->getLHS()->IgnoreImplicit()))
217 if (!isa
<CXXNullPtrLiteralExpr
>(binaryOp
->getRHS()->IgnoreImplicit()))
221 else // ignore anything more complicated
224 auto deleteExpr
= dyn_cast
<CXXDeleteExpr
>(ifStmt
->getThen());
227 CheckDeleteExpr(functionDecl
, deleteExpr
);
231 auto parenExpr
= dyn_cast
<ParenExpr
>(ifStmt
->getThen());
234 CheckParenExpr(functionDecl
, parenExpr
);
238 auto ifThenCompoundStmt
= dyn_cast
<CompoundStmt
>(ifStmt
->getThen());
239 if (!ifThenCompoundStmt
)
241 for (auto j
= ifThenCompoundStmt
->body_begin(); j
!= ifThenCompoundStmt
->body_end(); ++j
)
243 auto ifDeleteExpr
= dyn_cast
<CXXDeleteExpr
>(*j
);
245 CheckDeleteExpr(functionDecl
, ifDeleteExpr
);
246 ParenExpr
const * parenExpr
= dyn_cast
<ParenExpr
>(*j
);
248 CheckParenExpr(functionDecl
, parenExpr
);
252 void UseUniquePtr::CheckDeleteExpr(const FunctionDecl
* functionDecl
, const CXXDeleteExpr
* deleteExpr
)
254 auto deleteExprArg
= deleteExpr
->getArgument()->IgnoreParens()->IgnoreImplicit();
257 if (const MemberExpr
* memberExpr
= dyn_cast
<MemberExpr
>(deleteExprArg
))
259 // ignore delete static_cast<T>(p)->other;
260 if (!isa
<CXXThisExpr
>(memberExpr
->getBase()->IgnoreCasts()))
262 // don't always own this
263 if (fn
== SRCDIR
"/editeng/source/editeng/impedit2.cxx")
265 // this member needs to get passed via an extern "C" API
266 if (fn
== SRCDIR
"/sd/source/filter/sdpptwrp.cxx")
268 // ownership complicated between this and the group
269 if (fn
== SRCDIR
"/sc/source/core/data/formulacell.cxx")
272 if (fn
== SRCDIR
"/sw/source/filter/html/parcss1.cxx")
275 if (fn
== SRCDIR
"/sw/source/filter/writer/writer.cxx")
278 if (fn
== SRCDIR
"/sc/source/filter/html/htmlpars.cxx")
280 // complicated pimpl stuff in SalLayoutGlyphs
281 if (fn
== SRCDIR
"/vcl/source/gdi/impglyphitem.cxx")
284 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, memberExpr
,
285 "unconditional call to delete on a member, should be using std::unique_ptr");
289 const ArraySubscriptExpr
* arrayExpr
= dyn_cast
<ArraySubscriptExpr
>(deleteExprArg
);
292 auto baseMemberExpr
= dyn_cast
<MemberExpr
>(arrayExpr
->getBase()->IgnoreParens()->IgnoreImplicit());
294 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, baseMemberExpr
,
295 "unconditional call to delete on an array member, should be using std::unique_ptr");
300 bool any_equal(StringRef needle
, T first
) {
301 return needle
== first
;
304 template<typename T
, typename
... Args
>
305 bool any_equal(StringRef needle
, T first
, Args
... args
) {
306 return needle
== first
|| any_equal(needle
, args
...);
309 void UseUniquePtr::CheckDeleteLocalVar(const FunctionDecl
* functionDecl
, const CXXDeleteExpr
* deleteExpr
, const VarDecl
* varDecl
)
311 // ignore globals for now
312 if (varDecl
->hasGlobalStorage())
315 // Ignore times when we are casting from void* to init the var, normally indicates
316 // some complex memory management.
317 if (varDecl
->getInit())
319 if (auto explicitCast
= dyn_cast
<ExplicitCastExpr
>(varDecl
->getInit()))
321 if (loplugin::TypeCheck(explicitCast
->getSubExpr()->getType()).Pointer().Void())
326 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sal/qa/"))
328 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/comphelper/qa/"))
330 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/cppuhelper/qa/"))
332 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/libreofficekit/qa/"))
334 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/vcl/qa/"))
336 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sc/qa/"))
338 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sfx2/qa/"))
340 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/smoketest/"))
342 if (loplugin::hasPathnamePrefix(fn
, WORKDIR
))
345 if (fn
== SRCDIR
"/vcl/source/gdi/regband.cxx")
347 // this thing relies on explicit delete
348 if (loplugin::TypeCheck(varDecl
->getType()).Pointer().Class("VersionCompatRead").GlobalNamespace())
350 if (loplugin::TypeCheck(varDecl
->getType()).Pointer().Class("VersionCompatWrite").GlobalNamespace())
352 if (loplugin::TypeCheck(varDecl
->getType()).Pointer().Class("IMapCompat").GlobalNamespace())
354 // passing data to gtk API and I can't figure out the types
355 if (fn
== SRCDIR
"/vcl/unx/gtk3/gtkdata.cxx")
357 // sometimes this stuff is held by tools::SvRef, sometimes by std::unique_ptr...
358 if (fn
== SRCDIR
"/sot/source/unoolestorage/xolesimplestorage.cxx")
360 // don't feel like messing with this chunk of sfx2
361 if (fn
== SRCDIR
"/sfx2/source/appl/appinit.cxx")
363 if (fn
== SRCDIR
"/svx/source/svdraw/svdobj.cxx")
365 if (fn
== SRCDIR
"/svx/source/svdraw/svdmodel.cxx")
368 if (fn
== SRCDIR
"/basic/source/comp/parser.cxx")
370 if (fn
== SRCDIR
"/basic/source/runtime/runtime.cxx")
373 if (fn
== SRCDIR
"/svx/source/form/filtnav.cxx")
375 // using clucene macros
376 if (fn
== SRCDIR
"/helpcompiler/source/HelpSearch.cxx")
379 if (fn
== SRCDIR
"/filter/source/graphicfilter/ios2met/ios2met.cxx")
381 // no idea what this is trying to do
382 if (fn
== SRCDIR
"/cui/source/customize/SvxMenuConfigPage.cxx")
384 // I cannot follow the ownership of OSQLParseNode's
385 if (fn
== SRCDIR
"/dbaccess/source/core/api/SingleSelectQueryComposer.cxx")
387 if (fn
== SRCDIR
"/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx")
390 if (fn
== SRCDIR
"/formula/source/core/api/FormulaCompiler.cxx")
392 // smuggling data around via SvxFontListItem
393 if (fn
== SRCDIR
"/extensions/source/propctrlr/fontdialog.cxx")
396 if (fn
== SRCDIR
"/sc/source/ui/docshell/documentlinkmgr.cxx")
399 if (fn
== SRCDIR
"/sc/source/core/data/stlpool.cxx")
402 if (fn
== SRCDIR
"/sc/source/core/tool/autoform.cxx")
404 // unsure about ownership
405 if (fn
== SRCDIR
"/xmlsecurity/source/framework/saxeventkeeperimpl.cxx")
407 // ScTokenArray ownership complicated between this and the group
408 if (fn
== SRCDIR
"/sc/source/core/data/formulacell.cxx")
411 if (fn
== SRCDIR
"/sw/source/core/doc/tblafmt.cxx")
414 if (fn
== SRCDIR
"/sc/source/ui/unoobj/tokenuno.cxx")
416 // SwDoc::DelTextFormatColl
417 if (fn
== SRCDIR
"/sw/source/core/doc/docfmt.cxx")
419 // SwRootFrame::CalcFrameRects
420 if (fn
== SRCDIR
"/sw/source/core/layout/trvlfrm.cxx")
423 if (fn
== SRCDIR
"/sw/source/core/undo/SwUndoPageDesc.cxx")
425 // unsure about the SwLinePortion ownership
426 if (fn
== SRCDIR
"/sw/source/core/text/itrform2.cxx")
428 // can't follow the ownership
429 if (fn
== SRCDIR
"/sw/source/filter/html/htmlatr.cxx")
431 // SwTextFormatter::BuildMultiPortion complicated
432 if (fn
== SRCDIR
"/sw/source/core/text/pormulti.cxx")
434 // SwXMLExport::ExportTableLines
435 if (fn
== SRCDIR
"/sw/source/filter/xml/xmltble.cxx")
437 // SwPagePreview::~SwPagePreview
438 if (fn
== SRCDIR
"/sw/source/uibase/uiview/pview.cxx")
440 // alloc/free routines for the hand constructed virtual function table
441 if (fn
== SRCDIR
"/sal/textenc/convertisciidevangari.cxx")
443 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/bridges/"))
446 if (fn
== SRCDIR
"/sal/rtl/bootstrap.cxx")
448 // too complicated for my small brain
449 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/cppu/"))
452 if (fn
== SRCDIR
"/vcl/source/gdi/octree.cxx")
455 if (fn
== SRCDIR
"/vcl/source/filter/graphicfilter.cxx")
458 if (fn
== SRCDIR
"/svtools/source/control/ctrltool.cxx")
461 if (fn
== SRCDIR
"/sfx2/source/control/msgpool.cxx")
464 if (fn
== SRCDIR
"/svx/source/sdr/contact/objectcontact.cxx")
467 if (fn
== SRCDIR
"/cui/source/customize/cfg.cxx")
470 if (fn
== SRCDIR
"/lotuswordpro/source/filter/lwpfribptr.cxx")
473 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/connectivity/source/drivers/file/"))
476 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/unodevtools/source/skeletonmaker/"))
479 llvm::StringRef parentName
;
480 if (auto cxxMethodDecl
= dyn_cast
<CXXMethodDecl
>(functionDecl
))
482 parentName
= cxxMethodDecl
->getParent()->getName();
485 // no idea what is going on here
486 if (parentName
== "ScChangeActionLinkEntry")
489 if (parentName
== "SfxItemSet" || parentName
== "SfxItemPool")
492 if (parentName
== "ScFunctionList" || parentName
== "SwNodes"
493 || parentName
== "SwUnoCursor" || parentName
== "SortedResultSet"
494 || parentName
== "Atom" || parentName
== "RegionBand" || parentName
== "WMFWriter"
495 || parentName
== "Scheduler" || parentName
== "OpenGLContext"
496 || parentName
== "WizardDialog")
498 // manual ref counting
499 if (parentName
== "ScBroadcastAreaSlot")
502 if (any_equal(parentName
, "SwFormatField", "FontPropertyBox", "SdFontPropertyBox",
503 "SwHTMLParser", "PDFWriterImpl", "SbiParser", "DictionaryList", "SwGlossaryHdl", "SwGlossaryGroupDlg"))
506 if (any_equal(parentName
, "SbTreeListBox"))
509 if (functionDecl
->getIdentifier())
511 auto name
= functionDecl
->getName();
512 SmallString
<256> buf
;
513 if (!parentName
.empty())
514 name
= (parentName
+ "::" + name
).toStringRef(buf
);
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 deleteExpr
->getBeginLoc())
591 << deleteExpr
->getSourceRange();
593 DiagnosticsEngine::Note
,
595 varDecl
->getBeginLoc())
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
= init
->IgnoreImplicit();
664 if (auto x
= dyn_cast
<CXXConstructExpr
>(init
))
665 if (x
->getNumArgs() == 1
666 || (x
->getNumArgs() >= 2 && isa
<CXXDefaultArgExpr
>(x
->getArg(1))))
668 init
= x
->getArg(0)->IgnoreImplicit();
670 if (auto x
= dyn_cast
<CXXMemberCallExpr
>(init
))
671 init
= x
->getImplicitObjectArgument()->IgnoreParenImpCasts();
672 if ((memberExpr
= dyn_cast
<MemberExpr
>(init
)))
674 // look for deletes of an iterator object where the iterator is over a var
675 if (auto declRefExpr2
= dyn_cast
<DeclRefExpr
>(init
))
677 if ((varDecl
= dyn_cast
<VarDecl
>(declRefExpr2
->getDecl())))
683 // look for deletes like "delete m_pField[0]"
684 if (cxxOperatorCallExpr
->getOperator() == OO_Subscript
)
686 subExpr
= cxxOperatorCallExpr
->getArg(0)->IgnoreImplicit();
687 if ((memberExpr
= dyn_cast
<MemberExpr
>(subExpr
)))
689 if (auto declRefExpr
= dyn_cast
<DeclRefExpr
>(subExpr
))
691 if ((varDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl())))
703 // OStorage_Impl::Commit very complicated ownership passing going on
704 if (fn
== SRCDIR
"/package/source/xstor/xstorage.cxx")
707 if (fn
== SRCDIR
"/vcl/source/gdi/print.cxx")
710 if (fn
== SRCDIR
"/basic/source/runtime/runtime.cxx")
713 if (fn
== SRCDIR
"/sw/source/core/bastyp/swcache.cxx")
716 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, memberExpr
, "rather manage this member with std::some_container<std::unique_ptr<T>>");
721 // ignore if the value for the var comes from somewhere else
722 if (varDecl
->hasInit() && isa
<ExplicitCastExpr
>(varDecl
->getInit()->IgnoreImpCasts()))
725 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/vcl/qa/"))
728 if (fn
== SRCDIR
"/tools/source/generic/config.cxx")
731 if (fn
== SRCDIR
"/vcl/source/gdi/regband.cxx")
734 if (fn
== SRCDIR
"/vcl/source/gdi/regionband.cxx")
737 if (fn
== SRCDIR
"/vcl/source/gdi/octree.cxx")
740 if (fn
== SRCDIR
"/vcl/source/app/scheduler.cxx")
743 if (fn
== SRCDIR
"/vcl/source/filter/wmf/wmfwr.cxx")
746 if (fn
== SRCDIR
"/vcl/source/filter/graphicfilter.cxx")
749 if (fn
== SRCDIR
"/vcl/source/app/salvtables.cxx")
751 // undo code is tricky
752 if (fn
== SRCDIR
"/svl/source/undo/undo.cxx")
754 // subclass that messes with parent class in constructor/destructor, yuck
755 if (fn
== SRCDIR
"/svtools/source/contnr/imivctl1.cxx")
758 if (fn
== SRCDIR
"/connectivity/source/parse/sqlnode.cxx")
760 // the whole svx model/contact/view thing confuses me
761 if (fn
== SRCDIR
"/svx/source/sdr/contact/viewcontact.cxx")
763 if (fn
== SRCDIR
"/svx/source/sdr/contact/objectcontact.cxx")
766 if (fn
== SRCDIR
"/svx/source/unodialogs/textconversiondlgs/chinese_dictionarydialog.cxx")
769 if (fn
== SRCDIR
"/svx/source/svdraw/svdundo.cxx")
771 // TODO the lazydelete stuff should probably just be ripped out altogether now that we have VclPtr
772 if (fn
== SRCDIR
"/vcl/source/helper/lazydelete.cxx")
775 if (fn
== SRCDIR
"/filter/source/graphicfilter/idxf/dxfblkrd.cxx")
777 if (fn
== SRCDIR
"/filter/source/graphicfilter/idxf/dxftblrd.cxx")
779 if (fn
== SRCDIR
"/lotuswordpro/source/filter/utlist.cxx")
781 if (fn
== SRCDIR
"/lotuswordpro/source/filter/lwpfribptr.cxx")
784 if (fn
== SRCDIR
"/sd/source/ui/sidebar/MasterPagesSelector.cxx")
787 if (fn
== SRCDIR
"/sd/source/filter/ppt/pptatom.cxx")
790 if (fn
== SRCDIR
"/sc/source/core/data/funcdesc.cxx")
793 if (fn
== SRCDIR
"/sw/source/core/crsr/crsrsh.cxx")
796 if (fn
== SRCDIR
"/sw/source/core/docnode/nodes.cxx")
799 if (fn
== SRCDIR
"/sw/source/core/unocore/unocrsr.cxx")
802 if (fn
== SRCDIR
"/filter/source/graphicfilter/idxf/dxfentrd.cxx")
805 if (fn
== SRCDIR
"/filter/source/graphicfilter/ios2met/ios2met.cxx")
807 // sometimes owning, sometimes not
808 if (fn
== SRCDIR
"/sw/qa/core/Test-BigPtrArray.cxx")
812 DiagnosticsEngine::Warning
,
813 "loopdelete: rather manage this var with std::some_container<std::unique_ptr<T>>",
814 deleteExpr
->getBeginLoc())
815 << deleteExpr
->getSourceRange();
817 DiagnosticsEngine::Note
,
819 varDecl
->getBeginLoc())
820 << varDecl
->getSourceRange();
824 void UseUniquePtr::CheckCXXForRangeStmt(const FunctionDecl
* functionDecl
, const CXXForRangeStmt
* cxxForRangeStmt
)
826 CXXDeleteExpr
const * deleteExpr
= nullptr;
827 if (auto compoundStmt
= dyn_cast
<CompoundStmt
>(cxxForRangeStmt
->getBody()))
829 for (auto i
= compoundStmt
->body_begin(); i
!= compoundStmt
->body_end(); ++i
)
830 if ((deleteExpr
= dyn_cast
<CXXDeleteExpr
>(*i
)))
834 deleteExpr
= dyn_cast
<CXXDeleteExpr
>(cxxForRangeStmt
->getBody());
838 // check for delete of member
839 if (auto memberExpr
= dyn_cast
<MemberExpr
>(cxxForRangeStmt
->getRangeInit()))
841 auto fieldDecl
= dyn_cast
<FieldDecl
>(memberExpr
->getMemberDecl());
846 if (fn
== SRCDIR
"/vcl/source/gdi/print.cxx")
848 // sometimes it's an owning field, sometimes not
849 if (fn
== SRCDIR
"/i18npool/source/localedata/localedata.cxx")
852 CheckMemberDeleteExpr(functionDecl
, deleteExpr
, memberExpr
, "rather manage this with std::some_container<std::unique_ptr<T>>");
855 // check for delete of var
856 if (auto declRefExpr
= dyn_cast
<DeclRefExpr
>(cxxForRangeStmt
->getRangeInit()->IgnoreParens()->IgnoreImplicit()))
858 auto varDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl());
862 // don't feel like messing with this part of sfx2
863 if (fn
== SRCDIR
"/sfx2/source/control/msgpool.cxx")
865 if (fn
== SRCDIR
"/sfx2/source/doc/doctemplates.cxx")
868 if (fn
== SRCDIR
"/hwpfilter/source/grammar.cxx")
870 if (fn
== SRCDIR
"/hwpfilter/source/formula.cxx")
872 // no idea why, but ui tests crash afterwards in weird ways
873 if (fn
== SRCDIR
"/svtools/source/control/roadmap.cxx")
875 // sometimes it owns it, sometimes it does not
876 if (fn
== SRCDIR
"/dbaccess/source/ui/misc/WCopyTable.cxx")
879 if (fn
== SRCDIR
"/dbaccess/source/ui/misc/UITools.cxx")
882 if (fn
== SRCDIR
"/sw/source/core/bastyp/init.cxx")
885 if (fn
== SRCDIR
"/reportdesign/source/ui/misc/UITools.cxx")
888 if (fn
== SRCDIR
"/reportdesign/source/ui/report/ReportController.cxx")
891 if (fn
== SRCDIR
"/svx/source/sdr/contact/viewcontact.cxx")
893 if (fn
== SRCDIR
"/svx/source/sdr/contact/objectcontact.cxx")
897 DiagnosticsEngine::Warning
,
898 "rather manage this var with std::some_container<std::unique_ptr<T>>",
899 deleteExpr
->getBeginLoc())
900 << deleteExpr
->getSourceRange();
902 DiagnosticsEngine::Note
,
904 varDecl
->getBeginLoc())
905 << varDecl
->getSourceRange();
909 void UseUniquePtr::CheckMemberDeleteExpr(const FunctionDecl
* functionDecl
, const CXXDeleteExpr
* deleteExpr
,
910 const MemberExpr
* memberExpr
, StringRef message
)
912 // ignore union games
913 const FieldDecl
* fieldDecl
= dyn_cast
<FieldDecl
>(memberExpr
->getMemberDecl());
916 TagDecl
const * td
= dyn_cast
<TagDecl
>(fieldDecl
->getDeclContext());
920 // ignore calling delete on someone else's field
921 if (auto methodDecl
= dyn_cast
<CXXMethodDecl
>(functionDecl
))
922 if (fieldDecl
->getParent() != methodDecl
->getParent() )
925 if (ignoreLocation(fieldDecl
))
927 // to ignore things like the CPPUNIT macros
928 if (loplugin::hasPathnamePrefix(fn
, WORKDIR
"/"))
930 // passes and stores pointers to member fields
931 if (fn
== SRCDIR
"/sot/source/sdstor/stgdir.hxx")
933 // something platform-specific
934 if (fn
== SRCDIR
"/hwpfilter/source/htags.h")
936 // passes pointers to member fields
937 if (fn
== SRCDIR
"/sd/inc/sdpptwrp.hxx")
939 // @TODO intrusive linked-lists here, with some trickiness
940 if (fn
== SRCDIR
"/sw/source/filter/html/parcss1.hxx")
942 // @TODO SwDoc has some weird ref-counting going on
943 if (fn
== SRCDIR
"/sw/inc/shellio.hxx")
945 // @TODO it's sharing pointers with another class
946 if (fn
== SRCDIR
"/sc/inc/formulacell.hxx")
948 // some weird stuff going on here around struct Entity
949 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sax/"))
951 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/include/sax/"))
953 // manipulation of tree structures ie. StgAvlNode, don't lend themselves to std::unique_ptr
954 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/sot/"))
956 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/include/sot/"))
958 // the std::vector is being passed to another class
959 if (fn
== SRCDIR
"/sfx2/source/explorer/nochaos.cxx")
961 auto tc
= loplugin::TypeCheck(fieldDecl
->getType());
962 // these sw::Ring based classes do not lend themselves to std::unique_ptr management
963 if (tc
.Pointer().Class("SwNodeIndex").GlobalNamespace() || tc
.Pointer().Class("SwShellTableCursor").GlobalNamespace()
964 || tc
.Pointer().Class("SwBlockCursor").GlobalNamespace() || tc
.Pointer().Class("SwVisibleCursor").GlobalNamespace()
965 || tc
.Pointer().Class("SwShellCursor").GlobalNamespace())
967 // there is a loop in ~ImplPrnQueueList deleting stuff on a global data structure
968 if (fn
== SRCDIR
"/vcl/inc/print.h")
970 // painful linked list
971 if (fn
== SRCDIR
"/basic/source/inc/runtime.hxx")
973 // not sure how the node management is working here
974 if (fn
== SRCDIR
"/i18npool/source/localedata/saxparser.cxx")
976 // has a pointer that it only sometimes owns
977 if (fn
== SRCDIR
"/editeng/source/editeng/impedit.hxx")
981 DiagnosticsEngine::Warning
,
983 deleteExpr
->getBeginLoc())
984 << deleteExpr
->getSourceRange();
986 DiagnosticsEngine::Note
,
988 fieldDecl
->getBeginLoc())
989 << fieldDecl
->getSourceRange();
992 bool UseUniquePtr::TraverseFunctionDecl(FunctionDecl
* functionDecl
)
994 if (ignoreLocation(functionDecl
))
997 auto oldCurrent
= mpCurrentFunctionDecl
;
998 mpCurrentFunctionDecl
= functionDecl
;
999 bool ret
= RecursiveASTVisitor::TraverseFunctionDecl(functionDecl
);
1000 mpCurrentFunctionDecl
= oldCurrent
;
1005 bool UseUniquePtr::TraverseCXXMethodDecl(CXXMethodDecl
* methodDecl
)
1007 if (ignoreLocation(methodDecl
))
1010 auto oldCurrent
= mpCurrentFunctionDecl
;
1011 mpCurrentFunctionDecl
= methodDecl
;
1012 bool ret
= RecursiveASTVisitor::TraverseCXXMethodDecl(methodDecl
);
1013 mpCurrentFunctionDecl
= oldCurrent
;
1018 bool UseUniquePtr::TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl
* methodDecl
)
1020 if (ignoreLocation(methodDecl
))
1023 auto oldCurrent
= mpCurrentFunctionDecl
;
1024 mpCurrentFunctionDecl
= methodDecl
;
1025 bool ret
= RecursiveASTVisitor::TraverseCXXDeductionGuideDecl(methodDecl
);
1026 mpCurrentFunctionDecl
= oldCurrent
;
1031 bool UseUniquePtr::TraverseCXXConstructorDecl(CXXConstructorDecl
* methodDecl
)
1033 if (ignoreLocation(methodDecl
))
1036 auto oldCurrent
= mpCurrentFunctionDecl
;
1037 mpCurrentFunctionDecl
= methodDecl
;
1038 bool ret
= RecursiveASTVisitor::TraverseCXXConstructorDecl(methodDecl
);
1039 mpCurrentFunctionDecl
= oldCurrent
;
1044 bool UseUniquePtr::TraverseCXXConversionDecl(CXXConversionDecl
* methodDecl
)
1046 if (ignoreLocation(methodDecl
))
1049 auto oldCurrent
= mpCurrentFunctionDecl
;
1050 mpCurrentFunctionDecl
= methodDecl
;
1051 bool ret
= RecursiveASTVisitor::TraverseCXXConversionDecl(methodDecl
);
1052 mpCurrentFunctionDecl
= oldCurrent
;
1057 bool UseUniquePtr::TraverseCXXDestructorDecl(CXXDestructorDecl
* methodDecl
)
1059 if (ignoreLocation(methodDecl
))
1062 auto oldCurrent
= mpCurrentFunctionDecl
;
1063 mpCurrentFunctionDecl
= methodDecl
;
1064 bool ret
= RecursiveASTVisitor::TraverseCXXDestructorDecl(methodDecl
);
1065 mpCurrentFunctionDecl
= oldCurrent
;
1070 bool UseUniquePtr::TraverseConstructorInitializer(CXXCtorInitializer
* ctorInit
)
1072 if (!ctorInit
->getSourceLocation().isValid() || ignoreLocation(ctorInit
->getSourceLocation()))
1074 if (!ctorInit
->getMember())
1076 if (!loplugin::TypeCheck(ctorInit
->getMember()->getType()).Class("unique_ptr").StdNamespace())
1078 auto constructExpr
= dyn_cast_or_null
<CXXConstructExpr
>(ctorInit
->getInit());
1079 if (!constructExpr
|| constructExpr
->getNumArgs() == 0)
1081 auto init
= constructExpr
->getArg(0)->IgnoreImpCasts();
1082 if (!isa
<DeclRefExpr
>(init
))
1085 StringRef fn
= getFilenameOfLocation(compiler
.getSourceManager().getSpellingLoc(ctorInit
->getSourceLocation()));
1086 // cannot change URE
1087 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx"))
1091 DiagnosticsEngine::Warning
,
1092 "should be passing via std::unique_ptr param",
1093 ctorInit
->getSourceLocation())
1094 << ctorInit
->getSourceRange();
1095 return RecursiveASTVisitor
<UseUniquePtr
>::TraverseConstructorInitializer(ctorInit
);
1098 // Only checks for calls to delete on a pointer param
1099 bool UseUniquePtr::VisitCXXDeleteExpr(const CXXDeleteExpr
* deleteExpr
)
1101 if (!mpCurrentFunctionDecl
)
1103 if (ignoreLocation(mpCurrentFunctionDecl
))
1105 if (isInUnoIncludeFile(mpCurrentFunctionDecl
->getCanonicalDecl()->getBeginLoc()))
1107 auto declRefExpr
= dyn_cast
<DeclRefExpr
>(deleteExpr
->getArgument()->IgnoreParenImpCasts()->IgnoreImplicit());
1110 if (auto parmVarDecl
= dyn_cast
<ParmVarDecl
>(declRefExpr
->getDecl()))
1111 CheckDeleteParmVar(deleteExpr
, parmVarDecl
);
1112 else if (auto varDecl
= dyn_cast
<VarDecl
>(declRefExpr
->getDecl()))
1113 CheckDeleteLocalVar(mpCurrentFunctionDecl
, deleteExpr
, varDecl
);
1117 void UseUniquePtr::CheckDeleteParmVar(const CXXDeleteExpr
* deleteExpr
, const ParmVarDecl
* )
1119 if (mpCurrentFunctionDecl
->getIdentifier())
1121 auto name
= mpCurrentFunctionDecl
->getName();
1122 if (name
== "delete_IncludesCollection" || name
== "convertName"
1123 || name
== "createNamedType"
1124 || name
== "typelib_typedescriptionreference_release" || name
== "deleteExceptions"
1125 || name
== "uno_threadpool_destroy"
1126 || name
== "AddRanges_Impl"
1127 || name
== "DestroySalInstance"
1128 || name
== "ImplHandleUserEvent"
1129 || name
== "releaseDecimalPtr" // TODO, basic
1130 || name
== "replaceAndReset" // TODO, connectivity
1131 || name
== "intrusive_ptr_release"
1132 || name
== "FreeParaList"
1133 || name
== "DeleteSdrUndoAction" // TODO, sc
1134 || name
== "lcl_MergeGCBox" || name
== "lcl_MergeGCLine" || name
== "lcl_DelHFFormat")
1137 if (auto cxxMethodDecl
= dyn_cast
<CXXMethodDecl
>(mpCurrentFunctionDecl
))
1139 auto parentName
= cxxMethodDecl
->getParent()->getName();
1140 // include/o3tl/deleter.hxx
1141 if (parentName
== "default_delete")
1143 // TODO Bitmap::ReleaseAccess
1144 // Tricky because it reverberates through other code and requires that BitmapWriteAccess move into /include again
1145 if (parentName
== "Bitmap")
1147 // TODO virtual ones are much trickier, leave for later
1148 if (cxxMethodDecl
->isVirtual())
1150 // sw/inc/unobaseclass.hxx holds SolarMutex while deleting
1151 if (parentName
== "UnoImplPtrDeleter")
1155 // StgAvlNode::Remove
1156 if (fn
== SRCDIR
"/sot/source/sdstor/stgavl.cxx")
1158 // SfxItemPool::ReleaseDefaults and SfxItemPool::Free
1159 if (fn
== SRCDIR
"/svl/source/items/itempool.cxx")
1162 if (fn
== SRCDIR
"/sw/source/core/text/txtfly.cxx")
1164 // too messy to cope with the SQL parser
1165 if (fn
== SRCDIR
"/connectivity/source/parse/sqlnode.cxx")
1167 // I can't figure out the ownership of the SfxMedium in the call site(s)
1168 if (fn
== SRCDIR
"/sfx2/source/doc/sfxbasemodel.cxx")
1170 // pointer passed via IMPL_LINK
1171 if (fn
== SRCDIR
"/sfx2/source/control/dispatch.cxx")
1173 // NavigatorTreeModel::Remove
1174 if (fn
== SRCDIR
"/svx/source/form/navigatortreemodel.cxx")
1176 // SdrModel::AddUndo
1177 if (fn
== SRCDIR
"/svx/source/svdraw/svdmodel.cxx")
1180 if (fn
== SRCDIR
"/basctl/source/basicide/baside3.cxx")
1182 // ActualizeProgress::TimeoutHdl
1183 if (fn
== SRCDIR
"/cui/source/dialogs/cuigaldlg.cxx")
1185 // ToolbarSaveInData::RemoveToolbar
1186 if (fn
== SRCDIR
"/cui/source/customize/cfg.cxx")
1188 // OStorage_Impl::RemoveElement very complicated ownership passing going on
1189 if (fn
== SRCDIR
"/package/source/xstor/xstorage.cxx")
1191 // actually held via shared_ptr, uses protected deleter object
1192 if (fn
== SRCDIR
"/sd/source/ui/framework/tools/FrameworkHelper.cxx")
1194 // actually held via shared_ptr, uses protected deleter object
1195 if (fn
== SRCDIR
"/sd/source/ui/presenter/CanvasUpdateRequester.cxx")
1197 // actually held via shared_ptr, uses protected deleter object
1198 if (fn
== SRCDIR
"/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx")
1200 // actually held via shared_ptr, uses protected deleter object
1201 if (fn
== SRCDIR
"/sd/source/ui/sidebar/MasterPageContainer.cxx")
1203 // actually held via shared_ptr, uses protected deleter object
1204 if (fn
== SRCDIR
"/sd/source/ui/tools/TimerBasedTaskExecution.cxx")
1206 // actually held via shared_ptr, uses protected deleter object
1207 if (fn
== SRCDIR
"/sd/source/ui/view/ViewShellImplementation.cxx")
1209 // ScBroadcastAreaSlot::StartListeningArea manual ref-counting of ScBroadcastArea
1210 if (fn
== SRCDIR
"/sc/source/core/data/bcaslot.cxx")
1212 // ScDrawLayer::AddCalcUndo undo stuff
1213 if (fn
== SRCDIR
"/sc/source/core/data/drwlayer.cxx")
1215 // ScTable::SetFormulaCell
1216 if (fn
== SRCDIR
"/sc/source/core/data/table2.cxx")
1218 // ScDocument::SetFormulaCell
1219 if (fn
== SRCDIR
"/sc/source/core/data/documen2.cxx")
1221 // RemoveEditAttribsHandler, stored in mdds block
1222 if (fn
== SRCDIR
"/sc/source/core/data/column2.cxx")
1224 // just turns into a mess
1225 if (fn
== SRCDIR
"/sc/source/ui/Accessibility/AccessibleDocument.cxx")
1227 // SwCache::DeleteObj, linked list
1228 if (fn
== SRCDIR
"/sw/source/core/bastyp/swcache.cxx")
1230 // SAXEventKeeperImpl::smashBufferNode
1231 if (fn
== SRCDIR
"/xmlsecurity/source/framework/saxeventkeeperimpl.cxx")
1233 // SwDoc::DeleteExtTextInput
1234 if (fn
== SRCDIR
"/sw/source/core/doc/extinput.cxx")
1236 // SwDoc::DelSectionFormat
1237 if (fn
== SRCDIR
"/sw/source/core/docnode/ndsect.cxx")
1239 // SwFrame::DestroyFrame
1240 if (fn
== SRCDIR
"/sw/source/core/layout/ssfrm.cxx")
1242 // SwGluePortion::Join
1243 if (fn
== SRCDIR
"/sw/source/core/text/porglue.cxx")
1245 // SwDoc::DelFrameFormat
1246 if (fn
== SRCDIR
"/sw/source/core/doc/docfmt.cxx")
1248 // SwTextAttr::Destroy
1249 if (fn
== SRCDIR
"/sw/source/core/txtnode/txatbase.cxx")
1251 // IMPL_LINK( SwDoc, AddDrawUndo, SdrUndoAction *, pUndo, void )
1252 if (fn
== SRCDIR
"/sw/source/core/undo/undraw.cxx")
1254 // SwHTMLParser::EndAttr
1255 if (fn
== SRCDIR
"/sw/source/filter/html/swhtml.cxx")
1257 // SwGlossaryHdl::Expand sometimes the pointer is owned, sometimes it is not
1258 if (fn
== SRCDIR
"/sw/source/uibase/dochdl/gloshdl.cxx")
1260 // SwWrtShell::Insert only owned sometimes
1261 if (fn
== SRCDIR
"/sw/source/uibase/wrtsh/wrtsh1.cxx")
1264 if (fn
== SRCDIR
"/unoxml/source/rdf/librdf_repository.cxx")
1266 // SmCursor::LineToList ran out of enthusiasm to rework the node handling
1267 if (fn
== SRCDIR
"/starmath/source/cursor.cxx")
1269 // XMLEventOASISTransformerContext::FlushEventMap
1270 if (fn
== SRCDIR
"/xmloff/source/transform/EventOASISTContext.cxx")
1272 // XMLEventOOoTransformerContext::FlushEventMap
1273 if (fn
== SRCDIR
"/xmloff/source/transform/EventOOoTContext.cxx")
1275 // SbiProcDef::Match
1276 if (fn
== SRCDIR
"/basic/source/comp/symtbl.cxx")
1280 Sometimes we can pass the param as std::unique_ptr<T>& or std::unique_ptr, sometimes the method
1281 just needs to be inlined, which normally exposes more simplification.
1284 DiagnosticsEngine::Warning
,
1285 "calling delete on a pointer param, should be either allowlisted or simplified",
1286 deleteExpr
->getBeginLoc())
1287 << deleteExpr
->getSourceRange();
1291 loplugin::Plugin::Registration
< UseUniquePtr
> X("useuniqueptr", false);
1295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */