From ef82ccdda93186b4cab55aeac3844295194120a4 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Fri, 11 Mar 2022 10:48:06 +0200 Subject: new loplugin:trivialconstructor Change-Id: Iaaf63c49ce94987ab9c4ebc68e963cc3054a3c34 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131342 Tested-by: Jenkins Reviewed-by: Noel Grandin --- basic/inc/sbxfac.hxx | 1 - compilerplugins/clang/trivialconstructor.cxx | 146 +++++++++++++++++++++++++++ forms/source/xforms/namedcollection.hxx | 1 - include/comphelper/SelectionMultiplex.hxx | 1 - include/editeng/editview.hxx | 1 - include/editeng/svxacorr.hxx | 1 - include/filter/msfilter/escherex.hxx | 2 - include/formula/IFunctionDescription.hxx | 4 - include/oox/drawingml/chart/modelbase.hxx | 4 - include/svx/gridctrl.hxx | 1 - starmath/inc/parsebase.hxx | 1 - sw/inc/IDocumentExternalData.hxx | 1 - sw/source/core/inc/SwPortionHandler.hxx | 2 - vcl/inc/salmenu.hxx | 2 - vcl/inc/salsys.hxx | 1 - 15 files changed, 146 insertions(+), 23 deletions(-) create mode 100644 compilerplugins/clang/trivialconstructor.cxx diff --git a/basic/inc/sbxfac.hxx b/basic/inc/sbxfac.hxx index bbdbcb018f0b..5493a6687e00 100644 --- a/basic/inc/sbxfac.hxx +++ b/basic/inc/sbxfac.hxx @@ -26,7 +26,6 @@ class SbxFactory { public: virtual ~SbxFactory(); - SbxFactory() {} virtual SbxBaseRef Create(sal_uInt16 nSbxId, sal_uInt32); virtual SbxObjectRef CreateObject(const OUString&); }; diff --git a/compilerplugins/clang/trivialconstructor.cxx b/compilerplugins/clang/trivialconstructor.cxx new file mode 100644 index 000000000000..6f5bb640b760 --- /dev/null +++ b/compilerplugins/clang/trivialconstructor.cxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Look for declared constructors that can be trivial (and therefore don't need to be declared) + +namespace +{ +class TrivialConstructor : public loplugin::FilteringPlugin +{ +public: + explicit TrivialConstructor(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXConstructorDecl(CXXConstructorDecl const*); + +private: + bool HasTrivialConstructorBody(const CXXRecordDecl* BaseClassDecl, + const CXXRecordDecl* MostDerivedClassDecl); + bool FieldHasTrivialConstructorBody(const FieldDecl* Field); +}; + +bool TrivialConstructor::VisitCXXConstructorDecl(CXXConstructorDecl const* constructorDecl) +{ + if (ignoreLocation(constructorDecl)) + return true; + if (!constructorDecl->hasTrivialBody()) + return true; + if (constructorDecl->isExplicit()) + return true; + if (!constructorDecl->isDefaultConstructor()) + return true; + if (!constructorDecl->inits().empty()) + return true; + if (constructorDecl->getExceptionSpecType() != EST_None) + return true; + if (constructorDecl->getAccess() != AS_public) + return true; + if (!constructorDecl->isThisDeclarationADefinition()) + return true; + if (isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc(constructorDecl->getLocation()))) + return true; + const CXXRecordDecl* recordDecl = constructorDecl->getParent(); + if (std::distance(recordDecl->ctor_begin(), recordDecl->ctor_end()) != 1) + return true; + if (!HasTrivialConstructorBody(recordDecl, recordDecl)) + return true; + + // template magic in sc/inc/stlalgorithm.hxx + if (recordDecl->getIdentifier() && recordDecl->getName() == "AlignedAllocator") + return true; + + report(DiagnosticsEngine::Warning, "no need for explicit constructor decl", + constructorDecl->getLocation()) + << constructorDecl->getSourceRange(); + if (constructorDecl->getCanonicalDecl() != constructorDecl) + { + constructorDecl = constructorDecl->getCanonicalDecl(); + report(DiagnosticsEngine::Warning, "no need for explicit constructor decl", + constructorDecl->getLocation()) + << constructorDecl->getSourceRange(); + } + return true; +} + +bool TrivialConstructor::HasTrivialConstructorBody(const CXXRecordDecl* BaseClassDecl, + const CXXRecordDecl* MostDerivedClassDecl) +{ + if (BaseClassDecl != MostDerivedClassDecl && !BaseClassDecl->hasTrivialDefaultConstructor()) + return false; + + // Check fields. + for (const auto* field : BaseClassDecl->fields()) + if (!FieldHasTrivialConstructorBody(field)) + return false; + + // Check non-virtual bases. + for (const auto& I : BaseClassDecl->bases()) + { + if (I.isVirtual()) + continue; + if (!I.getType()->isRecordType()) + continue; + const CXXRecordDecl* NonVirtualBase = I.getType()->getAsCXXRecordDecl(); + if (NonVirtualBase && !HasTrivialConstructorBody(NonVirtualBase, MostDerivedClassDecl)) + return false; + } + + if (BaseClassDecl == MostDerivedClassDecl) + { + // Check virtual bases. + for (const auto& I : BaseClassDecl->vbases()) + { + if (!I.getType()->isRecordType()) + continue; + const CXXRecordDecl* VirtualBase = I.getType()->getAsCXXRecordDecl(); + if (VirtualBase && !HasTrivialConstructorBody(VirtualBase, MostDerivedClassDecl)) + return false; + } + } + return true; +} + +bool TrivialConstructor::FieldHasTrivialConstructorBody(const FieldDecl* Field) +{ + QualType FieldBaseElementType = compiler.getASTContext().getBaseElementType(Field->getType()); + + const RecordType* RT = FieldBaseElementType->getAs(); + if (!RT) + return true; + + CXXRecordDecl* FieldClassDecl = cast(RT->getDecl()); + + // The constructor for an implicit anonymous union member is never invoked. + if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) + return false; + + return FieldClassDecl->hasTrivialDefaultConstructor(); +} + +loplugin::Plugin::Registration X("trivialconstructor", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/namedcollection.hxx b/forms/source/xforms/namedcollection.hxx index 10eeafcfd65b..f5fed0c09572 100644 --- a/forms/source/xforms/namedcollection.hxx +++ b/forms/source/xforms/namedcollection.hxx @@ -37,7 +37,6 @@ class NamedCollection : public cppu::ImplInheritanceHelper< using Collection::hasItem; public: - NamedCollection() {} const T& getItem( const OUString& rName ) const { diff --git a/include/comphelper/SelectionMultiplex.hxx b/include/comphelper/SelectionMultiplex.hxx index 00ba7f955b09..c1a1842f2ee0 100644 --- a/include/comphelper/SelectionMultiplex.hxx +++ b/include/comphelper/SelectionMultiplex.hxx @@ -42,7 +42,6 @@ namespace comphelper friend class OSelectionChangeMultiplexer; public: - OSelectionChangeListener() {} virtual ~OSelectionChangeListener(); /// @throws css::uno::RuntimeException diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx index 6d3a09664767..4f312b578a62 100644 --- a/include/editeng/editview.hxx +++ b/include/editeng/editview.hxx @@ -95,7 +95,6 @@ enum class ScrollRangeCheck class EDITENG_DLLPUBLIC EditViewCallbacks { public: - EditViewCallbacks() {} virtual ~EditViewCallbacks(); // call this when text visualization changed in any way. It diff --git a/include/editeng/svxacorr.hxx b/include/editeng/svxacorr.hxx index e45cec1279eb..4197b456214c 100644 --- a/include/editeng/svxacorr.hxx +++ b/include/editeng/svxacorr.hxx @@ -98,7 +98,6 @@ enum class ACQuotes class EDITENG_DLLPUBLIC SvxAutoCorrDoc { public: - SvxAutoCorrDoc() {} virtual ~SvxAutoCorrDoc(); virtual bool Delete( sal_Int32 nStt, sal_Int32 nEnd ) = 0; diff --git a/include/filter/msfilter/escherex.hxx b/include/filter/msfilter/escherex.hxx index b4fdad459da9..dd13b5c72cf1 100644 --- a/include/filter/msfilter/escherex.hxx +++ b/include/filter/msfilter/escherex.hxx @@ -885,7 +885,6 @@ class EscherEx; class MSFILTER_DLLPUBLIC EscherExClientRecord_Base { public: - EscherExClientRecord_Base() {} virtual ~EscherExClientRecord_Base(); /// Application writes the record header @@ -899,7 +898,6 @@ public: class MSFILTER_DLLPUBLIC EscherExClientAnchor_Base { public: - EscherExClientAnchor_Base() {} virtual ~EscherExClientAnchor_Base(); /// Application writes the record header diff --git a/include/formula/IFunctionDescription.hxx b/include/formula/IFunctionDescription.hxx index b27907fedca5..28f293704364 100644 --- a/include/formula/IFunctionDescription.hxx +++ b/include/formula/IFunctionDescription.hxx @@ -48,7 +48,6 @@ namespace formula class SAL_NO_VTABLE IFunctionManager { public: - IFunctionManager(){} enum EToken { eOk, @@ -70,7 +69,6 @@ namespace formula class SAL_NO_VTABLE IFunctionCategory { public: - IFunctionCategory(){} virtual sal_uInt32 getCount() const = 0; virtual const IFunctionDescription* getFunction(sal_uInt32 _nPos) const = 0; virtual sal_uInt32 getNumber() const = 0; @@ -83,7 +81,6 @@ namespace formula class SAL_NO_VTABLE IFunctionDescription { public: - IFunctionDescription(){} virtual OUString getFunctionName() const = 0; virtual const IFunctionCategory* getCategory() const = 0; virtual OUString getDescription() const = 0; @@ -113,7 +110,6 @@ namespace formula class SAL_NO_VTABLE IFormulaEditorHelper { public: - IFormulaEditorHelper(){} virtual void notifyChange() = 0; virtual void fill() = 0; diff --git a/include/oox/drawingml/chart/modelbase.hxx b/include/oox/drawingml/chart/modelbase.hxx index a167077753e0..581713bbc9e1 100644 --- a/include/oox/drawingml/chart/modelbase.hxx +++ b/include/oox/drawingml/chart/modelbase.hxx @@ -58,8 +58,6 @@ public: typedef typename RefVector< ModelType >::value_type value_type; typedef typename RefVector< ModelType >::size_type size_type; - ModelVector() {} - ModelType& create() { return append( std::make_shared() ); } template< typename Param1Type > ModelType& create( const Param1Type& rParam1 ) { return append( std::make_shared( rParam1 ) ); } @@ -84,8 +82,6 @@ public: typedef typename RefMap< KeyType, ModelType >::mapped_type mapped_type; typedef typename RefMap< KeyType, ModelType >::value_type value_type; - ModelMap() {} - ModelType& create( KeyType eKey ) { return insert( eKey, new ModelType ); } private: diff --git a/include/svx/gridctrl.hxx b/include/svx/gridctrl.hxx index 9551afcbb8da..e029b8e23f8a 100644 --- a/include/svx/gridctrl.hxx +++ b/include/svx/gridctrl.hxx @@ -517,7 +517,6 @@ public: { friend class DbCellControl; friend class RowSetEventListener; - GrantControlAccess() { } }; /// called when a controller needs to be re-initialized diff --git a/starmath/inc/parsebase.hxx b/starmath/inc/parsebase.hxx index c5618525626f..ffa9b538a2b0 100644 --- a/starmath/inc/parsebase.hxx +++ b/starmath/inc/parsebase.hxx @@ -93,7 +93,6 @@ OUString getParseErrorDesc(SmParseError err); class AbstractSmParser { public: - AbstractSmParser() {} virtual ~AbstractSmParser() {} /** Parse rBuffer to formula tree */ diff --git a/sw/inc/IDocumentExternalData.hxx b/sw/inc/IDocumentExternalData.hxx index 7ed3dfafb279..50ab4f2d2189 100644 --- a/sw/inc/IDocumentExternalData.hxx +++ b/sw/inc/IDocumentExternalData.hxx @@ -35,7 +35,6 @@ struct ExternalDataTypeHash class ExternalData { public: - ExternalData() {} virtual ~ExternalData() {} }; diff --git a/sw/source/core/inc/SwPortionHandler.hxx b/sw/source/core/inc/SwPortionHandler.hxx index 2036b0a66d5f..c183781d8fea 100644 --- a/sw/source/core/inc/SwPortionHandler.hxx +++ b/sw/source/core/inc/SwPortionHandler.hxx @@ -46,8 +46,6 @@ class SW_DLLPUBLIC SwPortionHandler { public: - SwPortionHandler() {} /// (empty) constructor - virtual ~SwPortionHandler() {} /// (empty) destructor /** text portion. A run of nLength characters from the view diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx index c696503549e6..79254d9f5fd5 100644 --- a/vcl/inc/salmenu.hxx +++ b/vcl/inc/salmenu.hxx @@ -51,14 +51,12 @@ struct SalMenuButtonItem class VCL_PLUGIN_PUBLIC SalMenuItem { public: - SalMenuItem() {} virtual ~SalMenuItem(); }; class VCL_PLUGIN_PUBLIC SalMenu { public: - SalMenu() {} virtual ~SalMenu(); virtual bool VisibleMenuBar() = 0; // must return true to actually DISPLAY native menu bars diff --git a/vcl/inc/salsys.hxx b/vcl/inc/salsys.hxx index cf89bff59259..dff65b2f35cd 100644 --- a/vcl/inc/salsys.hxx +++ b/vcl/inc/salsys.hxx @@ -30,7 +30,6 @@ const int SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK = 1; class VCL_PLUGIN_PUBLIC SalSystem { public: - SalSystem() {} virtual ~SalSystem(); // get info about the display -- cgit