[Libreoffice-commits] core.git: compilerplugins/clang editeng/source include/editeng

Noel Grandin noel at peralex.com
Fri Jan 22 04:15:28 PST 2016


 compilerplugins/clang/sfxpoolitem.cxx |  147 ++++++++++++++++++++++++++++++++++
 editeng/source/items/paraitem.cxx     |    8 +
 include/editeng/pmdlitem.hxx          |    1 
 3 files changed, 156 insertions(+)

New commits:
commit 370294f6d1471b89a30c1f8b917cde3830d66b2f
Author: Noel Grandin <noel at peralex.com>
Date:   Tue Dec 8 14:17:07 2015 +0200

    new loplugin sfxpoolitem
    
    generates a warning about subclasses that add members but do not
    override operator==()
    
    Change-Id: If6df1a2cbd115f17bcca22f9b7995181dcf55c03
    Reviewed-on: https://gerrit.libreoffice.org/20468
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>

diff --git a/compilerplugins/clang/sfxpoolitem.cxx b/compilerplugins/clang/sfxpoolitem.cxx
new file mode 100644
index 0000000..3248135
--- /dev/null
+++ b/compilerplugins/clang/sfxpoolitem.cxx
@@ -0,0 +1,147 @@
+/* -*- 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 <string>
+#include <iostream>
+
+#include "plugin.hxx"
+#include "compat.hxx"
+#include "clang/AST/CXXInheritance.h"
+
+/*
+what might be more interesting is a warning about subclasses that add
+members but do not override virtual operator==() - that is easily
+forgotten and hard to notice.
+*/
+namespace {
+
+class SfxPoolItem:
+    public RecursiveASTVisitor<SfxPoolItem>, public loplugin::Plugin
+{
+public:
+    explicit SfxPoolItem(InstantiationData const & data): Plugin(data) {}
+
+    virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
+
+    bool VisitCXXRecordDecl( const CXXRecordDecl* );
+};
+
+bool BaseCheckNotSfxPoolItemSubclass(
+    const CXXRecordDecl *BaseDefinition
+#if __clang_major__ == 3 && __clang_minor__ <= 7
+    , void *
+#endif
+    )
+{
+    if (BaseDefinition && BaseDefinition->getQualifiedNameAsString() == "SfxPoolItem") {
+        return false;
+    }
+    return true;
+}
+
+bool isDerivedFromSfxPoolItem(const CXXRecordDecl *decl) {
+    if (!decl)
+        return false;
+    if (decl->getQualifiedNameAsString() == "SfxPoolItem")
+        return true;
+    if (!decl->hasDefinition()) {
+        return false;
+    }
+    if (// not sure what hasAnyDependentBases() does,
+        // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1
+        !decl->hasAnyDependentBases() &&
+        !compat::forallBases(*decl, BaseCheckNotSfxPoolItemSubclass, nullptr, true)) {
+        return true;
+    }
+    return false;
+}
+
+
+bool BaseCheckNotSwMsgPoolItemSubclass(
+    const CXXRecordDecl *BaseDefinition
+#if __clang_major__ == 3 && __clang_minor__ <= 7
+    , void *
+#endif
+    )
+{
+    if (BaseDefinition && BaseDefinition->getQualifiedNameAsString() == "SwMsgPoolItem") {
+        return false;
+    }
+    return true;
+}
+
+bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl *decl) {
+    if (!decl)
+        return false;
+    if (decl->getQualifiedNameAsString() == "SwMsgPoolItem")
+        return true;
+    if (!decl->hasDefinition()) {
+        return false;
+    }
+    if (// not sure what hasAnyDependentBases() does,
+        // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1
+        !decl->hasAnyDependentBases() &&
+        !compat::forallBases(*decl, BaseCheckNotSwMsgPoolItemSubclass, nullptr, true)) {
+        return true;
+    }
+    return false;
+}
+
+bool endsWith(const string& a, const string& b) {
+    if (b.size() > a.size()) return false;
+    return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
+}
+
+bool SfxPoolItem::VisitCXXRecordDecl(const CXXRecordDecl* decl)
+{
+    if (ignoreLocation(decl)) {
+       return true;
+    }
+    if (!decl->hasDefinition()) {
+       return true;
+    }
+    // check if this class is derived from Window
+    if (!isDerivedFromSfxPoolItem(decl)) {
+        return true;
+    }
+    // the SwMsgPoolItem are some sort of hack to transport down-castable objects to SwClient::Modify(), they're not "real" items
+    if (isDerivedFromSwMsgPoolItem(decl)) {
+        return true;
+    }
+    if (decl->field_begin() == decl->field_end()) {
+        return true;
+    }
+    // the enum types do some weird stuff involving SfxEnumItemInterface
+    std::string sRecordName = decl->getQualifiedNameAsString();
+    if (sRecordName == "SfxEnumItem" || sRecordName == "SfxAllEnumItem")
+        return true;
+
+    // the new field is only used for reading and writing to storage
+    if (sRecordName == "SvxCharSetColorItem")
+        return true;
+
+    for (auto it = decl->method_begin(); it != decl->method_end(); ++it) {
+        if ( endsWith((*it)->getQualifiedNameAsString(), "::operator==") )
+            return true;
+    }
+    report(
+            DiagnosticsEngine::Warning,
+            "SfxPoolItem subclass %0 declares new fields, but does not overide operator==",
+            decl->getLocStart())
+        << decl->getQualifiedNameAsString() << decl->getSourceRange();
+    return true;
+}
+
+
+
+loplugin::Plugin::Registration< SfxPoolItem > X("sfxpoolitem");
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/items/paraitem.cxx b/editeng/source/items/paraitem.cxx
index 061bf02..0b43f54 100644
--- a/editeng/source/items/paraitem.cxx
+++ b/editeng/source/items/paraitem.cxx
@@ -1273,6 +1273,14 @@ bool SvxPageModelItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId
     return bRet;
 }
 
+bool SvxPageModelItem::operator==( const SfxPoolItem& rAttr ) const
+{
+    DBG_ASSERT( SfxPoolItem::operator==(rAttr), "unequal types" );
+
+    return SfxStringItem::operator==(rAttr) &&
+           bAuto == static_cast<const SvxPageModelItem&>( rAttr ).bAuto;
+}
+
 bool SvxPageModelItem::GetPresentation
 (
     SfxItemPresentation ePres,
diff --git a/include/editeng/pmdlitem.hxx b/include/editeng/pmdlitem.hxx
index 4a0e4ee..423a06b 100644
--- a/include/editeng/pmdlitem.hxx
+++ b/include/editeng/pmdlitem.hxx
@@ -51,6 +51,7 @@ public:
 
     virtual bool            QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override;
     virtual bool            PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) override;
+    virtual bool            operator==( const SfxPoolItem& ) const override;
 };
 
 inline SvxPageModelItem::SvxPageModelItem( sal_uInt16 nWh )


More information about the Libreoffice-commits mailing list